From e9e2a24377325cd9263627c1830576916917c447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=90=E1=85=A2=E1=84=92=E1=85=AE?= =?UTF-8?q?=E1=86=AB?= Date: Thu, 11 Jul 2024 15:05:30 +0900 Subject: [PATCH 001/273] =?UTF-8?q?chore:=20webpack,=20react,=20typescript?= =?UTF-8?q?=20=ED=99=98=EA=B2=BD=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 --- client/.gitignore | 10 + client/.gitkeep | 0 client/index.html | 11 + client/package-lock.json | 5143 ++++++++++++++++++++++++++++++++++++++ client/package.json | 28 + client/src/App.tsx | 9 + client/src/index.tsx | 9 + client/tsconfig.json | 44 + client/webpack.config.js | 38 + 9 files changed, 5292 insertions(+) create mode 100644 client/.gitignore delete mode 100644 client/.gitkeep create mode 100644 client/index.html create mode 100644 client/package-lock.json create mode 100644 client/package.json create mode 100644 client/src/App.tsx create mode 100644 client/src/index.tsx create mode 100644 client/tsconfig.json create mode 100644 client/webpack.config.js diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 000000000..b20b2e92f --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,10 @@ +logs +*.log +npm-debug.log* + +node_modules +dist + +.env + +*storybook.log diff --git a/client/.gitkeep b/client/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/index.html b/client/index.html new file mode 100644 index 000000000..77aaf80a0 --- /dev/null +++ b/client/index.html @@ -0,0 +1,11 @@ + + + + + + 행동대장 + + +
+ + diff --git a/client/package-lock.json b/client/package-lock.json new file mode 100644 index 000000000..249f0c13e --- /dev/null +++ b/client/package-lock.json @@ -0,0 +1,5143 @@ +{ + "name": "haengdong-client", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "haengdong-client", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "ts-loader": "^9.5.1", + "typescript": "^5.5.3", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", + "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.2.0.tgz", + "integrity": "sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "peer": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true, + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "peer": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peer": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001641", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz", + "integrity": "sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "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, + "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-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.824", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.824.tgz", + "integrity": "sha512-GTQnZOP1v0wCuoWzKOxL8rurg9T13QRYISkoICGaZzskBf9laC3V8g9BHTpJv+j9vBRcKOulbGXwMzuzNdVrAA==", + "dev": true, + "peer": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "peer": true + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "peer": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "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 + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "peer": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "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, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz", + "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==", + "dev": true, + "dependencies": { + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/html-loader/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/html-loader/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/html-loader/node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/launch-editor": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", + "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", + "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", + "dev": true, + "dependencies": { + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.1.2", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "peer": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true, + "peer": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "dev": true, + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "peer": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.9.tgz", + "integrity": "sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "14 >=14.20 || 16 >=16.20 || >=18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/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 + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "peer": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.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, + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy-transport/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.31.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", + "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "peer": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webpack": { + "version": "5.92.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz", + "integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==", + "dev": true, + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz", + "integrity": "sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.6.0", + "mime-types": "^2.1.31", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/client/package.json b/client/package.json new file mode 100644 index 000000000..3f0fd4175 --- /dev/null +++ b/client/package.json @@ -0,0 +1,28 @@ +{ + "name": "haengdong-client", + "version": "1.0.0", + "description": "", + "type": "module", + "scripts": { + "start": "webpack serve ", + "build": "webpack --mode production" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "ts-loader": "^9.5.1", + "typescript": "^5.5.3", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + } +} diff --git a/client/src/App.tsx b/client/src/App.tsx new file mode 100644 index 000000000..243a74f3c --- /dev/null +++ b/client/src/App.tsx @@ -0,0 +1,9 @@ +const App: React.FC = () =>{ + return( +
+ Hello, React with Webpack +
+ ); +} + +export default App; diff --git a/client/src/index.tsx b/client/src/index.tsx new file mode 100644 index 000000000..c018515cd --- /dev/null +++ b/client/src/index.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/client/tsconfig.json b/client/tsconfig.json new file mode 100644 index 000000000..5dfba11d7 --- /dev/null +++ b/client/tsconfig.json @@ -0,0 +1,44 @@ +{ + "compilerOptions": { + "sourceMap": true, + "module": "ES2020", + "target": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "useDefineForClassFields": true, + "removeComments": true, + "skipLibCheck": true, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + "types": ["jest"], + "esModuleInterop": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitAny": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + + "baseUrl": "./", + "paths": { + "components/*": [ + "src/components/*" + ], + }, + "outDir": "./dist" + }, + "include": ["src"], +} \ No newline at end of file diff --git a/client/webpack.config.js b/client/webpack.config.js new file mode 100644 index 000000000..9cc915a78 --- /dev/null +++ b/client/webpack.config.js @@ -0,0 +1,38 @@ +import path from "path"; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default { + mode: 'development', + entry: "./src/index.tsx", + resolve: { + extensions: [".js", ".jsx", ".ts", ".tsx"], + }, + output: { + path: path.join(__dirname, "dist"), + filename: "bundle.min.js", + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'ts-loader', + exclude: /node_modules/, + } + ] + }, + plugins: [ + new HtmlWebpackPlugin({ + template: "./index.html" + }), + new ForkTsCheckerWebpackPlugin(), + ], + devServer: { + port: 3000, + hot: true, + } +} \ No newline at end of file From dff70d7bee4c2d5c8d9b9a005dd78a4d8ceb28ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=90=E1=85=A2=E1=84=92=E1=85=AE?= =?UTF-8?q?=E1=86=AB?= Date: Thu, 11 Jul 2024 16:47:41 +0900 Subject: [PATCH 002/273] =?UTF-8?q?chore:=20eslint,=20prettier=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: JinHo Kim Co-authored-by: Pakxe --- client/.eslintrc.json | 87 + client/.gitignore | 1 + client/.npmrc | 1 + client/.prettierrc | 13 + client/index.html | 2 +- client/package-lock.json | 4110 +++++++++++++++++++++++++++++++------- client/package.json | 26 +- client/src/App.tsx | 10 +- client/src/index.tsx | 6 +- client/tsconfig.json | 80 +- client/webpack.config.js | 24 +- 11 files changed, 3548 insertions(+), 812 deletions(-) create mode 100644 client/.eslintrc.json create mode 100644 client/.npmrc create mode 100644 client/.prettierrc diff --git a/client/.eslintrc.json b/client/.eslintrc.json new file mode 100644 index 000000000..035405363 --- /dev/null +++ b/client/.eslintrc.json @@ -0,0 +1,87 @@ +{ + "extends": [ + "airbnb", + "airbnb/hooks", + "eslint:recommended", + "plugin:react/recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended", + // "plugin:storybook/recommended", + "plugin:import/typescript", + "plugin:import/recommended", + "plugin:import/errors", + "plugin:import/warnings", + "prettier", // Prettier 설정을 ESLint에 추가 + "plugin:prettier/recommended" // + ], + "parser": "@typescript-eslint/parser", + "plugins": ["react", "@typescript-eslint", "import", "prettier"], + "rules": { + "prettier/prettier": "error", + "react/react-in-jsx-scope": "off", + "react/prop-types": "off", + "react/jsx-uses-vars": "error", + "@typescript-eslint/no-use-before-define": ["error"], + "@typescript-eslint/explicit-module-boundary-types": "error", + "import/order": [ + "error", + { + "newlines-between": "always", + "groups": ["type", "builtin", "external", "internal", "parent", "sibling", "index", "unknown"], + "pathGroups": [ + { + "pattern": "react*", + "group": "external", + "position": "before" + }, + { + "pattern": "@hooks/*", + "group": "internal", + "position": "after" + }, + { + "pattern": "@apis/*", + "group": "internal", + "position": "after" + }, + { + "pattern": "@pages/*", + "group": "internal", + "position": "after" + }, + { + "pattern": "@components/*", + "group": "internal", + "position": "after" + }, + { + "pattern": "@assets/*", + "group": "internal", + "position": "after" + }, + { + "pattern": "@utils/*", + "group": "internal", + "position": "after" + }, + { + "pattern": "@constants/*", + "group": "internal", + "position": "after" + } + ] + } + ] + }, + "settings": { + "import/resolver": { + "node": { + "extensions": [".js", ".jsx", ".ts", ".tsx"] + }, + "typescript": { + "directory": "./src" + } + }, + "import/parsers": {"@typescript-eslint/parser": [".ts", ".tsx"]} + } +} diff --git a/client/.gitignore b/client/.gitignore index b20b2e92f..afd0485d1 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -8,3 +8,4 @@ dist .env *storybook.log +.DS_Store diff --git a/client/.npmrc b/client/.npmrc new file mode 100644 index 000000000..d1cdf2f06 --- /dev/null +++ b/client/.npmrc @@ -0,0 +1 @@ +engine-strict = true \ No newline at end of file diff --git a/client/.prettierrc b/client/.prettierrc new file mode 100644 index 000000000..fce76bb96 --- /dev/null +++ b/client/.prettierrc @@ -0,0 +1,13 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "jsxSingleQuote": false, + "bracketSpacing": false, + "proseWrap": "preserve", + "useTabs": true +} \ No newline at end of file diff --git a/client/index.html b/client/index.html index 77aaf80a0..05702360a 100644 --- a/client/index.html +++ b/client/index.html @@ -1,4 +1,4 @@ - + diff --git a/client/package-lock.json b/client/package-lock.json index 249f0c13e..bd52102a9 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,18 +10,36 @@ "license": "ISC", "dependencies": { "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" }, "devDependencies": { + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "eslint": "^9.6.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^4.6.2", "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", + "prettier": "3.3.2", "ts-loader": "^9.5.1", "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.4" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" } }, "node_modules/@babel/code-frame": { @@ -132,6 +150,222 @@ "node": ">=10.0.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", + "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.0.tgz", + "integrity": "sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", + "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -294,6 +528,41 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "dev": true }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -304,6 +573,26 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", + "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@types/body-parser": { "version": "1.19.5", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", @@ -342,35 +631,6 @@ "@types/node": "*" } }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", - "dev": true, - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "peer": true - }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -422,6 +682,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -537,165 +803,258 @@ "@types/node": "*" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", "dev": true, - "peer": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", "dev": true, - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", "dev": true, - "peer": true, "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, - "peer": true, "dependencies": { - "@xtuc/long": "4.2.2" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "node_modules/@typescript-eslint/parser": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", + "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", "dev": true, - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", "dev": true, - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", "dev": true, - "peer": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" + "@typescript-eslint/types": "7.16.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, "node_modules/@webpack-cli/configtest": { @@ -742,20 +1101,6 @@ } } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "peer": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "peer": true - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -781,14 +1126,13 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, - "peer": true, "peerDependencies": { - "acorn": "^8" + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/ajv": { @@ -910,12 +1254,231 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "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": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "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, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "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, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", + "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1010,39 +1573,6 @@ "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -1111,27 +1641,6 @@ "tslib": "^2.0.3" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001641", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz", - "integrity": "sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1184,16 +1693,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0" - } - }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -1417,15 +1916,116 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "dev": true }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -1504,6 +2104,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1529,6 +2146,18 @@ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -1541,6 +2170,18 @@ "node": ">=6" } }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -1627,13 +2268,6 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true }, - "node_modules/electron-to-chromium": { - "version": "1.4.824", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.824.tgz", - "integrity": "sha512-GTQnZOP1v0wCuoWzKOxL8rurg9T13QRYISkoICGaZzskBf9laC3V8g9BHTpJv+j9vBRcKOulbGXwMzuzNdVrAA==", - "dev": true, - "peer": true - }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -1692,6 +2326,66 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", @@ -1713,21 +2407,107 @@ "node": ">= 0.4" } }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", "dev": true, - "peer": true + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", "dev": true, - "peer": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "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, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/escape-html": { @@ -1745,116 +2525,687 @@ "node": ">=0.8.0" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "node_modules/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/config-array": "^0.17.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.6.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.0.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=8.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, - "peer": true, "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "peer": true, - "engines": { - "node": ">=4.0" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "node_modules/eslint-import-resolver-node/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 + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, - "peer": true, + "dependencies": { + "debug": "^3.2.7" + }, "engines": { - "node": ">=4.0" + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "engines": { - "node": ">= 0.6" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "node_modules/eslint-module-utils/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 }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "peer": true, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "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.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, "engines": { - "node": ">=0.8.x" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/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 + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz", + "integrity": "sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.hasown": "^1.1.4", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", + "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", @@ -1888,12 +3239,40 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -1903,6 +3282,15 @@ "node": ">= 4.9.1" } }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/faye-websocket": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", @@ -1915,6 +3303,18 @@ "node": ">=0.8.0" } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -1967,6 +3367,25 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", @@ -1987,6 +3406,15 @@ } } }, + "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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/foreground-child": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", @@ -2138,6 +3566,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -2169,6 +3624,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -2201,12 +3673,53 @@ "node": ">= 6" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "node_modules/globals": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", + "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "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, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, - "peer": true + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/gopd": { "version": "1.0.1", @@ -2226,12 +3739,27 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, + "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==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2277,6 +3805,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -2505,189 +4048,537 @@ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", "dev": true }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", "dev": true, "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "hasown": "^2.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "is-typed-array": "^1.1.13" }, "engines": { - "node": ">=8.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "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==", "dev": true, "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, + "bin": { + "is-docker": "cli.js" + }, "engines": { - "node": ">=10.17.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hyperdyperid": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", - "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { - "node": ">=10.18" + "node": ">=0.10.0" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "call-bind": "^1.0.2" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" + "is-docker": "^3.0.0" }, "bin": { - "import-local-fixture": "fixtures/cli.js" + "is-inside-container": "cli.js" }, "engines": { - "node": ">=8" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { - "node": ">=10.13.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", "dev": true, "engines": { - "node": ">= 10" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "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==", "dev": true, "dependencies": { - "binary-extensions": "^2.0.0" + "has-tostringtag": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "dependencies": { - "hasown": "^2.0.2" + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -2696,124 +4587,128 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "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, - "bin": { - "is-docker": "cli.js" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "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==", "dev": true, "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" + "has-symbols": "^1.0.2" }, "engines": { - "node": ">=14.16" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-network-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, "engines": { - "node": ">=16" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "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, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "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==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "call-bind": "^1.0.2" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-wsl": { @@ -2852,6 +4747,19 @@ "node": ">=0.10.0" } }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", @@ -2867,21 +4775,6 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "peer": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2899,6 +4792,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -2911,6 +4810,24 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -2923,6 +4840,30 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -2932,6 +4873,24 @@ "node": ">=0.10.0" } }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/launch-editor": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", @@ -2942,22 +4901,25 @@ "shell-quote": "^1.8.1" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.11.5" - } - }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -2976,6 +4938,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3042,6 +5010,15 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -3127,6 +5104,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -3155,6 +5141,12 @@ "multicast-dns": "cli.js" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -3164,13 +5156,6 @@ "node": ">= 0.6" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "peer": true - }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -3196,13 +5181,6 @@ "node": ">= 6.13.0" } }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true, - "peer": true - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3218,29 +5196,161 @@ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/object.hasown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", "dev": true, "dependencies": { - "boolbase": "^1.0.0" + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -3308,6 +5418,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -3535,6 +5662,51 @@ "node": ">=8" } }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -3551,6 +5723,17 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3597,15 +5780,25 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "peer": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/range-parser": { "version": "1.2.1", @@ -3663,6 +5856,42 @@ "react": "^18.3.1" } }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/react-router": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", + "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", + "dependencies": { + "@remix-run/router": "1.17.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", + "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", + "dependencies": { + "@remix-run/router": "1.17.1", + "react-router": "6.24.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -3701,6 +5930,45 @@ "node": ">= 10.13.0" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -3785,6 +6053,16 @@ "node": ">= 4" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "5.0.9", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.9.tgz", @@ -3815,6 +6093,53 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3835,6 +6160,23 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -3928,16 +6270,6 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -4033,6 +6365,21 @@ "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, + "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/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -4105,6 +6452,15 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -4220,6 +6576,18 @@ "node": ">= 0.8" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4291,7 +6659,92 @@ "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "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", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "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, + "dependencies": { + "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" } }, "node_modules/strip-ansi": { @@ -4319,6 +6772,15 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -4328,20 +6790,16 @@ "node": ">=6" } }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -4356,6 +6814,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -4383,40 +6857,11 @@ "node": ">=10" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, "node_modules/thingies": { "version": "1.21.0", @@ -4473,6 +6918,18 @@ "tslib": "2" } }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/ts-loader": { "version": "9.5.1", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", @@ -4502,12 +6959,36 @@ "node": ">= 8" } }, + "node_modules/tsconfig-paths": { + "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, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "dev": true }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -4521,6 +7002,79 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", @@ -4534,6 +7088,69 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", + "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.16.0", + "@typescript-eslint/parser": "7.16.0", + "@typescript-eslint/utils": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -4558,37 +7175,6 @@ "node": ">= 0.8" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4637,20 +7223,6 @@ "node": ">= 0.8" } }, - "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", - "dev": true, - "peer": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/wbuf": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", @@ -4660,54 +7232,6 @@ "minimalistic-assert": "^1.0.0" } }, - "node_modules/webpack": { - "version": "5.92.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz", - "integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==", - "dev": true, - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, "node_modules/webpack-cli": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", @@ -4970,16 +7494,6 @@ "node": ">=10.0.0" } }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -5018,12 +7532,106 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "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.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -5138,6 +7746,18 @@ "optional": true } } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/client/package.json b/client/package.json index 3f0fd4175..7546cdc62 100644 --- a/client/package.json +++ b/client/package.json @@ -5,24 +5,44 @@ "type": "module", "scripts": { "start": "webpack serve ", - "build": "webpack --mode production" + "build": "webpack --mode production", + "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", + "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "eslint": "^9.6.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^4.6.2", "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", + "prettier": "3.3.2", "ts-loader": "^9.5.1", "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.4" }, "dependencies": { "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "engines": { + "npm": ">=10.7.0", + "node": ">=20.15.1" } -} +} \ No newline at end of file diff --git a/client/src/App.tsx b/client/src/App.tsx index 243a74f3c..937325a99 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,9 +1,5 @@ -const App: React.FC = () =>{ - return( -
- Hello, React with Webpack -
- ); -} +const App: React.FC = () => { + return
Hello, React with Webpack
; +}; export default App; diff --git a/client/src/index.tsx b/client/src/index.tsx index c018515cd..e3791f790 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -3,7 +3,7 @@ import ReactDOM from 'react-dom/client'; import App from './App'; ReactDOM.createRoot(document.getElementById('root')!).render( - - - , + + + , ); diff --git a/client/tsconfig.json b/client/tsconfig.json index 5dfba11d7..c3bf098d3 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,44 +1,42 @@ { - "compilerOptions": { - "sourceMap": true, - "module": "ES2020", - "target": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "useDefineForClassFields": true, - "removeComments": true, - "skipLibCheck": true, - - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - - "jsx": "react-jsx", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, + "compilerOptions": { + "sourceMap": true, + "module": "ES2020", + "target": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "useDefineForClassFields": true, + "removeComments": true, + "skipLibCheck": true, - "types": ["jest"], - "esModuleInterop": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictBindCallApply": true, - "strictPropertyInitialization": true, - "noImplicitAny": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noImplicitReturns": true, - "forceConsistentCasingInFileNames": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, - "baseUrl": "./", - "paths": { - "components/*": [ - "src/components/*" - ], - }, - "outDir": "./dist" - }, - "include": ["src"], -} \ No newline at end of file + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + "types": ["jest"], + "esModuleInterop": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitAny": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + + "baseUrl": "./", + "paths": { + "components/*": ["src/components/*"] + }, + "outDir": "./dist" + }, + "include": ["src"] +} diff --git a/client/webpack.config.js b/client/webpack.config.js index 9cc915a78..03798e534 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -1,38 +1,38 @@ import path from "path"; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; -import { fileURLToPath } from 'url'; +import HtmlWebpackPlugin from "html-webpack-plugin"; +import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin"; +import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export default { - mode: 'development', + mode: "development", entry: "./src/index.tsx", resolve: { extensions: [".js", ".jsx", ".ts", ".tsx"], }, - output: { + output: { path: path.join(__dirname, "dist"), filename: "bundle.min.js", }, module: { rules: [ - { + { test: /\.tsx?$/, - loader: 'ts-loader', + loader: "ts-loader", exclude: /node_modules/, - } - ] + }, + ], }, plugins: [ new HtmlWebpackPlugin({ - template: "./index.html" + template: "./index.html", }), new ForkTsCheckerWebpackPlugin(), ], devServer: { port: 3000, hot: true, - } -} \ No newline at end of file + }, +}; From 29a0a46e7d454756618f79c0a15fa819bea5817d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=90=E1=85=A2=E1=84=92=E1=85=AE?= =?UTF-8?q?=E1=86=AB?= Date: Thu, 11 Jul 2024 17:25:53 +0900 Subject: [PATCH 003/273] =?UTF-8?q?docs:=20pr=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=20=EB=B0=8F=20issue=20=ED=85=9C=ED=94=8C=EB=A6=BF=20?= =?UTF-8?q?=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 --- .github/ISSUE_TEMPLATE/bug-template.md | 10 ++++++++++ .github/ISSUE_TEMPLATE/feature-template.md | 9 +++++++++ .github/pull-request-template.md | 13 +++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-template.md create mode 100644 .github/ISSUE_TEMPLATE/feature-template.md create mode 100644 .github/pull-request-template.md diff --git a/.github/ISSUE_TEMPLATE/bug-template.md b/.github/ISSUE_TEMPLATE/bug-template.md new file mode 100644 index 000000000..1a8d6a0d0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-template.md @@ -0,0 +1,10 @@ +## 📄 버그 내용 +어떤 버그인지 간결하게 설명해주세요. + +## 🚨 버그 발생 상황 +최대한 상세하게 작성해주세요. + +## 예상 결과 +예상했던 정상적인 결과가 어떤 것인지 설명해주세요. + +## 🫡 참고사항 diff --git a/.github/ISSUE_TEMPLATE/feature-template.md b/.github/ISSUE_TEMPLATE/feature-template.md new file mode 100644 index 000000000..76b8b47be --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-template.md @@ -0,0 +1,9 @@ +## 📄 설명 + +추가하려는 기능에 대해 간결하게 설명해주세요. + +## 🏁 할 일 + +- [ ] 예상되는 작업을 상세하게 작성해주세요. (checkBox 형태로 작성해주세요.) + +## 🫡 참고사항 diff --git a/.github/pull-request-template.md b/.github/pull-request-template.md new file mode 100644 index 000000000..863663bb0 --- /dev/null +++ b/.github/pull-request-template.md @@ -0,0 +1,13 @@ +## issue +- close #n + +## 구현 사항 +어떤 것을 구현했는지 필요히다면 사진 || 영상과 함께 자세히 설명해주세요. + +## 중점적으로 리뷰받고 싶은 부분(선택) +어떤 부분을 중점으로 리뷰했으면 좋겠는지 작성해주세요. + +## 논의하고 싶은 부분(선택) +논의하고 싶은 부분이 있다면 작성해주세요. + +## 🫡 참고사항 From 4ac4d93f0ecd5005b07927e424c4a48c383244d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=90=E1=85=A2=E1=84=92=E1=85=AE?= =?UTF-8?q?=E1=86=AB?= Date: Thu, 11 Jul 2024 17:47:30 +0900 Subject: [PATCH 004/273] =?UTF-8?q?docs:=20issue=20=ED=85=9C=ED=94=8C?= =?UTF-8?q?=EB=A6=BF=EC=97=90=20=ED=83=80=EC=9D=B4=ED=8B=80=EA=B3=BC=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=EB=90=9C=20=EB=B6=80=EA=B0=80=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 --- .github/ISSUE_TEMPLATE/bug-template.md | 8 ++++++++ .github/ISSUE_TEMPLATE/feature-template.md | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug-template.md b/.github/ISSUE_TEMPLATE/bug-template.md index 1a8d6a0d0..e14ce93b3 100644 --- a/.github/ISSUE_TEMPLATE/bug-template.md +++ b/.github/ISSUE_TEMPLATE/bug-template.md @@ -1,3 +1,11 @@ +--- +name: Bug Template +about: 버그를 제보하는 템플릿 +title: "" +labels: 🚨bug +assignees: '' +--- + ## 📄 버그 내용 어떤 버그인지 간결하게 설명해주세요. diff --git a/.github/ISSUE_TEMPLATE/feature-template.md b/.github/ISSUE_TEMPLATE/feature-template.md index 76b8b47be..d29aa8e98 100644 --- a/.github/ISSUE_TEMPLATE/feature-template.md +++ b/.github/ISSUE_TEMPLATE/feature-template.md @@ -1,3 +1,11 @@ +--- +name: Feature Template +about: 기능에 관한 템플릿 +title: "" +labels: ⚙️ feat +assignees: '' +--- + ## 📄 설명 추가하려는 기능에 대해 간결하게 설명해주세요. From c4a8dc16ae255273e4b1ecae8fbd7f2122ed6c80 Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 20:34:38 +0900 Subject: [PATCH 005/273] =?UTF-8?q?chore:=20=EB=AA=A8=EB=93=A0=20install?= =?UTF-8?q?=20=EC=97=90=20legacy-peer-deps=EB=A5=BC=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari --- client/.npmrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/.npmrc b/client/.npmrc index d1cdf2f06..ece05f588 100644 --- a/client/.npmrc +++ b/client/.npmrc @@ -1 +1,2 @@ -engine-strict = true \ No newline at end of file +engine-strict = true +legacy-peer-deps = true From 404c8c525b91a718c89e20405aededa4b31364bf Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 20:35:38 +0900 Subject: [PATCH 006/273] =?UTF-8?q?chore:=20emotion=20css=20props=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EC=98=88=EC=A0=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari --- client/src/App.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/src/App.tsx b/client/src/App.tsx index 937325a99..b5b756a36 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,5 +1,12 @@ +import {css} from '@emotion/react'; + +// 테스트 css props 사용 예제입니다. 추후 삭제 예정 +const style = css` + color: red; +`; + const App: React.FC = () => { - return
Hello, React with Webpack
; + return
Hello, React with Webpack
; }; export default App; From 6eb4bb5ec624c070ebfc7eb9066819336fa9587a Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 20:36:39 +0900 Subject: [PATCH 007/273] =?UTF-8?q?chore:=20webpack,=20@emotion/react=20?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=84=A4?= =?UTF-8?q?=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari --- client/package-lock.json | 16390 +++++++++++++++++++------------------ client/package.json | 96 +- 2 files changed, 8678 insertions(+), 7808 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index bd52102a9..aced154c7 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,7763 +1,8631 @@ { - "name": "haengdong-client", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "haengdong-client", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" - }, - "devDependencies": { - "@eslint/compat": "^1.1.0", - "@eslint/js": "^9.6.0", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "eslint": "^9.6.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.3", - "eslint-plugin-react-hooks": "^4.6.2", - "fork-ts-checker-webpack-plugin": "^9.0.2", - "globals": "^15.8.0", - "html-loader": "^5.0.0", - "html-webpack-plugin": "^5.6.0", - "prettier": "3.3.2", - "ts-loader": "^9.5.1", - "typescript": "^5.5.3", - "typescript-eslint": "^7.16.0", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.0.4" - }, - "engines": { - "node": ">=20.15.1", - "npm": ">=10.7.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/compat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", - "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.0.tgz", - "integrity": "sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==", - "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", - "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", - "dev": true, - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@jsonjoy.com/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/json-pack": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", - "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", - "dev": true, - "dependencies": { - "@jsonjoy.com/base64": "^1.1.1", - "@jsonjoy.com/util": "^1.1.2", - "hyperdyperid": "^1.2.0", - "thingies": "^1.20.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/util": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.2.0.tgz", - "integrity": "sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "dev": true - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@remix-run/router": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", - "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dev": true, - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.14", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", - "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "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": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "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, - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "node_modules/available-typed-arrays": { - "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, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", - "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "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, - "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-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "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, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "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, - "dependencies": { - "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==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.6.0.tgz", - "integrity": "sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/config-array": "^0.17.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.6.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-node/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 - }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils/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 - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "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.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/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 - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", - "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", - "dev": true, - "dependencies": { - "aria-query": "~5.1.3", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.9.1", - "axobject-query": "~3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.19", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.34.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz", - "integrity": "sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.hasown": "^1.1.4", - "object.values": "^1.2.0", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-react/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, - "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "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 - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": 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==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", - "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^8.2.0", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">=12.13.0", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "typescript": ">3.6.0", - "webpack": "^5.11.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", - "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "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, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "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==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "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, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "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, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] - }, - "node_modules/html-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz", - "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==", - "dev": true, - "dependencies": { - "html-minifier-terser": "^7.2.0", - "parse5": "^7.1.2" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/html-loader/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/html-loader/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/html-loader/node_modules/html-minifier-terser": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", - "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "~5.3.2", - "commander": "^10.0.0", - "entities": "^4.4.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.15.1" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - } - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/hyperdyperid": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", - "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", - "dev": true, - "engines": { - "node": ">=10.18" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.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==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "dependencies": { - "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==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.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", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-network-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/launch-editor": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", - "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", - "dev": true, - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", - "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", - "dev": true, - "dependencies": { - "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.1.2", - "tree-dump": "^1.0.1", - "tslib": "^2.0.0" - }, - "engines": { - "node": ">= 4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "dev": true - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.hasown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", - "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "dependencies": { - "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" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", - "dev": true, - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-retry": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", - "dev": true, - "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", - "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", - "dev": true - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/react-router": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", - "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", - "dependencies": { - "@remix-run/router": "1.17.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", - "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", - "dependencies": { - "@remix-run/router": "1.17.1", - "react-router": "6.24.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.9.tgz", - "integrity": "sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "14 >=14.20 || 16 >=16.20 || >=18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/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 - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.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, - "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, - "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/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/spdy-transport/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/spdy-transport/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/spdy/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/spdy/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", - "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", - "dev": true, - "dependencies": { - "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", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", - "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "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, - "dependencies": { - "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" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.31.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", - "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/thingies": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", - "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", - "dev": true, - "engines": { - "node": ">=10.18" - }, - "peerDependencies": { - "tslib": "^2" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tree-dump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", - "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4", - "source-map": "^0.7.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-loader/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tsconfig-paths": { - "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, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", - "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", - "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "7.16.0", - "@typescript-eslint/parser": "7.16.0", - "@typescript-eslint/utils": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz", - "integrity": "sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^4.6.0", - "mime-types": "^2.1.31", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-dev-server": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", - "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.4.0", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "rimraf": "^5.0.5", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.1.0", - "ws": "^8.16.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack-dev-server/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "dependencies": { - "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.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } + "name": "haengdong-client", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "haengdong-client", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@emotion/react": "^11.11.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "devDependencies": { + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "eslint": "^9.6.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^4.6.2", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "prettier": "3.3.2", + "ts-loader": "^9.5.1", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", + "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", + "dependencies": { + "@babel/types": "^7.24.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", + "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", + "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.8", + "@babel/types": "^7.24.8", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/types": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "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", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "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==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "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==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", + "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.0.tgz", + "integrity": "sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", + "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", + "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.2.0.tgz", + "integrity": "sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", + "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", + "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "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": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "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, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "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, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", + "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "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, + "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-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.827", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", + "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "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, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/config-array": "^0.17.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.6.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.0.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/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 + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/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 + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "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.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/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 + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz", + "integrity": "sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.hasown": "^1.1.4", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", + "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "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 + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": 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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/globals": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", + "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "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, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "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==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "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, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz", + "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==", + "dev": true, + "dependencies": { + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/html-loader/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/html-loader/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/html-loader/node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/launch-editor": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", + "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", + "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", + "dev": true, + "dependencies": { + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.1.2", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.hasown": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", + "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "dev": true, + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-router": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", + "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", + "dependencies": { + "@remix-run/router": "1.17.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", + "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", + "dependencies": { + "@remix-run/router": "1.17.1", + "react-router": "6.24.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.9.tgz", + "integrity": "sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "14 >=14.20 || 16 >=16.20 || >=18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/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 + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.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, + "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, + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy-transport/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "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", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "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, + "dependencies": { + "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" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.31.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", + "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tsconfig-paths": { + "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, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", + "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.16.0", + "@typescript-eslint/parser": "7.16.0", + "@typescript-eslint/utils": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webpack": { + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz", + "integrity": "sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.6.0", + "mime-types": "^2.1.31", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "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.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } } diff --git a/client/package.json b/client/package.json index 7546cdc62..d9717163d 100644 --- a/client/package.json +++ b/client/package.json @@ -1,48 +1,50 @@ { - "name": "haengdong-client", - "version": "1.0.0", - "description": "", - "type": "module", - "scripts": { - "start": "webpack serve ", - "build": "webpack --mode production", - "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", - "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "@eslint/compat": "^1.1.0", - "@eslint/js": "^9.6.0", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "eslint": "^9.6.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.3", - "eslint-plugin-react-hooks": "^4.6.2", - "fork-ts-checker-webpack-plugin": "^9.0.2", - "globals": "^15.8.0", - "html-loader": "^5.0.0", - "html-webpack-plugin": "^5.6.0", - "prettier": "3.3.2", - "ts-loader": "^9.5.1", - "typescript": "^5.5.3", - "typescript-eslint": "^7.16.0", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.0.4" - }, - "dependencies": { - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" - }, - "engines": { - "npm": ">=10.7.0", - "node": ">=20.15.1" - } -} \ No newline at end of file + "name": "haengdong-client", + "version": "1.0.0", + "description": "", + "type": "module", + "scripts": { + "start": "webpack serve ", + "build": "webpack --mode production", + "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", + "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "eslint": "^9.6.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^4.6.2", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "prettier": "3.3.2", + "ts-loader": "^9.5.1", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4" + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "engines": { + "npm": ">=10.7.0", + "node": ">=20.15.1" + } +} From 32f623ab3351ae2d2365f7750674da74441fa0ea Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 20:38:18 +0900 Subject: [PATCH 008/273] =?UTF-8?q?chore:=20css=20props=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=B4=20'js?= =?UTF-8?q?xImportSource'=20=EC=98=B5=EC=85=98=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari --- client/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/client/tsconfig.json b/client/tsconfig.json index c3bf098d3..6ecb17ef8 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -31,6 +31,7 @@ "alwaysStrict": true, "noImplicitReturns": true, "forceConsistentCasingInFileNames": true, + "jsxImportSource": "@emotion/react", "baseUrl": "./", "paths": { From a8515a59b83f2987cfc41dba766ec963a68b6e5d Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 20:39:13 +0900 Subject: [PATCH 009/273] =?UTF-8?q?chore:=20css=20props=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20=EC=9C=84=ED=95=B4=20=EB=AA=A8=EB=93=A0=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B5=9C=EC=83=81=EB=8B=A8=EC=97=90=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=EC=9D=84=20=EC=9E=90=EB=8F=99=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=ED=95=B4=EC=A3=BC=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=ED=94=8C=EB=9F=AC=EA=B7=B8=EC=9D=B8=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari --- client/webpack.config.js | 73 ++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/client/webpack.config.js b/client/webpack.config.js index 03798e534..9dd8ce0fb 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -1,38 +1,47 @@ -import path from "path"; -import HtmlWebpackPlugin from "html-webpack-plugin"; -import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin"; -import { fileURLToPath } from "url"; +import path from 'path'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import {ModifySourcePlugin, ConcatOperation} from 'modify-source-webpack-plugin'; +import {fileURLToPath} from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); export default { - mode: "development", - entry: "./src/index.tsx", - resolve: { - extensions: [".js", ".jsx", ".ts", ".tsx"], - }, - output: { - path: path.join(__dirname, "dist"), - filename: "bundle.min.js", - }, - module: { - rules: [ - { - test: /\.tsx?$/, - loader: "ts-loader", - exclude: /node_modules/, - }, - ], - }, - plugins: [ - new HtmlWebpackPlugin({ - template: "./index.html", - }), - new ForkTsCheckerWebpackPlugin(), - ], - devServer: { - port: 3000, - hot: true, - }, + mode: 'development', + entry: './src/index.tsx', + resolve: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + output: { + path: path.join(__dirname, 'dist'), + filename: 'bundle.min.js', + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, + plugins: [ + new HtmlWebpackPlugin({ + template: './index.html', + }), + new ForkTsCheckerWebpackPlugin(), + new ModifySourcePlugin({ + rules: [ + { + test: /\.tsx$/i, + operations: [new ConcatOperation('start', '/** @jsxImportSource @emotion/react */\n\n')], + }, + ], + }), + ], + devServer: { + port: 3001, + hot: true, + }, }; From 80c352f660c2f4ae6ef04bef6908184e40758f41 Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 20:42:55 +0900 Subject: [PATCH 010/273] =?UTF-8?q?chore:=20=EA=B0=9C=EB=B0=9C=EC=84=9C?= =?UTF-8?q?=EB=B2=84=20=ED=8F=AC=ED=8A=B8=EB=B2=88=ED=98=B8=203001=20->=20?= =?UTF-8?q?3000=20=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari --- client/webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/webpack.config.js b/client/webpack.config.js index 9dd8ce0fb..9f355cf8f 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -41,7 +41,7 @@ export default { }), ], devServer: { - port: 3001, + port: 3000, hot: true, }, }; From c7cae03bb984636a7c205b65a9b082cbc9896415 Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 20:43:21 +0900 Subject: [PATCH 011/273] =?UTF-8?q?chore:=20prettier=EC=97=90=EC=84=9C=20u?= =?UTF-8?q?seTabs=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe , soi-ha , jinhokim98 , Todari --- client/.prettierrc | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/client/.prettierrc b/client/.prettierrc index fce76bb96..a661f29c2 100644 --- a/client/.prettierrc +++ b/client/.prettierrc @@ -1,13 +1,12 @@ { - "singleQuote": true, - "trailingComma": "all", - "printWidth": 120, - "tabWidth": 2, - "semi": true, - "arrowParens": "avoid", - "endOfLine": "auto", - "jsxSingleQuote": false, - "bracketSpacing": false, - "proseWrap": "preserve", - "useTabs": true -} \ No newline at end of file + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "jsxSingleQuote": false, + "bracketSpacing": false, + "proseWrap": "preserve" +} From 288718bf0be19924442dcf22069b542ef0d18444 Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 21:03:29 +0900 Subject: [PATCH 012/273] =?UTF-8?q?chore:=20=EC=97=AC=EB=9F=AC=20=EB=AA=85?= =?UTF-8?q?=EC=9D=B4=20co-authored-by=EB=A1=9C=20=EB=93=A4=EC=96=B4?= =?UTF-8?q?=EA=B0=88=20=EC=88=98=20=EC=9E=88=EB=8A=94=EC=A7=80=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari --- client/src/App.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/App.tsx b/client/src/App.tsx index b5b756a36..5a7e5f458 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,12 +1,13 @@ import {css} from '@emotion/react'; +// co-authored-by test // 테스트 css props 사용 예제입니다. 추후 삭제 예정 const style = css` - color: red; + color: red; `; const App: React.FC = () => { - return
Hello, React with Webpack
; + return
Hello, React with Webpack
; }; export default App; From 5fe7696d529f42c0cffe75ab7afd85e1c6de88be Mon Sep 17 00:00:00 2001 From: pakxe Date: Mon, 15 Jul 2024 21:04:18 +0900 Subject: [PATCH 013/273] =?UTF-8?q?chore:=20=EC=9E=84=EC=8B=9C=EB=A1=9C=20?= =?UTF-8?q?=EC=A7=80=EC=9B=A0=EB=8D=98=20types=20=EC=98=B5=EC=85=98?= =?UTF-8?q?=EC=9D=84=20=EB=8B=A4=EC=8B=9C=20=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari Co-authored-by: pakxe Co-authored-by: soi-ha Co-authored-by: jinhokim98 Co-authored-by: Todari --- client/tsconfig.json | 74 ++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/client/tsconfig.json b/client/tsconfig.json index 6ecb17ef8..be12e5cfb 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,43 +1,43 @@ { - "compilerOptions": { - "sourceMap": true, - "module": "ES2020", - "target": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "useDefineForClassFields": true, - "removeComments": true, - "skipLibCheck": true, + "compilerOptions": { + "sourceMap": true, + "module": "ES2020", + "target": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "useDefineForClassFields": true, + "removeComments": true, + "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, - "jsx": "react-jsx", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, - "types": ["jest"], - "esModuleInterop": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictBindCallApply": true, - "strictPropertyInitialization": true, - "noImplicitAny": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noImplicitReturns": true, - "forceConsistentCasingInFileNames": true, - "jsxImportSource": "@emotion/react", + "types": ["jest"], + "esModuleInterop": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitAny": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + "jsxImportSource": "@emotion/react", - "baseUrl": "./", - "paths": { - "components/*": ["src/components/*"] - }, - "outDir": "./dist" - }, - "include": ["src"] + "baseUrl": "./", + "paths": { + "components/*": ["src/components/*"] + }, + "outDir": "./dist" + }, + "include": ["src"] } From 748656c951bbc8162343f6aa9707bded3f186ab0 Mon Sep 17 00:00:00 2001 From: Soyeon Choe Date: Mon, 15 Jul 2024 22:41:03 +0900 Subject: [PATCH 014/273] =?UTF-8?q?chore:=20=EA=B8=B0=EB=B3=B8=20webpack?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> --- HDesign/.gitignore | 11 + HDesign/.npmrc | 2 + HDesign/.prettierrc | 12 + HDesign/.storybook/main.ts | 18 + HDesign/.storybook/preview.ts | 14 + HDesign/eslint.config.mjs | 127 + HDesign/package-lock.json | 15532 ++++++++++++++++++++++++++++++++ HDesign/package.json | 66 + HDesign/tsconfig.json | 43 + HDesign/webpack.config.js | 48 + 10 files changed, 15873 insertions(+) create mode 100644 HDesign/.gitignore create mode 100644 HDesign/.npmrc create mode 100644 HDesign/.prettierrc create mode 100644 HDesign/.storybook/main.ts create mode 100644 HDesign/.storybook/preview.ts create mode 100644 HDesign/eslint.config.mjs create mode 100644 HDesign/package-lock.json create mode 100644 HDesign/package.json create mode 100644 HDesign/tsconfig.json create mode 100644 HDesign/webpack.config.js diff --git a/HDesign/.gitignore b/HDesign/.gitignore new file mode 100644 index 000000000..afd0485d1 --- /dev/null +++ b/HDesign/.gitignore @@ -0,0 +1,11 @@ +logs +*.log +npm-debug.log* + +node_modules +dist + +.env + +*storybook.log +.DS_Store diff --git a/HDesign/.npmrc b/HDesign/.npmrc new file mode 100644 index 000000000..ece05f588 --- /dev/null +++ b/HDesign/.npmrc @@ -0,0 +1,2 @@ +engine-strict = true +legacy-peer-deps = true diff --git a/HDesign/.prettierrc b/HDesign/.prettierrc new file mode 100644 index 000000000..c025201f4 --- /dev/null +++ b/HDesign/.prettierrc @@ -0,0 +1,12 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "jsxSingleQuote": false, + "bracketSpacing": false, + "proseWrap": "preserve" +} diff --git a/HDesign/.storybook/main.ts b/HDesign/.storybook/main.ts new file mode 100644 index 000000000..dcdd7bf09 --- /dev/null +++ b/HDesign/.storybook/main.ts @@ -0,0 +1,18 @@ +import type {StorybookConfig} from '@storybook/react-webpack5'; + +const config: StorybookConfig = { + stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + '@storybook/addon-webpack5-compiler-swc', + '@storybook/addon-onboarding', + '@storybook/addon-links', + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/react-webpack5', + options: {}, + }, +}; +export default config; diff --git a/HDesign/.storybook/preview.ts b/HDesign/.storybook/preview.ts new file mode 100644 index 000000000..a66ea2ee6 --- /dev/null +++ b/HDesign/.storybook/preview.ts @@ -0,0 +1,14 @@ +import type {Preview} from '@storybook/react'; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/HDesign/eslint.config.mjs b/HDesign/eslint.config.mjs new file mode 100644 index 000000000..ea53f995c --- /dev/null +++ b/HDesign/eslint.config.mjs @@ -0,0 +1,127 @@ +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; + +import {fixupConfigRules, fixupPluginRules} from '@eslint/compat'; +import react from 'eslint-plugin-react'; +import typescriptEslint from '@typescript-eslint/eslint-plugin'; +import _import from 'eslint-plugin-import'; +import prettier from 'eslint-plugin-prettier'; +import tsParser from '@typescript-eslint/parser'; +import js from '@eslint/js'; +import {FlatCompat} from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [ + ...fixupConfigRules( + compat.extends( + 'airbnb', + 'airbnb/hooks', + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + 'plugin:import/typescript', + 'plugin:import/recommended', + 'plugin:import/errors', + 'plugin:import/warnings', + 'prettier', + 'plugin:prettier/recommended', + ), + ), + { + plugins: { + react: fixupPluginRules(react), + '@typescript-eslint': fixupPluginRules(typescriptEslint), + import: fixupPluginRules(_import), + prettier: fixupPluginRules(prettier), + }, + + languageOptions: { + parser: tsParser, + }, + + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + + typescript: { + directory: './lib', + }, + }, + + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + }, + + rules: { + 'prettier/prettier': 'error', + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + 'react/jsx-uses-vars': 'error', + '@typescript-eslint/no-use-before-define': ['error'], + '@typescript-eslint/explicit-module-boundary-types': 'error', + + 'import/order': [ + 'error', + { + 'newlines-between': 'always', + + groups: ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'], + + pathGroups: [ + { + pattern: 'react*', + group: 'external', + position: 'before', + }, + { + pattern: '@hooks/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@apis/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@pages/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@components/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@assets/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@utils/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@constants/*', + group: 'internal', + position: 'after', + }, + ], + }, + ], + }, + }, +]; diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json new file mode 100644 index 000000000..0d86a87a3 --- /dev/null +++ b/HDesign/package-lock.json @@ -0,0 +1,15532 @@ +{ + "name": "haengdong-design", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "haengdong-design", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@emotion/react": "^11.11.4", + "modify-source-webpack-plugin": "^4.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/addon-webpack5-compiler-swc": "^1.0.4", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.2", + "@storybook/test": "^8.2.2", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "eslint": "^8.57.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-storybook": "^0.8.0", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "prettier": "3.3.2", + "storybook": "^8.2.2", + "ts-loader": "^9.5.1", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", + "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", + "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.9", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-module-transforms": "^7.24.9", + "@babel/helpers": "^7.24.8", + "@babel/parser": "^7.24.8", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/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/core/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", + "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", + "dependencies": { + "@babel/types": "^7.24.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", + "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", + "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", + "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", + "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", + "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", + "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", + "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", + "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", + "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", + "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", + "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz", + "integrity": "sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-flow": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", + "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", + "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", + "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.8", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", + "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-flow-strip-types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", + "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/register/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", + "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", + "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.8", + "@babel/types": "^7.24.8", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/types": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@base2/pretty-print-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", + "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", + "dev": true + }, + "node_modules/@chromatic-com/storybook": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.6.1.tgz", + "integrity": "sha512-x1x1NB3j4xpfeSWKr96emc+7ZvfsvH+/WVb3XCjkB24PPbT8VZXb3mJSAQMrSzuQ8+eQE9kDogYHH9Fj3tb/Cw==", + "dev": true, + "dependencies": { + "chromatic": "^11.4.0", + "filesize": "^10.0.12", + "jsonfile": "^6.1.0", + "react-confetti": "^6.1.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=16.0.0", + "yarn": ">=1.22.18" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "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", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "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==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "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==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", + "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", + "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", + "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.2.0.tgz", + "integrity": "sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dev": true, + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", + "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/addon-actions": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.2.tgz", + "integrity": "sha512-SN4cSRt3f0qXi5te+yhMseSdQuZntA8lGlASbRmN77YQTpIaGsNiH88xFoky0s9qz531hiRfU1R0ZSMylBwSKw==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.2.tgz", + "integrity": "sha512-m/xJe7uKL+kfJx7pQcHwAeIvJ3tdLIpDGrMAVDNDJHcAxfe44cFjIInaV/1HKf3y5Awap+DZFW66ekkxuI9zzA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-controls": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.2.tgz", + "integrity": "sha512-y241aOANGzT5XBADUIvALwG/xF5eC6UItzmWJaFvOzSBCq74GIA0+Hu9atyFdvFQbXOrdvPWC4jR+9iuBFRxAA==", + "dev": true, + "dependencies": { + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.2.tgz", + "integrity": "sha512-qk/yjAR9RpsSrKLLbeCgb6u58c8TmYqyJSnXgbAozZZNKHBWlIpvZ/hTNYud8qo0coPlxnLdjnZf32TykWGlAg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.2.2", + "@storybook/csf-plugin": "8.2.2", + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.2", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "fs-extra": "^11.1.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-docs/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/addon-essentials": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.2.tgz", + "integrity": "sha512-yN//BFMbSvNV0+Sll2hcKmgJX06TUKQDm6pZimUjkXczFtOmK7K/UdDmKjWS+qjhfJdWpxdRoEpxoHvvRmNfsA==", + "dev": true, + "dependencies": { + "@storybook/addon-actions": "8.2.2", + "@storybook/addon-backgrounds": "8.2.2", + "@storybook/addon-controls": "8.2.2", + "@storybook/addon-docs": "8.2.2", + "@storybook/addon-highlight": "8.2.2", + "@storybook/addon-measure": "8.2.2", + "@storybook/addon-outline": "8.2.2", + "@storybook/addon-toolbars": "8.2.2", + "@storybook/addon-viewport": "8.2.2", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-highlight": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.2.tgz", + "integrity": "sha512-yDTRzzL+IJAymgY32xoZl09BGBVmPOUV2wVNGYcZkkBLvz2GSQMTfUe1/7F4jAx//+rFBu48/MQzsTC7Bk8kPw==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-interactions": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.2.tgz", + "integrity": "sha512-zRRuUwm/l41JtTUgjIoQTUgLT99Hsdz9cqKca/8NYo1MGBdEcKE41DH4aBIzKaOKFu7p9q00/o/X1EqYX4LMUA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.2.2", + "@storybook/test": "8.2.2", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-links": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.2.tgz", + "integrity": "sha512-eGh7O7SgTJMtnuXC0HlRPOegu1njcJS2cnVqjbzjvjxsPSBhbHpdYMi9Q9E7al/FKuqMUOjIR9YLIlmK1AJaqA==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-measure": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.2.tgz", + "integrity": "sha512-3rCo/aMltt5FrBVdr2dYlD8HlE2q9TLKGJZnwh9on4QyL6ArHbdYw0LmyHe/LrFahJ49w1XQZBMSJcAdRkkS7w==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-onboarding": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.2.tgz", + "integrity": "sha512-dCdE8Mt/JW6cq6dY7co35Sul/bAkUT3ixaxBrUagFUYUQ/PTYM6p4/B+45RURD5S9z8LVHH1rVgmEeScm3U78w==", + "dev": true, + "dependencies": { + "react-confetti": "^6.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-outline": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.2.tgz", + "integrity": "sha512-Y+PQtfTNO8GLX5nz+3x5AMfHNvdGvBXazJ29+Rl1ygYN1+Q9ZhRJDE1kAK0wLxb7CG14peAgdYEaQb3Rduv7HQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-toolbars": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.2.tgz", + "integrity": "sha512-JGOueOc3EPljlCl9dVSQee0aMYoqGNvN0UH+R6wYJ3bDZ+tUG/iYpsZVPUOvS8vzp3Imk5Is1kzQbQYJtzdGLg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-viewport": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.2.tgz", + "integrity": "sha512-gkZ8bsjGGP0NuevkT2iKC+szezSy+w4BrBDknf490mRU2K/B2e7TGojf/j/AtxzILMzD4IKzKUXbE/zwcqjZvA==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.4.tgz", + "integrity": "sha512-S/ypdAK9oqwUAt3ZOn44qi3RWdH5uBLbBgtfHSXckqTpQRu7F7A9bRzjK+H5ti4xVADRhxu/xzIBwxWgcCeIXA==", + "dev": true, + "dependencies": { + "@swc/core": "1.5.7", + "swc-loader": "^0.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@storybook/blocks": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.2.tgz", + "integrity": "sha512-av0Tryg4toDl2L/d1ABErtsAk9wvM1su6+M4wq5/Go50sk5IjGTldhbZFa9zNOohxLkZwaj0Q5xAgJ1Y+m5KrQ==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.4.5", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.2.tgz", + "integrity": "sha512-ud6a3pRusbC/TvT1ed15INxSivyL2y2zI61O/MWQZmM8sZOIC6ObdHLtzU4+535IIqiXhPoQ/QiOBbejqjgZvw==", + "dev": true, + "dependencies": { + "@storybook/core-webpack": "8.2.2", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "browser-assert": "^1.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "cjs-module-lexer": "^1.2.3", + "constants-browserify": "^1.0.0", + "css-loader": "^6.7.1", + "es-module-lexer": "^1.5.0", + "express": "^4.19.2", + "fork-ts-checker-webpack-plugin": "^8.0.0", + "fs-extra": "^11.1.0", + "html-webpack-plugin": "^5.5.0", + "magic-string": "^0.30.5", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "semver": "^7.3.7", + "style-loader": "^3.3.1", + "terser-webpack-plugin": "^5.3.1", + "ts-dedent": "^2.0.0", + "url": "^0.11.0", + "util": "^0.12.4", + "util-deprecate": "^1.0.2", + "webpack": "5", + "webpack-dev-middleware": "^6.1.2", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.6.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", + "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", + "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/codemod": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.2.2.tgz", + "integrity": "sha512-wRUVKLHVUhbLJYKW3QOufUxJGwaUT4jTCD8+HOGpHPdJO3NrwXu186xt4tuPZO2Y/NnacPeCQPsaK5ok4O8o7A==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/core": "8.2.2", + "@storybook/csf": "0.1.11", + "@types/cross-spawn": "^6.0.2", + "cross-spawn": "^7.0.3", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "lodash": "^4.17.21", + "prettier": "^3.1.1", + "recast": "^0.23.5", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/core": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.2.tgz", + "integrity": "sha512-L4ojYI+Os/i5bCReDIlFgEDQSS94mbJlNU9WRzEGZpqNC5/hbFEC9Tip7P1MiRx9NrewkzU7b+UCP7mi3e4drQ==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@types/express": "^4.17.21", + "@types/node": "^18.0.0", + "browser-assert": "^1.2.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", + "esbuild-register": "^3.5.0", + "express": "^4.19.2", + "process": "^0.11.10", + "recast": "^0.23.5", + "util": "^0.12.4", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-webpack": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.2.tgz", + "integrity": "sha512-M5wzgNbotVXcfo7WkXIuDxcBl7tTjnQ27lmlSBk+cu63pDvNn4UMDan621FcvxWq2DbjgIj+PASZ4DzM5O+ovA==", + "dev": true, + "dependencies": { + "@types/node": "^18.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/core-webpack/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/core/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/csf": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", + "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", + "dev": true, + "dependencies": { + "type-fest": "^2.19.0" + } + }, + "node_modules/@storybook/csf-plugin": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.2.2.tgz", + "integrity": "sha512-3K2RUpDDvq3DT46qAIj2VBC+fzTTebRUcZUsRfS6G1AzaX9p25iClEHiwcJacFkgQKhkci8A/Ly3Z4JJ3b4Pgw==", + "dev": true, + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true + }, + "node_modules/@storybook/icons": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.9.tgz", + "integrity": "sha512-cOmylsz25SYXaJL/gvTk/dl3pyk7yBFRfeXTsHvTA3dfhoU/LWSq0NKL9nM7WBasJyn6XPSGnLS4RtKXLw5EUg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@storybook/instrumenter": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.2.2.tgz", + "integrity": "sha512-refwnHqKHhya45MgqakhMG0jKhTiEIAl0aOwAaQy9+zf9ncMIYQAXRQsSZ2Z188lFWE24wbeHKteb62a5ZfWwQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@vitest/utils": "^1.3.1", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/preset-react-webpack": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.2.tgz", + "integrity": "sha512-GJkDtw4Ac8icD66fotGXYE3rmZkIwASpNLOeGzyP4eMMNaf5vlvTDxwkY551cGbnA5P7r4UkGjDiWinB9XE4VQ==", + "dev": true, + "dependencies": { + "@storybook/core-webpack": "8.2.2", + "@storybook/react": "8.2.2", + "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "magic-string": "^0.30.5", + "react-docgen": "^7.0.0", + "resolve": "^1.22.8", + "semver": "^7.3.7", + "tsconfig-paths": "^4.2.0", + "webpack": "5" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/react": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.2.tgz", + "integrity": "sha512-U4p/RV78yhjEwEzem8U7wE5/3sSpnqreGsPdAHMCIHd69e9tVeF0rwrTJGp917RClPjBKgEcfelCuvOlby4MrA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.2", + "@types/escodegen": "^0.0.6", + "@types/estree": "^0.0.51", + "@types/node": "^18.0.0", + "acorn": "^7.4.1", + "acorn-jsx": "^5.3.1", + "acorn-walk": "^7.2.0", + "escodegen": "^2.1.0", + "html-tags": "^3.1.0", + "lodash": "^4.17.21", + "prop-types": "^15.7.2", + "react-element-to-jsx-string": "^15.0.0", + "semver": "^7.3.7", + "ts-dedent": "^2.0.0", + "type-fest": "~2.19", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin": { + "version": "1.0.6--canary.9.0c3f3b7.0", + "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", + "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "endent": "^2.0.1", + "find-cache-dir": "^3.3.1", + "flat-cache": "^3.0.4", + "micromatch": "^4.0.2", + "react-docgen-typescript": "^2.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "typescript": ">= 4.x", + "webpack": ">= 4" + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@storybook/react-dom-shim": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.2.tgz", + "integrity": "sha512-4fb1/yT9WXHzHjs0In6orIEZxga5eXd9UaXEFGudBgowCjDUVP9LabDdKTbGusz20lfaAkATsRG/W+EcSLoh8w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/react-webpack5": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.2.tgz", + "integrity": "sha512-JPR2Lp88KbfRWgnAd4lKFRKuc9Up6YeqbaDb6sptOXXzDM4nOhlRXKqp2tIqyhfiKp3wmu3PksixqD8f8VS9CA==", + "dev": true, + "dependencies": { + "@storybook/builder-webpack5": "8.2.2", + "@storybook/preset-react-webpack": "8.2.2", + "@storybook/react": "8.2.2", + "@types/node": "^18.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/react-webpack5/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/react/node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@storybook/react/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/react/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/test": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.2.2.tgz", + "integrity": "sha512-X2qAKErjTh1X7XLAZqCMtU0ZK8JuwdKmgiqU0oXWxIDmCX6/Dm9ZIcdMZHs/S+K/UnIByjNlQpTShLVfRUeN1w==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/instrumenter": "8.2.2", + "@testing-library/dom": "10.1.0", + "@testing-library/jest-dom": "6.4.5", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "1.6.0", + "@vitest/spy": "1.6.0", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@swc/core": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.7.tgz", + "integrity": "sha512-U4qJRBefIJNJDRCCiVtkfa/hpiZ7w0R6kASea+/KLp+vkus3zcLSB8Ub8SvKgTIxjWpwsKcZlPf5nrv4ls46SQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.2", + "@swc/types": "0.1.7" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.5.7", + "@swc/core-darwin-x64": "1.5.7", + "@swc/core-linux-arm-gnueabihf": "1.5.7", + "@swc/core-linux-arm64-gnu": "1.5.7", + "@swc/core-linux-arm64-musl": "1.5.7", + "@swc/core-linux-x64-gnu": "1.5.7", + "@swc/core-linux-x64-musl": "1.5.7", + "@swc/core-win32-arm64-msvc": "1.5.7", + "@swc/core-win32-ia32-msvc": "1.5.7", + "@swc/core-win32-x64-msvc": "1.5.7" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.7.tgz", + "integrity": "sha512-bZLVHPTpH3h6yhwVl395k0Mtx8v6CGhq5r4KQdAoPbADU974Mauz1b6ViHAJ74O0IVE5vyy7tD3OpkQxL/vMDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.7.tgz", + "integrity": "sha512-RpUyu2GsviwTc2qVajPL0l8nf2vKj5wzO3WkLSHAHEJbiUZk83NJrZd1RVbEknIMO7+Uyjh54hEh8R26jSByaw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.7.tgz", + "integrity": "sha512-cTZWTnCXLABOuvWiv6nQQM0hP6ZWEkzdgDvztgHI/+u/MvtzJBN5lBQ2lue/9sSFYLMqzqff5EHKlFtrJCA9dQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.7.tgz", + "integrity": "sha512-hoeTJFBiE/IJP30Be7djWF8Q5KVgkbDtjySmvYLg9P94bHg9TJPSQoC72tXx/oXOgXvElDe/GMybru0UxhKx4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.7.tgz", + "integrity": "sha512-+NDhK+IFTiVK1/o7EXdCeF2hEzCiaRSrb9zD7X2Z7inwWlxAntcSuzZW7Y6BRqGQH89KA91qYgwbnjgTQ22PiQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.7.tgz", + "integrity": "sha512-25GXpJmeFxKB+7pbY7YQLhWWjkYlR+kHz5I3j9WRl3Lp4v4UD67OGXwPe+DIcHqcouA1fhLhsgHJWtsaNOMBNg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.7.tgz", + "integrity": "sha512-0VN9Y5EAPBESmSPPsCJzplZHV26akC0sIgd3Hc/7S/1GkSMoeuVL+V9vt+F/cCuzr4VidzSkqftdP3qEIsXSpg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.7.tgz", + "integrity": "sha512-RtoNnstBwy5VloNCvmvYNApkTmuCe4sNcoYWpmY7C1+bPR+6SOo8im1G6/FpNem8AR5fcZCmXHWQ+EUmRWJyuA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.7.tgz", + "integrity": "sha512-Xm0TfvcmmspvQg1s4+USL3x8D+YPAfX2JHygvxAnCJ0EHun8cm2zvfNBcsTlnwYb0ybFWXXY129aq1wgFC9TpQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.7.tgz", + "integrity": "sha512-tp43WfJLCsKLQKBmjmY/0vv1slVywR5Q4qKjF5OIY8QijaEW7/8VwPyUyVoJZEnDgv9jKtUTG5PzqtIYPZGnyg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "node_modules/@swc/types": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.7.tgz", + "integrity": "sha512-scHWahbHF0eyj3JsxG9CFJgFdFNaVQCNAimBlT6PzS3n/HptxqREjsm4OH6AN3lYcffZYSPxXW8ua2BEHp0lJQ==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", + "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", + "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/doctrine": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", + "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", + "dev": true + }, + "node_modules/@types/emscripten": { + "version": "1.39.13", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", + "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==", + "dev": true + }, + "node_modules/@types/escodegen": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz", + "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==", + "dev": true + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", + "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==", + "dev": true + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", + "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", + "dev": true + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", + "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vitest/utils/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/utils/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/fslib": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", + "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", + "dev": true, + "dependencies": { + "@yarnpkg/libzip": "^2.3.0", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/fslib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@yarnpkg/libzip": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", + "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", + "dev": true, + "dependencies": { + "@types/emscripten": "^1.39.6", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/libzip/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "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": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "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, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "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, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", + "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromatic": { + "version": "11.5.5", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.5.5.tgz", + "integrity": "sha512-YS0GJwegF0vpMbwZE68/xJlI4SlUGMqI78V2ATAF19YwTHaq8jGP1CPQGKUSlgWUhzPtyu3ELy6Dvv/owYljAg==", + "dev": true, + "bin": { + "chroma": "dist/bin.js", + "chromatic": "dist/bin.js", + "chromatic-cli": "dist/bin.js" + }, + "peerDependencies": { + "@chromatic-com/cypress": "^0.*.* || ^1.0.0", + "@chromatic-com/playwright": "^0.*.* || ^1.0.0" + }, + "peerDependenciesMeta": { + "@chromatic-com/cypress": { + "optional": true + }, + "@chromatic-com/playwright": { + "optional": true + } + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "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-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.827", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", + "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dev": true, + "dependencies": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "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, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/esbuild-register": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", + "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" + } + }, + "node_modules/esbuild-register/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/esbuild-register/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", + "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", + "dev": true, + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" + }, + "engines": { + "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/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 + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/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 + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "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.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/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 + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.4.tgz", + "integrity": "sha512-Np+jo9bUwJNxCsT12pXtrGhJgT3T44T1sHhn1Ssr42XFn8TES0267wPGo5nNrMHi8qkyimDAX2BUmkf9pSaVzA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-storybook": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.8.0.tgz", + "integrity": "sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.0.1", + "@typescript-eslint/utils": "^5.62.0", + "requireindex": "^1.2.0", + "ts-dedent": "^2.2.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "eslint": ">=6" + } + }, + "node_modules/eslint-plugin-storybook/node_modules/@storybook/csf": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", + "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "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==" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-parse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fd-package-json": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", + "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", + "dev": true, + "dependencies": { + "walk-up-path": "^3.0.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/filesize": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.4.tgz", + "integrity": "sha512-ryBwPIIeErmxgPnm6cbESAzXjuEFubs+yKYLBZvg3CaiNcmkJChoOGcBSrZ6IwkMwPABwPpVXE6IlNdGJJrvEg==", + "dev": true, + "engines": { + "node": ">= 10.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flat-cache/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/flow-parser": { + "version": "0.239.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.239.1.tgz", + "integrity": "sha512-topOrETNxJ6T2gAnQiWqAlzGPj8uI2wtmNOlDIMNB+qyvGJZ6R++STbUOTAYmvPhOMz2gXnXPH0hOvURYmrBow==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": 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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/giget": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "tar": "^6.2.0" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/globals": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", + "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "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, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "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==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "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, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-heading-rank": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", + "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz", + "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==", + "dev": true, + "dependencies": { + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/html-loader/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/html-loader/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/html-loader/node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-absolute-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", + "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jscodeshift": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/preset-flow": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@babel/register": "^7.22.15", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.23.3", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/launch-editor": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", + "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils-webpack-v4": { + "name": "loader-utils", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/loader-utils-webpack-v4/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true + }, + "node_modules/markdown-to-jsx": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz", + "integrity": "sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", + "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", + "dev": true, + "dependencies": { + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.1.2", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mlly": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", + "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + } + }, + "node_modules/modify-source-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/modify-source-webpack-plugin/-/modify-source-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-UaLQyFXoPWpWxkNUBFo9BotC20CCAGe7HEX9iKtB0P0MgNXgURf9TXUgNGuY5iVV5lDDQtcMjT2vneQWnNmwEw==", + "dependencies": { + "loader-utils-webpack-v4": "npm:loader-utils@^2.0.4", + "schema-utils": "^4.0.0" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/modify-source-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-dir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-dir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", + "dev": true + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nypm": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.9.tgz", + "integrity": "sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/nypm/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/nypm/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/nypm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nypm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/objectorarray": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", + "dev": true + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "dev": true, + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-types": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.3.tgz", + "integrity": "sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==", + "dev": true, + "dependencies": { + "confbox": "^0.1.7", + "mlly": "^1.7.1", + "pathe": "^1.1.2" + } + }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-confetti": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", + "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", + "dev": true, + "dependencies": { + "tween-functions": "^1.2.0" + }, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-docgen": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.0.3.tgz", + "integrity": "sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.9", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9", + "@types/babel__core": "^7.18.0", + "@types/babel__traverse": "^7.18.0", + "@types/doctrine": "^0.0.9", + "@types/resolve": "^1.20.2", + "doctrine": "^3.0.0", + "resolve": "^1.22.1", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=16.14.0" + } + }, + "node_modules/react-docgen-typescript": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", + "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", + "dev": true, + "peerDependencies": { + "typescript": ">= 4.3.x" + } + }, + "node_modules/react-docgen/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-element-to-jsx-string": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", + "integrity": "sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==", + "dev": true, + "dependencies": { + "@base2/pretty-print-object": "1.0.1", + "is-plain-object": "5.0.0", + "react-is": "18.1.0" + }, + "peerDependencies": { + "react": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0", + "react-dom": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/react-is": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", + "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "dev": true + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-router": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", + "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", + "dependencies": { + "@remix-run/router": "1.17.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", + "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", + "dependencies": { + "@remix-run/router": "1.17.1", + "react-router": "6.24.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recast": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", + "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "dev": true, + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent/node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "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", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/rehype-external-links": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", + "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-is-element": "^3.0.0", + "is-absolute-url": "^4.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", + "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.9.tgz", + "integrity": "sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": "14 >=14.20 || 16 >=16.20 || >=18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/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 + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.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, + "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, + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy-transport/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/storybook": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.2.2.tgz", + "integrity": "sha512-xDT9gyzAEFQNeK7P+Mj/8bNzN+fbm6/4D6ihdSzmczayjydpNjMs74HDHMY6S4Bfu6tRVyEK2ALPGnr6ZVofBA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/codemod": "8.2.2", + "@storybook/core": "8.2.2", + "@types/semver": "^7.3.4", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "cross-spawn": "^7.0.3", + "detect-indent": "^6.1.0", + "envinfo": "^7.7.3", + "execa": "^5.0.0", + "fd-package-json": "^1.2.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "giget": "^1.0.0", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "leven": "^3.1.0", + "ora": "^5.4.1", + "prettier": "^3.1.1", + "prompts": "^2.4.0", + "semver": "^7.3.7", + "strip-json-comments": "^3.0.1", + "tempy": "^3.1.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0" + }, + "bin": { + "getstorybook": "bin/index.cjs", + "sb": "bin/index.cjs", + "storybook": "bin/index.cjs" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/storybook/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/storybook/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "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", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "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, + "dependencies": { + "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" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dev": true, + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/telejson": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", + "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/temp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/temp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/temp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.31.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", + "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tsconfig-paths": { + "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, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", + "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.16.0", + "@typescript-eslint/parser": "7.16.0", + "@typescript-eslint/utils": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unplugin": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.11.0.tgz", + "integrity": "sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "chokidar": "^3.6.0", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.6.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "dev": true, + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.11.2" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/url/node_modules/qs": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", + "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walk-up-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", + "dev": true + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webpack": { + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz", + "integrity": "sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.6.0", + "mime-types": "^2.1.31", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-hot-middleware": { + "version": "2.26.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", + "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", + "dev": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "strip-ansi": "^6.0.0" + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "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.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/HDesign/package.json b/HDesign/package.json new file mode 100644 index 000000000..5abaa6227 --- /dev/null +++ b/HDesign/package.json @@ -0,0 +1,66 @@ +{ + "name": "haengdong-design", + "version": "1.0.0", + "description": "", + "type": "module", + "scripts": { + "start": "webpack serve ", + "build": "webpack --mode production", + "storybook": "storybook dev -p 6006", + "lint": "eslint 'lib/**/*.{js,jsx,ts,tsx}'", + "format": "prettier --write 'lib/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", + "build-storybook": "storybook build" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/addon-webpack5-compiler-swc": "^1.0.4", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.2", + "@storybook/test": "^8.2.2", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "eslint": "^8.57.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-storybook": "^0.8.0", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "prettier": "3.3.2", + "storybook": "^8.2.2", + "ts-loader": "^9.5.1", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4" + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "modify-source-webpack-plugin": "^4.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "engines": { + "npm": ">=10.7.0", + "node": ">=20.15.1" + } +} diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json new file mode 100644 index 000000000..4f0fd007a --- /dev/null +++ b/HDesign/tsconfig.json @@ -0,0 +1,43 @@ +{ + "compilerOptions": { + "sourceMap": true, + "module": "ES2020", + "target": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "useDefineForClassFields": true, + "removeComments": true, + "skipLibCheck": true, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + // "types": ["jest"], + "esModuleInterop": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitAny": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + "jsxImportSource": "@emotion/react", + + "baseUrl": "./", + "paths": { + "components/*": ["lib/components/*"] + }, + "outDir": "./dist" + }, + "include": ["lib"] +} diff --git a/HDesign/webpack.config.js b/HDesign/webpack.config.js new file mode 100644 index 000000000..7077a6f5a --- /dev/null +++ b/HDesign/webpack.config.js @@ -0,0 +1,48 @@ +import path from 'path'; +import {fileURLToPath} from 'url'; + +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import {ModifySourcePlugin, ConcatOperation} from 'modify-source-webpack-plugin'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default { + mode: 'development', + entry: './lib/index.tsx', + resolve: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + output: { + path: path.join(__dirname, 'dist'), + filename: 'bundle.min.js', + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, + plugins: [ + new HtmlWebpackPlugin({ + template: './index.html', + }), + new ForkTsCheckerWebpackPlugin(), + new ModifySourcePlugin({ + rules: [ + { + test: /\.tsx$/i, + operations: [new ConcatOperation('start', '/** @jsxImportSource @emotion/react */\n\n')], + }, + ], + }), + ], + devServer: { + port: 3000, + hot: true, + }, +}; From 3d7044380e32499d3de44c2c847aa4a0533b7779 Mon Sep 17 00:00:00 2001 From: Soyeon Choe Date: Tue, 16 Jul 2024 01:58:54 +0900 Subject: [PATCH 015/273] =?UTF-8?q?feat:=20theme,=20token=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> --- HDesign/lib/theme/GlobalStyle.ts | 121 ++++++++++++++++++++++++++ HDesign/lib/theme/HDesignProvider.tsx | 35 ++++++++ HDesign/lib/theme/theme.type.ts | 7 ++ HDesign/lib/token/colors.ts | 43 +++++++++ HDesign/lib/token/typography.ts | 67 ++++++++++++++ 5 files changed, 273 insertions(+) create mode 100644 HDesign/lib/theme/GlobalStyle.ts create mode 100644 HDesign/lib/theme/HDesignProvider.tsx create mode 100644 HDesign/lib/theme/theme.type.ts create mode 100644 HDesign/lib/token/colors.ts create mode 100644 HDesign/lib/token/typography.ts diff --git a/HDesign/lib/theme/GlobalStyle.ts b/HDesign/lib/theme/GlobalStyle.ts new file mode 100644 index 000000000..08cd8094e --- /dev/null +++ b/HDesign/lib/theme/GlobalStyle.ts @@ -0,0 +1,121 @@ +import {css} from '@emotion/react'; + +export const GlobalStyle = css` + *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { + all: unset; + display: revert; + } + + /* Preferred box-sizing value */ + *, + *::before, + *::after { + box-sizing: border-box; + } + + /* Fix mobile Safari increase font-size on landscape mode */ + html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; + } + + /* Reapply the pointer cursor for anchor tags */ + a, + button { + cursor: revert; + } + + /* Remove list styles (bullets/numbers) */ + ol, + ul, + menu, + summary { + list-style: none; + } + + /* For images to not be able to exceed their container */ + img { + max-inline-size: 100%; + max-block-size: 100%; + } + + /* Removes spacing between cells in tables */ + table { + border-collapse: collapse; + } + + /* Safari - solving issue when using user-select:none on the text input doesn't working */ + input, + textarea { + -webkit-user-select: auto; + } + + /* Revert the 'white-space' property for textarea elements on Safari */ + textarea { + white-space: revert; + } + + /* Minimum style to allow to style meter element */ + meter { + -webkit-appearance: revert; + appearance: revert; + } + + /* Preformatted text - use only for this feature */ + :where(pre) { + all: revert; + box-sizing: border-box; + } + + /* Fix the feature of 'hidden' attribute. + display: revert; revert to element instead of attribute */ + :where([hidden]) { + display: none; + } + + /* Revert for bug in Chromium browsers + - Fix for the content editable attribute will work properly. + - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element */ + :where([contenteditable]:not([contenteditable='false'])) { + -moz-user-modify: read-write; + -webkit-user-modify: read-write; + overflow-wrap: break-word; + -webkit-line-break: after-white-space; + -webkit-user-select: auto; + } + + /* Apply back the draggable feature - exist only in Chromium and Safari */ + :where([draggable='true']) { + -webkit-user-drag: element; + } + + /* Revert Modal native behavior */ + :where(dialog:modal) { + all: revert; + box-sizing: border-box; + } + + /* Remove details summary webkit styles */ + ::-webkit-details-marker { + display: none; + } + + /* Chrome, Safari, Edge, Opera */ + input::-webkit-outer-spin-button, + input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + /* Firefox */ + input[type='number'] { + -moz-appearance: textfield; + } + + #root { + display: flex; + justify-content: center; + background-color: #eeeeee; + } +`; diff --git a/HDesign/lib/theme/HDesignProvider.tsx b/HDesign/lib/theme/HDesignProvider.tsx new file mode 100644 index 000000000..d196dba2d --- /dev/null +++ b/HDesign/lib/theme/HDesignProvider.tsx @@ -0,0 +1,35 @@ +import React, {createContext, useContext, useState, ReactNode} from 'react'; +import {Global} from '@emotion/react'; +import {COLORS} from '../token/colors'; +import {TYPOGRAPHY} from '../token/typography'; +import {Theme} from './theme.type'; +import {GlobalStyle} from './GlobalStyle'; + +interface ThemeContextProps { + theme: Theme; +} + +const defaultTheme: Theme = { + colors: COLORS, + typography: TYPOGRAPHY, +}; + +const ThemeContext = createContext(undefined); + +export const HDesignProvider: React.FC<{children: ReactNode}> = ({children}) => { + const [theme, _] = useState(defaultTheme); + return ( + + + {children} + + ); +}; + +export const useTheme = (): ThemeContextProps => { + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within a HDesignProvider'); + } + return context; +}; diff --git a/HDesign/lib/theme/theme.type.ts b/HDesign/lib/theme/theme.type.ts new file mode 100644 index 000000000..73c0f8359 --- /dev/null +++ b/HDesign/lib/theme/theme.type.ts @@ -0,0 +1,7 @@ +import {ColorTokens} from '../token/colors'; +import {TypographyTokens} from '../token/typography'; + +export interface Theme { + colors: ColorTokens; + typography: TypographyTokens; +} diff --git a/HDesign/lib/token/colors.ts b/HDesign/lib/token/colors.ts new file mode 100644 index 000000000..668f1c272 --- /dev/null +++ b/HDesign/lib/token/colors.ts @@ -0,0 +1,43 @@ +const PRIMITIVE_COLORS = { + white: '#FFFFFF', + purple: { + 50: '#f4e8ff', + 100: '#e0c7fe', + 200: '#cba0fe', + 300: '#b575ff', + 400: '#a350fd', + 500: '#8f2bf3', + 600: '#8425ec', + 700: '#7519e3', + 800: '#6712db', + 900: '#5100cd', + }, + gray: { + 50: '#F9F8FD', + 100: '#F1F0F5', + 200: '#E7E6EB', + 300: '#D6D5DA', + 400: '#B2B1B6', + 500: '#929195', + 600: '#6A696D', + 700: '#56555A', + 800: '#38373B', + 900: '#18171B', + }, +}; + +type Color = string; + +export type ColorTokens = Record; + +// TODO: (@soha) 대괄호 사용에 대해 논의 +export const COLORS: ColorTokens = { + white: PRIMITIVE_COLORS.white, + black: PRIMITIVE_COLORS.gray[700], + primary: PRIMITIVE_COLORS.purple[300], + onPrimary: PRIMITIVE_COLORS.white, + secondary: PRIMITIVE_COLORS.purple[50], + onSecondary: PRIMITIVE_COLORS.purple[600], + tertiary: PRIMITIVE_COLORS.gray[200], + onTertiary: PRIMITIVE_COLORS.gray[700], +}; diff --git a/HDesign/lib/token/typography.ts b/HDesign/lib/token/typography.ts new file mode 100644 index 000000000..c88d61ea9 --- /dev/null +++ b/HDesign/lib/token/typography.ts @@ -0,0 +1,67 @@ +type Typography = Record; +export type TypographyTokens = Record; + +export const TYPOGRAPHY: TypographyTokens = { + head: { + fontFamily: 'Pretendard', + fontSize: '3rem', + lineHeight: '1.5', + fontWeight: '700', + }, + title: { + fontFamily: 'Pretendard', + fontSize: '2rem', + lineHeight: '1.5', + fontWeight: '700', + }, + subTitle: { + fontFamily: 'Pretendard', + fontSize: '1.5rem', + lineHeight: '1.5', + fontWeight: '700', + }, + bodyBold: { + fontFamily: 'Pretendard', + fontSize: '1rem', + lineHeight: '1.5', + fontWeight: '700', + }, + body: { + fontFamily: 'Pretendard', + fontSize: '1rem', + lineHeight: '1.5', + fontWeight: '400', + }, + smallBodyBold: { + fontFamily: 'Pretendard', + fontSize: '0.875rem', + lineHeight: '1.5', + fontWeight: '700', + }, + smallBody: { + fontFamily: 'Pretendard', + fontSize: '0.875rem', + lineHeight: '1.5', + fontWeight: '400', + }, + captionBold: { + fontFamily: 'Pretendard', + fontSize: '0.75rem', + lineHeight: '1.5', + fontWeight: '700', + }, + caption: { + fontFamily: 'Pretendard', + fontSize: '0.75rem', + lineHeight: '1.5', + fontWeight: '400', + }, + tiny: { + fontFamily: 'Pretendard', + fontSize: '0.625rem', + lineHeight: '1.5', + fontWeight: '400', + }, +}; + +export default TYPOGRAPHY; From 9cf6fd53a6c2036cbbd54b625b2631c786d4b0c4 Mon Sep 17 00:00:00 2001 From: Soyeon Choe Date: Tue, 16 Jul 2024 01:59:39 +0900 Subject: [PATCH 016/273] =?UTF-8?q?chore:=20storybook=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> --- HDesign/.gitignore | 1 + HDesign/.storybook/main.ts | 2 +- .../.storybook/{preview.ts => preview.tsx} | 10 +++ HDesign/package-lock.json | 71 +++++++++++-------- HDesign/package.json | 2 +- 5 files changed, 56 insertions(+), 30 deletions(-) rename HDesign/.storybook/{preview.ts => preview.tsx} (54%) diff --git a/HDesign/.gitignore b/HDesign/.gitignore index afd0485d1..b98928456 100644 --- a/HDesign/.gitignore +++ b/HDesign/.gitignore @@ -7,5 +7,6 @@ dist .env +storybook-static *storybook.log .DS_Store diff --git a/HDesign/.storybook/main.ts b/HDesign/.storybook/main.ts index dcdd7bf09..30eb7b35e 100644 --- a/HDesign/.storybook/main.ts +++ b/HDesign/.storybook/main.ts @@ -1,7 +1,7 @@ import type {StorybookConfig} from '@storybook/react-webpack5'; const config: StorybookConfig = { - stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + stories: ['../lib/**/*.mdx', '../lib/**/*.stories.@(js|jsx|mjs|ts|tsx)'], addons: [ '@storybook/addon-webpack5-compiler-swc', '@storybook/addon-onboarding', diff --git a/HDesign/.storybook/preview.ts b/HDesign/.storybook/preview.tsx similarity index 54% rename from HDesign/.storybook/preview.ts rename to HDesign/.storybook/preview.tsx index a66ea2ee6..921253ef6 100644 --- a/HDesign/.storybook/preview.ts +++ b/HDesign/.storybook/preview.tsx @@ -1,4 +1,7 @@ +import React from 'react'; + import type {Preview} from '@storybook/react'; +import {HDesignProvider} from '../lib/theme/HDesignProvider'; const preview: Preview = { parameters: { @@ -9,6 +12,13 @@ const preview: Preview = { }, }, }, + decorators: [ + Story => ( + + + + ), + ], }; export default preview; diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 0d86a87a3..7fea2f72f 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -26,7 +26,7 @@ "@storybook/addon-webpack5-compiler-swc": "^1.0.4", "@storybook/blocks": "^8.2.2", "@storybook/react": "^8.2.2", - "@storybook/react-webpack5": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", "@storybook/test": "^8.2.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", @@ -3544,12 +3544,12 @@ } }, "node_modules/@storybook/builder-webpack5": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.2.tgz", - "integrity": "sha512-ud6a3pRusbC/TvT1ed15INxSivyL2y2zI61O/MWQZmM8sZOIC6ObdHLtzU4+535IIqiXhPoQ/QiOBbejqjgZvw==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.3.tgz", + "integrity": "sha512-yU9rtcVpo12vD8m/nbdepyJ09K937ZnSsrvIM9XfzbxXA/+p4Cov9Rjg1VfoWyRd1ApxaztSktQlawBlb6bKEA==", "dev": true, "dependencies": { - "@storybook/core-webpack": "8.2.2", + "@storybook/core-webpack": "8.2.3", "@types/node": "^18.0.0", "@types/semver": "^7.3.4", "browser-assert": "^1.2.1", @@ -3582,7 +3582,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.2.2" + "storybook": "^8.2.3" }, "peerDependenciesMeta": { "typescript": { @@ -3879,9 +3879,9 @@ } }, "node_modules/@storybook/core-webpack": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.2.tgz", - "integrity": "sha512-M5wzgNbotVXcfo7WkXIuDxcBl7tTjnQ27lmlSBk+cu63pDvNn4UMDan621FcvxWq2DbjgIj+PASZ4DzM5O+ovA==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", + "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", "dev": true, "dependencies": { "@types/node": "^18.0.0", @@ -3892,7 +3892,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.2.2" + "storybook": "^8.2.3" } }, "node_modules/@storybook/core-webpack/node_modules/@types/node": { @@ -3976,13 +3976,13 @@ } }, "node_modules/@storybook/preset-react-webpack": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.2.tgz", - "integrity": "sha512-GJkDtw4Ac8icD66fotGXYE3rmZkIwASpNLOeGzyP4eMMNaf5vlvTDxwkY551cGbnA5P7r4UkGjDiWinB9XE4VQ==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.3.tgz", + "integrity": "sha512-i886+vCMGlpFgOAOIg6BxSHgt38MXS6gqNX8Z65KVVIlI6i/9WqEQeHYfukbdGvVZ96cYWmdrnqUieIIkdCdBw==", "dev": true, "dependencies": { - "@storybook/core-webpack": "8.2.2", - "@storybook/react": "8.2.2", + "@storybook/core-webpack": "8.2.3", + "@storybook/react": "8.2.3", "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", "@types/node": "^18.0.0", "@types/semver": "^7.3.4", @@ -4005,7 +4005,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" + "storybook": "^8.2.3" }, "peerDependenciesMeta": { "typescript": { @@ -4124,13 +4124,13 @@ } }, "node_modules/@storybook/react": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.2.tgz", - "integrity": "sha512-U4p/RV78yhjEwEzem8U7wE5/3sSpnqreGsPdAHMCIHd69e9tVeF0rwrTJGp917RClPjBKgEcfelCuvOlby4MrA==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.3.tgz", + "integrity": "sha512-818F6pJWFBiwG0r6DiUVrV+qndwbIso2gtgJoituBgIJO2eIzNmkPNSsckbaR7u+FpE4dWiIIhmDVZSnRwvDlA==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0", - "@storybook/react-dom-shim": "8.2.2", + "@storybook/react-dom-shim": "8.2.3", "@types/escodegen": "^0.0.6", "@types/estree": "^0.0.51", "@types/node": "^18.0.0", @@ -4157,7 +4157,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2", + "storybook": "^8.2.3", "typescript": ">= 4.2.x" }, "peerDependenciesMeta": { @@ -4224,14 +4224,14 @@ } }, "node_modules/@storybook/react-webpack5": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.2.tgz", - "integrity": "sha512-JPR2Lp88KbfRWgnAd4lKFRKuc9Up6YeqbaDb6sptOXXzDM4nOhlRXKqp2tIqyhfiKp3wmu3PksixqD8f8VS9CA==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.3.tgz", + "integrity": "sha512-lcm73r8S5Uy2ENuFDSR07fW+KRSYGNcrF53VItP+rgFZHrOm7gaeebrjSIA6r4tQwdd9218VaqpQGFrKAURS2w==", "dev": true, "dependencies": { - "@storybook/builder-webpack5": "8.2.2", - "@storybook/preset-react-webpack": "8.2.2", - "@storybook/react": "8.2.2", + "@storybook/builder-webpack5": "8.2.3", + "@storybook/preset-react-webpack": "8.2.3", + "@storybook/react": "8.2.3", "@types/node": "^18.0.0" }, "engines": { @@ -4244,7 +4244,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2", + "storybook": "^8.2.3", "typescript": ">= 4.2.x" }, "peerDependenciesMeta": { @@ -4262,6 +4262,21 @@ "undici-types": "~5.26.4" } }, + "node_modules/@storybook/react/node_modules/@storybook/react-dom-shim": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.3.tgz", + "integrity": "sha512-N8AsM6N1S867GGWt2J2q5oY5ryqxohh3y1HqNtjg+wXf5+RkTD6M2Cgqe6p+JHz81nDKyvvVzP60MvvDhY5VOA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3" + } + }, "node_modules/@storybook/react/node_modules/@types/estree": { "version": "0.0.51", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", diff --git a/HDesign/package.json b/HDesign/package.json index 5abaa6227..2e97b2ed8 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -25,7 +25,7 @@ "@storybook/addon-webpack5-compiler-swc": "^1.0.4", "@storybook/blocks": "^8.2.2", "@storybook/react": "^8.2.2", - "@storybook/react-webpack5": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", "@storybook/test": "^8.2.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", From 94b04b7bba988fa4ad5370e424e1f01db929f252 Mon Sep 17 00:00:00 2001 From: Soyeon Choe Date: Tue, 16 Jul 2024 01:59:58 +0900 Subject: [PATCH 017/273] =?UTF-8?q?feat:=20Button=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> --- .../lib/components/Button/Button.stories.tsx | 40 +++++++++++ HDesign/lib/components/Button/Button.style.ts | 69 +++++++++++++++++++ HDesign/lib/components/Button/Button.tsx | 18 +++++ HDesign/lib/components/Button/Button.type.ts | 16 +++++ 4 files changed, 143 insertions(+) create mode 100644 HDesign/lib/components/Button/Button.stories.tsx create mode 100644 HDesign/lib/components/Button/Button.style.ts create mode 100644 HDesign/lib/components/Button/Button.tsx create mode 100644 HDesign/lib/components/Button/Button.type.ts diff --git a/HDesign/lib/components/Button/Button.stories.tsx b/HDesign/lib/components/Button/Button.stories.tsx new file mode 100644 index 000000000..2e8b00bb3 --- /dev/null +++ b/HDesign/lib/components/Button/Button.stories.tsx @@ -0,0 +1,40 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Button from './Button'; + +const meta = { + title: 'Components/Button', + component: Button, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + variants: { + description: '', + control: {type: 'select'}, + options: ['', 'primary', 'secondary', 'tertiary'], + }, + size: { + description: '', + control: {type: 'select'}, + options: ['', 'small', 'medium', 'large'], + }, + disabled: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + variants: 'primary', + size: 'medium', + disabled: false, + children: 'button', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/lib/components/Button/Button.style.ts b/HDesign/lib/components/Button/Button.style.ts new file mode 100644 index 000000000..d9270b35c --- /dev/null +++ b/HDesign/lib/components/Button/Button.style.ts @@ -0,0 +1,69 @@ +import {css} from '@emotion/react'; +import {ButtonStyleProps, ButtonSize, ButtonVariants} from './Button.type'; +import {Theme} from '../../theme/theme.type'; + +export const buttonStyle = (props: Required) => { + return [ + getButtonDefaultStyle(props.theme), + getButtonSizeStyle(props.size), + getButtonVariantsStyle(props.variants, props.theme), + ]; +}; + +const getButtonDefaultStyle = (theme: Theme) => + css({ + display: 'flex', + lineHeight: '1', + + '&:disabled': { + backgroundColor: theme.colors.tertiary, + color: theme.colors.onPrimary, + }, + }); + +const getButtonSizeStyle = (size: ButtonSize) => { + const style = { + small: css({ + padding: '0.5rem 0.75rem', + borderRadius: '0.75rem', + fontFamily: 'Pretendard', + fontSize: '0.75rem', + fontWeight: '400', + }), + medium: css({ + padding: '0.75rem 1rem', + borderRadius: '1rem', + fontFamily: 'Pretendard', + fontSize: '1rem', + fontWeight: '700', + }), + large: css({ + padding: '1rem 1.5rem', + borderRadius: '1.25rem', + fontFamily: 'Pretendard', + fontSize: '1.25rem', + fontWeight: '700', + }), + }; + + return style[size]; +}; + +const getButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => { + const style = { + primary: css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + secondary: css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + tertiary: css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + }; + + return style[variants]; +}; diff --git a/HDesign/lib/components/Button/Button.tsx b/HDesign/lib/components/Button/Button.tsx new file mode 100644 index 000000000..01474c0e8 --- /dev/null +++ b/HDesign/lib/components/Button/Button.tsx @@ -0,0 +1,18 @@ +/** @jsxImportSource @emotion/react */ +import React, {forwardRef} from 'react'; + +import {buttonStyle} from './Button.style'; + +import {ButtonProps} from './Button.type'; + +import {useTheme} from '../../theme/HDesignProvider'; + +export const Button: React.FC = forwardRef(function Button( + {variants = 'primary', size = 'medium', ...htmlProps}: ButtonProps, + ref, +) { + const {theme} = useTheme(); + return + + ); +}; + +export default Main; diff --git a/client/src/pages/Main/index.ts b/client/src/pages/Main/index.ts new file mode 100644 index 000000000..c3cce532e --- /dev/null +++ b/client/src/pages/Main/index.ts @@ -0,0 +1 @@ +export {default as MainPage} from './Main'; From 00d75e4b81239b573fdf4819cf2cdc4defc6575a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 01:00:56 +0900 Subject: [PATCH 024/273] =?UTF-8?q?feat:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=8D=BC?= =?UTF-8?q?=EB=B8=94=EB=A6=AC=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/src/pages/CreateEvent/CreateEvent.tsx | 26 ++++++++++++++++++++ client/src/pages/CreateEvent/index.ts | 1 + 2 files changed, 27 insertions(+) create mode 100644 client/src/pages/CreateEvent/CreateEvent.tsx create mode 100644 client/src/pages/CreateEvent/index.ts diff --git a/client/src/pages/CreateEvent/CreateEvent.tsx b/client/src/pages/CreateEvent/CreateEvent.tsx new file mode 100644 index 000000000..476418ead --- /dev/null +++ b/client/src/pages/CreateEvent/CreateEvent.tsx @@ -0,0 +1,26 @@ +import {useState} from 'react'; +import {useNavigate} from 'react-router-dom'; +import {ROUTER_URLS} from '../../constants/routerUrls'; + +const CreateEvent = () => { + const [eventTitle, setEventTitle] = useState(''); + const navigate = useNavigate(); + + const submitEventTitle = (event: React.FormEvent) => { + event.preventDefault(); + navigate(`${ROUTER_URLS.completeCreateEvent}?${new URLSearchParams({title: eventTitle})}`); + }; + + return ( +
+

행사 생성하기

+

시작할 행사 이름을 입력해 주세요.

+
+ setEventTitle(event.target.value)} /> + +
+
+ ); +}; + +export default CreateEvent; diff --git a/client/src/pages/CreateEvent/index.ts b/client/src/pages/CreateEvent/index.ts new file mode 100644 index 000000000..ac2c26d0c --- /dev/null +++ b/client/src/pages/CreateEvent/index.ts @@ -0,0 +1 @@ +export {default as CreateEventPage} from './CreateEvent'; From b287a347caab9cf20205c2dc1c9da154dc53e6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 01:01:14 +0900 Subject: [PATCH 025/273] =?UTF-8?q?feat:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=99=84=EB=A3=8C=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=ED=8D=BC=EB=B8=94=EB=A6=AC=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- .../CompleteCreateEvent.tsx | 34 +++++++++++++++++++ client/src/pages/CompleteCreateEvent/index.ts | 1 + 2 files changed, 35 insertions(+) create mode 100644 client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx create mode 100644 client/src/pages/CompleteCreateEvent/index.ts diff --git a/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx b/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx new file mode 100644 index 000000000..d8fdf9735 --- /dev/null +++ b/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx @@ -0,0 +1,34 @@ +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; +import {ROUTER_URLS} from '../../constants/routerUrls'; + +const CompleteCreateEvent = () => { + const [url, setUrl] = useState(''); + const navigate = useNavigate(); + const location = useLocation(); + + useEffect(() => { + const getUrl = async () => { + const eventTitle = location.search; + console.log(eventTitle); + + // const url = await fetch(); + setUrl('hangsapage'); + }; + + getUrl(); + }, []); + + return ( +
+

행사 개시

+

+ 행사가 성공적으로 개시됐어요 :) 행사 링크를 통해서 참여자 관리가 가능해요. 관리를 위해서 행사 관리 링크를 보관해 + 주세요. +

+ +
+ ); +}; + +export default CompleteCreateEvent; diff --git a/client/src/pages/CompleteCreateEvent/index.ts b/client/src/pages/CompleteCreateEvent/index.ts new file mode 100644 index 000000000..a1e4fa117 --- /dev/null +++ b/client/src/pages/CompleteCreateEvent/index.ts @@ -0,0 +1 @@ +export {default as CompleteCreateEventPage} from './CompleteCreateEvent'; From 367db233d479d8f496b831a74c831996ce1ea452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 01:01:38 +0900 Subject: [PATCH 026/273] =?UTF-8?q?design:=20=EC=A0=84=EC=97=AD=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=EB=A7=81=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/src/index.css | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 client/src/index.css diff --git a/client/src/index.css b/client/src/index.css new file mode 100644 index 000000000..c6eed01ac --- /dev/null +++ b/client/src/index.css @@ -0,0 +1,5 @@ +body { + max-width: 768px; + margin: 0 auto; + border: 1px solid gray; +} From 6b2c45a041967355289baa35ab483a67d7b28fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 01:02:42 +0900 Subject: [PATCH 027/273] =?UTF-8?q?feat:=20=EB=9D=BC=EC=9A=B0=ED=84=B0=20?= =?UTF-8?q?=EC=85=8B=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/src/router.tsx | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 client/src/router.tsx diff --git a/client/src/router.tsx b/client/src/router.tsx new file mode 100644 index 000000000..079abd426 --- /dev/null +++ b/client/src/router.tsx @@ -0,0 +1,35 @@ +import {createBrowserRouter} from 'react-router-dom'; +import App from './App'; +import {ROUTER_URLS} from './constants/routerUrls'; +import {MainPage} from './pages/Main'; +import {CreateEventPage} from './pages/CreateEvent'; +import {CompleteCreateEventPage} from './pages/CompleteCreateEvent'; +import {EventPage} from './pages/Event'; + +const router = createBrowserRouter([ + { + path: '', + element: , + children: [ + { + index: true, + path: ROUTER_URLS.main, + element: , + }, + { + path: ROUTER_URLS.createEvent, + element: , + }, + { + path: ROUTER_URLS.completeCreateEvent, + element: , + }, + { + path: ROUTER_URLS.eventManage, + element: , + }, + ], + }, +]); + +export default router; From fb6b0944d1d6aedaf1a925408d9be88e28e6580a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 01:03:03 +0900 Subject: [PATCH 028/273] =?UTF-8?q?feat:=20=EC=95=B1=EC=9D=98=20=EC=A7=84?= =?UTF-8?q?=EC=9E=85=EC=A0=90=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/src/App.tsx | 10 ++-------- client/src/index.tsx | 11 +++++++---- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/client/src/App.tsx b/client/src/App.tsx index 5a7e5f458..b6c73d8be 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,13 +1,7 @@ -import {css} from '@emotion/react'; -// co-authored-by test - -// 테스트 css props 사용 예제입니다. 추후 삭제 예정 -const style = css` - color: red; -`; +import {Outlet} from 'react-router-dom'; const App: React.FC = () => { - return
Hello, React with Webpack
; + return ; }; export default App; diff --git a/client/src/index.tsx b/client/src/index.tsx index e3791f790..a9cac3df9 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -1,9 +1,12 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import App from './App'; +import {RouterProvider} from 'react-router-dom'; +import router from './router'; +import './reset.css'; +import './index.css'; ReactDOM.createRoot(document.getElementById('root')!).render( - - - , + + + , ); From e102d59d34482f5e07e38b311078e4a14e2b293c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 01:03:49 +0900 Subject: [PATCH 029/273] =?UTF-8?q?feat:=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/src/constants/routerUrls.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 client/src/constants/routerUrls.ts diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts new file mode 100644 index 000000000..c93f9fefe --- /dev/null +++ b/client/src/constants/routerUrls.ts @@ -0,0 +1,7 @@ +export const ROUTER_URLS = { + main: '', + createEvent: '/create-event', + completeCreateEvent: '/create-event/complete', + event: '/event', + eventManage: '/event/:eventId', +}; From 3d4a4b98c8747f4b6f1f6723e3c69b5de41de311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 03:28:17 +0900 Subject: [PATCH 030/273] =?UTF-8?q?fix:=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20=EC=8B=9C=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EA=B0=80=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/webpack.config.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/webpack.config.js b/client/webpack.config.js index b002366f3..1c48c4260 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -16,6 +16,7 @@ export default { output: { path: path.join(__dirname, 'dist'), filename: 'bundle.min.js', + publicPath: '/', }, module: { rules: [ From 74378e6d8712318e64060fd7150ae20ad86215b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 03:29:13 +0900 Subject: [PATCH 031/273] =?UTF-8?q?feat:=20=EB=AA=A8=EB=8B=AC=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/src/components/Modal/Modal.style.ts | 23 ++++++++++++++++++++++ client/src/components/Modal/Modal.tsx | 19 ++++++++++++++++++ client/src/components/Modal/index.ts | 1 + 3 files changed, 43 insertions(+) create mode 100644 client/src/components/Modal/Modal.style.ts create mode 100644 client/src/components/Modal/Modal.tsx create mode 100644 client/src/components/Modal/index.ts diff --git a/client/src/components/Modal/Modal.style.ts b/client/src/components/Modal/Modal.style.ts new file mode 100644 index 000000000..727d0482f --- /dev/null +++ b/client/src/components/Modal/Modal.style.ts @@ -0,0 +1,23 @@ +import {css} from '@emotion/react'; + +export const modalBodyStyle = css` + z-index: 100; + background-color: white; + position: fixed; + bottom: 0; + left: 0; + right: 0; + padding: 20px; + border-radius: 20px 20px 0 0; + box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); +`; + +export const modalBackdropStyle = css` + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); + z-index: 99; +`; diff --git a/client/src/components/Modal/Modal.tsx b/client/src/components/Modal/Modal.tsx new file mode 100644 index 000000000..323262a2e --- /dev/null +++ b/client/src/components/Modal/Modal.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import {css} from '@emotion/react'; +import {modalBodyStyle, modalBackdropStyle} from './Modal.style'; + +interface ModalProps { + children: React.ReactNode; + onClose: () => void; +} + +const Modal = ({children, onClose}: ModalProps) => { + return ( + <> +
+
{children}
+ + ); +}; + +export default Modal; diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts new file mode 100644 index 000000000..1693a3eef --- /dev/null +++ b/client/src/components/Modal/index.ts @@ -0,0 +1 @@ +export {default as Modal} from './Modal'; From c3e7e64e0f5bdd399a916bfffe852fb44a3546d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 03:29:32 +0900 Subject: [PATCH 032/273] =?UTF-8?q?feat:=20=EC=8A=A4=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/src/components/Switch/Switch.style.tsx | 17 ++++++++++++ client/src/components/Switch/Switch.tsx | 27 +++++++++++++++++++ client/src/components/Switch/index.tsx | 1 + 3 files changed, 45 insertions(+) create mode 100644 client/src/components/Switch/Switch.style.tsx create mode 100644 client/src/components/Switch/Switch.tsx create mode 100644 client/src/components/Switch/index.tsx diff --git a/client/src/components/Switch/Switch.style.tsx b/client/src/components/Switch/Switch.style.tsx new file mode 100644 index 000000000..0e1b81b50 --- /dev/null +++ b/client/src/components/Switch/Switch.style.tsx @@ -0,0 +1,17 @@ +import {css} from '@emotion/react'; + +export const buttonStyle = (isActive: boolean) => css` + font-weight: ${isActive ? 'bold' : 'normal'}; + color: ${isActive ? '#333' : '#ccc'}; + padding: 10px; + cursor: pointer; +`; + +export const dividerStyle = css` + color: #ccc; +`; + +export const switchStyle = css` + display: flex; + align-items: center; +`; diff --git a/client/src/components/Switch/Switch.tsx b/client/src/components/Switch/Switch.tsx new file mode 100644 index 000000000..8fca98b73 --- /dev/null +++ b/client/src/components/Switch/Switch.tsx @@ -0,0 +1,27 @@ +import {buttonStyle, switchStyle} from './Switch.style'; +import React from 'react'; + +interface SwitchProps { + buttonList: string[]; + initialButton?: string; + curSwitch: string; + setSwitch: React.Dispatch>; +} + +const Switch = ({buttonList, initialButton = buttonList[0], setSwitch, curSwitch}: SwitchProps) => { + const handleButtonClick = (type: string) => { + setSwitch(type); + }; + + return ( +
+ {buttonList.map(buttonName => ( + + ))} +
+ ); +}; + +export default Switch; diff --git a/client/src/components/Switch/index.tsx b/client/src/components/Switch/index.tsx new file mode 100644 index 000000000..6c9915003 --- /dev/null +++ b/client/src/components/Switch/index.tsx @@ -0,0 +1 @@ +export {default as Switch} from './Switch'; From af02b4ee3d687817be4d4eab63438e2bff7db04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 03:30:32 +0900 Subject: [PATCH 033/273] =?UTF-8?q?feat:=20=EC=B4=88=EA=B8=B0=EC=9D=B8?= =?UTF-8?q?=EC=9B=90=20=EC=84=B8=ED=8C=85=20=EA=B8=B0=EB=8A=A5=20=ED=8D=BC?= =?UTF-8?q?=EB=B8=94=EB=A6=AC=EC=8B=B1=20=EB=B0=8F=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- .../SetInitialParticipants.style.ts | 35 ++++++++++++++ .../SetInitialParticipants.tsx | 47 +++++++++++++++++++ .../Modal/SetInitialParticipants/index.ts | 1 + 3 files changed, 83 insertions(+) create mode 100644 client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts create mode 100644 client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx create mode 100644 client/src/components/Modal/SetInitialParticipants/index.ts diff --git a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts new file mode 100644 index 000000000..7f666c8d1 --- /dev/null +++ b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts @@ -0,0 +1,35 @@ +import {css} from '@emotion/react'; + +export const inputStyle = css` + width: 100%; + padding: 10px; + border: 1px solid #ccc; + border-radius: 10px; + margin-bottom: 10px; +`; + +export const buttonStyle = (isActive: boolean) => css` + display: block; + width: 100%; + padding: 10px; + background-color: ${isActive ? '#B575FF' : '#e0e0e0'}; + border: none; + border-radius: 10px; + text-align: center; + color: ${isActive ? 'white' : '#999'}; + margin-top: 10px; +`; + +export const plusButtonStyle = css` + display: flex; + justify-content: center; + align-items: center; + width: 40px; + height: 40px; + background-color: #f5f5ff; + border: none; + border-radius: 50%; + color: #9e77ed; + font-size: 24px; + margin: 20px auto; +`; diff --git a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx new file mode 100644 index 000000000..115e4c576 --- /dev/null +++ b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx @@ -0,0 +1,47 @@ +import {useState} from 'react'; +import {buttonStyle, inputStyle, plusButtonStyle} from './SetInitialParticipants.style'; + +interface SetInitialParticipantsProps { + setParticipantsAndModalClose: (participants: string[]) => void; +} + +const SetInitialParticipants = ({setParticipantsAndModalClose}: SetInitialParticipantsProps) => { + const [value, setValue] = useState(''); + const [participants, setParticipants] = useState([]); + + const addParticipants = (event: React.FormEvent) => { + if (value === '') return; + + event.preventDefault(); + setParticipants(prev => [...prev, value]); + setValue(''); + }; + + return ( + <> +

초기 인원 설정하기

+ {participants.map((participant, index) => ( + + ))} +
+ setValue(event.target.value)} + /> + +
+ + + ); +}; + +export default SetInitialParticipants; diff --git a/client/src/components/Modal/SetInitialParticipants/index.ts b/client/src/components/Modal/SetInitialParticipants/index.ts new file mode 100644 index 000000000..c41b6a206 --- /dev/null +++ b/client/src/components/Modal/SetInitialParticipants/index.ts @@ -0,0 +1 @@ +export {default as SetInitialParticipants} from './SetInitialParticipants'; From 64192d02254e1b804be42c9d77b9046e0a797ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 03:32:48 +0900 Subject: [PATCH 034/273] =?UTF-8?q?feat:=20=ED=96=89=EB=8F=99=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EB=AA=A8=EB=8B=AC=20?= =?UTF-8?q?=EC=BB=A8=ED=85=90=EC=B8=A0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- .../SetActionModalContent.style.tsx | 24 +++++++++ .../SetActionModalContent.tsx | 52 +++++++++++++++++++ .../Modal/SetActionModalContent/index.ts | 1 + 3 files changed, 77 insertions(+) create mode 100644 client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.tsx create mode 100644 client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx create mode 100644 client/src/components/Modal/SetActionModalContent/index.ts diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.tsx b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.tsx new file mode 100644 index 000000000..48e975e9c --- /dev/null +++ b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.tsx @@ -0,0 +1,24 @@ +import {css} from '@emotion/react'; + +export const buttonStyle = (isActive: boolean) => css` + font-weight: ${isActive ? 'bold' : 'normal'}; + color: ${isActive ? '#333' : '#ccc'}; + padding: 10px; + cursor: pointer; +`; + +export const dividerStyle = css` + margin: 0 10px; + color: #ccc; +`; + +export const switchStyle = css` + display: flex; + align-items: center; +`; + +export const switchContainerStyle = css` + display: flex; + width: 100%; + justify-content: space-between; +`; diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx new file mode 100644 index 000000000..2fca07526 --- /dev/null +++ b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx @@ -0,0 +1,52 @@ +import {PurchaseInformation} from '../../../pages/Event/Event'; +import {Switch} from '../../../components/Switch'; +import SetPurchase from './SetPurchase'; +import {useState} from 'react'; +import UpdateParticipants from './UpdateParticipants'; +import {switchContainerStyle} from './SetActionModalContent.style'; + +// type ActionType = '지출' | '인원'; + +interface SetActionModalContentProps { + setOpen: React.Dispatch>; + participants: string[]; + setParticipants: React.Dispatch>; + purchaseInformation: PurchaseInformation; + setPurchaseInformation: React.Dispatch>; +} + +const SetActionModalContent = ({ + setOpen, + participants, + setParticipants, + purchaseInformation, + setPurchaseInformation, +}: SetActionModalContentProps) => { + const [actionType, setActionType] = useState('지출'); + const [participantType, setParticipantType] = useState('늦참'); + + return ( + <> +
+ + {actionType === '인원' && ( + + )} +
+ + {actionType === '지출' && ( + + )} + {actionType === '인원' && ( + + )} + + ); +}; + +export default SetActionModalContent; diff --git a/client/src/components/Modal/SetActionModalContent/index.ts b/client/src/components/Modal/SetActionModalContent/index.ts new file mode 100644 index 000000000..c7514135c --- /dev/null +++ b/client/src/components/Modal/SetActionModalContent/index.ts @@ -0,0 +1 @@ +export {default as SetActionModalContent} from './SetActionModalContent'; From 5ebfab3262a5d43b11a19a0e19a67397c1f4afbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 03:34:51 +0900 Subject: [PATCH 035/273] =?UTF-8?q?feat:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EA=B4=80=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- .../SetActionModalContent/SetPurchase.tsx | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 client/src/components/Modal/SetActionModalContent/SetPurchase.tsx diff --git a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx new file mode 100644 index 000000000..8506c2813 --- /dev/null +++ b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx @@ -0,0 +1,28 @@ +import {PurchaseInformation} from '../../../pages/Event/Event'; + +interface SetPurchaseProps { + setPurchaseInformation: (info: PurchaseInformation) => void; + purchaseInformation: PurchaseInformation; +} + +const SetPurchase = ({setPurchaseInformation, purchaseInformation}: SetPurchaseProps) => { + const handleNameChange = (e: React.ChangeEvent) => { + setPurchaseInformation({...purchaseInformation, name: e.target.value}); + }; + + const handlePriceChange = (e: React.ChangeEvent) => { + setPurchaseInformation({...purchaseInformation, price: parseFloat(e.target.value)}); + }; + + return ( + <> +
+ + +
+ + + ); +}; + +export default SetPurchase; From 077c88b89fb0494dd84db6d8a1e43e8525acd0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 03:35:04 +0900 Subject: [PATCH 036/273] =?UTF-8?q?feat:=20=EC=9D=B8=EC=9B=90=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EA=B8=B0=EB=8A=A5=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- .../UpdateParticipants.tsx | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx diff --git a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx new file mode 100644 index 000000000..0ec844f56 --- /dev/null +++ b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx @@ -0,0 +1,42 @@ +import {useState} from 'react'; + +interface UpdateParticipantsProps { + setOpen: React.Dispatch>; + participantType: string; + participants: string[]; + setParticipants: React.Dispatch>; +} + +const UpdateParticipants = ({setOpen, participantType, participants, setParticipants}: UpdateParticipantsProps) => { + const [name, setName] = useState(''); + + const updateParticipant = () => { + if (participantType === '늦참') { + if (participants.includes(name)) { + alert('이미 있는 사용자입니다.'); + return; + } + + setParticipants([...participants, name]); + } else if (participantType === '탈주') { + if (!participants.includes(name)) { + alert('그런 사용자는 없습니다. 올바른 이름을 입력해주세요.'); + return; + } + + setParticipants(prev => prev.filter(participant => participant !== name)); + } + + setName(''); + setOpen(false); + }; + + return ( +
+ setName(event.target.value)} value={name} /> + +
+ ); +}; + +export default UpdateParticipants; From 82b874386ab35eb36dfde18a671c1fb4a815f22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Tue, 16 Jul 2024 03:35:25 +0900 Subject: [PATCH 037/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=8D=BC=EB=B8=94?= =?UTF-8?q?=EB=A6=AC=EC=8B=B1=20=EB=B0=8F=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- client/src/pages/Event/Event.style.ts | 17 +++++++ client/src/pages/Event/Event.tsx | 72 +++++++++++++++++++++++++++ client/src/pages/Event/index.ts | 1 + 3 files changed, 90 insertions(+) create mode 100644 client/src/pages/Event/Event.style.ts create mode 100644 client/src/pages/Event/Event.tsx create mode 100644 client/src/pages/Event/index.ts diff --git a/client/src/pages/Event/Event.style.ts b/client/src/pages/Event/Event.style.ts new file mode 100644 index 000000000..517466c92 --- /dev/null +++ b/client/src/pages/Event/Event.style.ts @@ -0,0 +1,17 @@ +import {css} from '@emotion/react'; + +export const orderHeaderStyle = css` + display: flex; + justify-content: space-between; + align-items: center; + + width: 100%; +`; + +export const orderFooterStyle = css` + display: flex; + justify-content: space-between; + align-items: center; + + width: 100%; +`; diff --git a/client/src/pages/Event/Event.tsx b/client/src/pages/Event/Event.tsx new file mode 100644 index 000000000..4f311809d --- /dev/null +++ b/client/src/pages/Event/Event.tsx @@ -0,0 +1,72 @@ +import {SetInitialParticipants} from '../../components/Modal/SetInitialParticipants'; +import {Modal} from '../../components/Modal'; +import {useState} from 'react'; +import {useParams} from 'react-router-dom'; +import {SetActionModalContent} from '../../components/Modal/SetActionModalContent'; +import {orderFooterStyle, orderHeaderStyle} from './Event.style'; + +export type PurchaseInformation = { + name: string; + price: number; +}; + +const Event = () => { + const {eventId} = useParams(); + const [open, setOpen] = useState(false); + const [participants, setParticipants] = useState([]); + const [order, setOrder] = useState(0); + + const [purchaseInformation, setPurchaseInformation] = useState({ + name: '', + price: 0, + }); + + const setParticipantsAndModalClose = (participants: string[]) => { + setParticipants(participants); + setOrder(1); + setOpen(false); + }; + + return ( +
+

{eventId}

+

“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요.

+ {order > 0 && ( +
+
+

{`${order}차`}

+

{`${participants.length}명`}

+
+
+
{purchaseInformation.name}
+

{purchaseInformation.price.toLocaleString()}

+
+
+
총액
+

{purchaseInformation.price.toLocaleString()}

+
+
+ )} + + {open && ( + setOpen(false)}> + {participants.length === 0 ? ( + + ) : ( + + )} + + )} +
+ ); +}; + +export default Event; diff --git a/client/src/pages/Event/index.ts b/client/src/pages/Event/index.ts new file mode 100644 index 000000000..fa85db27a --- /dev/null +++ b/client/src/pages/Event/index.ts @@ -0,0 +1 @@ +export {default as EventPage} from './Event'; From e8adc5b00d311cc70ae3309ace3ec1e7a42d94a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A7=84=ED=98=B8?= Date: Wed, 17 Jul 2024 15:44:03 +0900 Subject: [PATCH 038/273] =?UTF-8?q?feat:=20=ED=95=B4=EC=BB=A4=ED=86=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EC=B6=9C=EB=A0=A5=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=9E=84=EC=8B=9C=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pakxe --- .../SetActionModalContent.tsx | 12 ++++-- .../SetActionModalContent/SetPurchase.tsx | 30 ++++++++++---- .../UpdateParticipants.tsx | 13 +++++- client/src/pages/Event/Event.tsx | 41 ++++++++++++++----- 4 files changed, 73 insertions(+), 23 deletions(-) diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx index 2fca07526..931dc523d 100644 --- a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx +++ b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx @@ -11,8 +11,8 @@ interface SetActionModalContentProps { setOpen: React.Dispatch>; participants: string[]; setParticipants: React.Dispatch>; - purchaseInformation: PurchaseInformation; - setPurchaseInformation: React.Dispatch>; + purchaseInformation: any; + setPurchaseInformation: any; } const SetActionModalContent = ({ @@ -35,7 +35,11 @@ const SetActionModalContent = ({
{actionType === '지출' && ( - + )} {actionType === '인원' && ( )} diff --git a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx index 8506c2813..b40176c78 100644 --- a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx +++ b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx @@ -1,26 +1,40 @@ +import {useState} from 'react'; import {PurchaseInformation} from '../../../pages/Event/Event'; interface SetPurchaseProps { - setPurchaseInformation: (info: PurchaseInformation) => void; - purchaseInformation: PurchaseInformation; + setOpen: React.Dispatch>; + setPurchaseInformation: any; + purchaseInformation: any; } -const SetPurchase = ({setPurchaseInformation, purchaseInformation}: SetPurchaseProps) => { +const SetPurchase = ({setOpen, setPurchaseInformation}: SetPurchaseProps) => { + const [newPurchaseInformation, setNewPurchaseInformation] = useState({ + name: '', + price: 0, + }); + const handleNameChange = (e: React.ChangeEvent) => { - setPurchaseInformation({...purchaseInformation, name: e.target.value}); + setNewPurchaseInformation({...newPurchaseInformation, name: e.target.value}); }; const handlePriceChange = (e: React.ChangeEvent) => { - setPurchaseInformation({...purchaseInformation, price: parseFloat(e.target.value)}); + setNewPurchaseInformation({...newPurchaseInformation, price: parseFloat(e.target.value)}); + }; + + const addPurchaseInformation = () => { + setPurchaseInformation((prev: PurchaseInformation[]) => [...prev, newPurchaseInformation]); + setOpen(false); }; return ( <>
- - + +
- + ); }; diff --git a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx index 0ec844f56..e64ceff53 100644 --- a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx +++ b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx @@ -5,9 +5,18 @@ interface UpdateParticipantsProps { participantType: string; participants: string[]; setParticipants: React.Dispatch>; + setPurchaseInformation: any; + purchaseInformation: any; } -const UpdateParticipants = ({setOpen, participantType, participants, setParticipants}: UpdateParticipantsProps) => { +const UpdateParticipants = ({ + setPurchaseInformation, + purchaseInformation, + setOpen, + participantType, + participants, + setParticipants, +}: UpdateParticipantsProps) => { const [name, setName] = useState(''); const updateParticipant = () => { @@ -18,6 +27,7 @@ const UpdateParticipants = ({setOpen, participantType, participants, setParticip } setParticipants([...participants, name]); + setPurchaseInformation([...purchaseInformation, {name, type: '늦참'}]); } else if (participantType === '탈주') { if (!participants.includes(name)) { alert('그런 사용자는 없습니다. 올바른 이름을 입력해주세요.'); @@ -25,6 +35,7 @@ const UpdateParticipants = ({setOpen, participantType, participants, setParticip } setParticipants(prev => prev.filter(participant => participant !== name)); + setPurchaseInformation([...purchaseInformation, {name, type: '탈주'}]); } setName(''); diff --git a/client/src/pages/Event/Event.tsx b/client/src/pages/Event/Event.tsx index 4f311809d..c7cb2d245 100644 --- a/client/src/pages/Event/Event.tsx +++ b/client/src/pages/Event/Event.tsx @@ -10,16 +10,23 @@ export type PurchaseInformation = { price: number; }; +type ParticipantType = { + name: string; + type: '늦참' | '탈주'; +}; + const Event = () => { const {eventId} = useParams(); const [open, setOpen] = useState(false); const [participants, setParticipants] = useState([]); const [order, setOrder] = useState(0); - const [purchaseInformation, setPurchaseInformation] = useState({ - name: '', - price: 0, - }); + const [purchaseInformation, setPurchaseInformation] = useState<(PurchaseInformation | ParticipantType)[]>([ + { + name: '', + price: 0, + } as PurchaseInformation, + ]); const setParticipantsAndModalClose = (participants: string[]) => { setParticipants(participants); @@ -37,14 +44,26 @@ const Event = () => {

{`${order}차`}

{`${participants.length}명`}

-
-
{purchaseInformation.name}
-

{purchaseInformation.price.toLocaleString()}

-
-
+ {purchaseInformation.map((information, index) => ( +
+ {'type' in information ? ( + <> +
+ {information.name} {information.type}입니다. +
+ + ) : ( + <> +
{information.name}
+

{information.price.toLocaleString()}원

+ + )} +
+ ))} + {/*
총액
-

{purchaseInformation.price.toLocaleString()}

-
+

{purchaseInformation.reduce((total, info) => 'price' in info ? total + info.price : total, 0).toLocaleString()}원

+
*/} )} + ); +}); + +export default IconButton; diff --git a/HDesign/src/components/IconButton/IconButton.type.ts b/HDesign/src/components/IconButton/IconButton.type.ts new file mode 100644 index 000000000..10415621c --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.type.ts @@ -0,0 +1,11 @@ +type IconButtonType = 'inputDelete' | 'plus' | 'buljusa'; + +export interface IconButtonStyleProps {} + +export interface IconButtonCustomProps { + iconType: IconButtonType; +} + +export type IconButtonOptionProps = IconButtonStyleProps & IconButtonCustomProps; + +export type IconButtonProps = React.ComponentProps<'button'> & IconButtonOptionProps; diff --git a/HDesign/src/components/InOutItem/InOutItem.stories.tsx b/HDesign/src/components/InOutItem/InOutItem.stories.tsx new file mode 100644 index 000000000..595e22b12 --- /dev/null +++ b/HDesign/src/components/InOutItem/InOutItem.stories.tsx @@ -0,0 +1,32 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import InOutItem from '@components/InOutItem/InOutItem'; + +const meta = { + title: 'Components/InOutItem', + component: InOutItem, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + names: { + description: '', + control: {type: 'text'}, + }, + inOutType: { + description: '', + control: {type: 'select', options: ['in', 'out']}, + }, + }, + args: { + names: ['감자', '토다리'], + inOutType: 'out', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/InOutItem/InOutItem.style.ts b/HDesign/src/components/InOutItem/InOutItem.style.ts new file mode 100644 index 000000000..b14dedae8 --- /dev/null +++ b/HDesign/src/components/InOutItem/InOutItem.style.ts @@ -0,0 +1,21 @@ +import {Theme} from '@/theme/theme.type'; +import {css} from '@emotion/react'; + +export const inOutItemStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'space-between', + padding: '0.5rem 0.5rem 0.5rem 0.25rem', + borderRadius: '0.5rem', + backgroundColor: theme.colors.white, + }); + +export const prefixStyle = css({ + display: 'flex', + gap: '0.25rem', +}); + +export const textStyle = (theme: Theme) => + css({ + color: theme.colors.black, + }); diff --git a/HDesign/src/components/InOutItem/InOutItem.tsx b/HDesign/src/components/InOutItem/InOutItem.tsx new file mode 100644 index 000000000..97548cd40 --- /dev/null +++ b/HDesign/src/components/InOutItem/InOutItem.tsx @@ -0,0 +1,26 @@ +/** @jsxImportSource @emotion/react */ +import React from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {InOutItemProps} from './InOutItem.type'; +import {inOutItemStyle, prefixStyle, textStyle} from './InOutItem.style'; +import Text from '@components/Text/Text'; +import IconButton from '../IconButton/IconButton'; + +export const InOutItem: React.FC = ({names = [], inOutType = 'out', ...htmlProps}: InOutItemProps) => { + const {theme} = useTheme(); + + // TODO: (@toari) : 사람 수 많을 때 UX writing 처리 + return ( +
+
+ + + {names.join(', ')} {inOutType === 'out' ? '나감' : '들어옴'} + +
+
+ ); +}; +export default InOutItem; diff --git a/HDesign/src/components/InOutItem/InOutItem.type.ts b/HDesign/src/components/InOutItem/InOutItem.type.ts new file mode 100644 index 000000000..c82fad4f8 --- /dev/null +++ b/HDesign/src/components/InOutItem/InOutItem.type.ts @@ -0,0 +1,12 @@ +export type InOutType = 'in' | 'out'; + +export interface InOutItemStyleProps {} + +export interface InOutItemCustomProps { + names?: string[]; + inOutType?: InOutType; +} + +export type InOutItemOptionProps = InOutItemStyleProps & InOutItemCustomProps; + +export type InOutItemProps = React.ComponentProps<'div'> & InOutItemOptionProps; diff --git a/HDesign/src/components/Input/Input.stories.tsx b/HDesign/src/components/Input/Input.stories.tsx new file mode 100644 index 000000000..da5df07ab --- /dev/null +++ b/HDesign/src/components/Input/Input.stories.tsx @@ -0,0 +1,28 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Input from '@components/Input/Input'; + +const meta = { + title: 'Components/Input', + component: Input, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + value: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + disabled: false, + placeholder: 'placeholder', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts new file mode 100644 index 000000000..b23ba358c --- /dev/null +++ b/HDesign/src/components/Input/Input.style.ts @@ -0,0 +1,27 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const inputBoxStyle = (theme: Theme) => + css({ + display: 'flex', + width: '100%', + justifyContent: 'space-between', + padding: '0.75rem 1rem', + borderRadius: '1rem', + backgroundColor: theme.colors.grayContainer, + }); + +export const inputStyle = (theme: Theme) => + css( + { + display: 'flex', + width: '100%', + color: theme.colors.black, + + '&:placeholder': { + color: theme.colors.gray, + }, + }, + theme.typography.body, + ); diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx new file mode 100644 index 000000000..8f6c35e1e --- /dev/null +++ b/HDesign/src/components/Input/Input.tsx @@ -0,0 +1,30 @@ +/** @jsxImportSource @emotion/react */ +import React, {forwardRef, useImperativeHandle, useRef} from 'react'; + +import IconButton from '@components/IconButton/IconButton'; +import {InputProps} from '@components/Input/Input.type'; +import {inputBoxStyle, inputStyle} from '@components/Input/Input.style'; +import {useInput} from '@components/Input/useInput'; + +import {useTheme} from '@theme/HDesignProvider'; + +export const Input: React.FC = forwardRef(function Input( + {value: propsValue, onChange, ...htmlProps}: InputProps, + ref, +) { + const {theme} = useTheme(); + const inputRef = useRef(null); + + useImperativeHandle(ref, () => inputRef.current!); + + const {value, handleChange, handleClickDelete} = useInput({propsValue, onChange, inputRef}); + + return ( +
+ + {value && } +
+ ); +}); + +export default Input; diff --git a/HDesign/src/components/Input/Input.type.ts b/HDesign/src/components/Input/Input.type.ts new file mode 100644 index 000000000..da35ca5ed --- /dev/null +++ b/HDesign/src/components/Input/Input.type.ts @@ -0,0 +1,11 @@ +import {Theme} from '@theme/theme.type'; + +export interface InputStyleProps { + theme?: Theme; +} + +export interface InputCustomProps {} + +export type InputOptionProps = InputStyleProps & InputCustomProps; + +export type InputProps = React.ComponentProps<'input'> & InputOptionProps; diff --git a/HDesign/src/components/Input/useInput.ts b/HDesign/src/components/Input/useInput.ts new file mode 100644 index 000000000..af4892964 --- /dev/null +++ b/HDesign/src/components/Input/useInput.ts @@ -0,0 +1,36 @@ +import {RefObject, useEffect, useState} from 'react'; + +interface UseInputProps { + propsValue: T; + onChange?: (e: React.ChangeEvent) => void; + inputRef: RefObject; +} + +export const useInput = ({propsValue, onChange, inputRef}: UseInputProps) => { + const [value, setValue] = useState(propsValue || ''); + + useEffect(() => { + setValue(propsValue || ''); + }, [propsValue]); + + const handleClickDelete = () => { + setValue(''); + + if (inputRef.current) { + inputRef.current.focus(); + } + + if (onChange) { + onChange({target: {value: ''}} as React.ChangeEvent); + } + }; + + const handleChange = (e: React.ChangeEvent) => { + setValue(e.target.value); + if (onChange) { + onChange(e); + } + }; + + return {value, handleChange, handleClickDelete}; +}; diff --git a/HDesign/src/components/StepItem/StepItem.stories.tsx b/HDesign/src/components/StepItem/StepItem.stories.tsx new file mode 100644 index 000000000..3a81c38f6 --- /dev/null +++ b/HDesign/src/components/StepItem/StepItem.stories.tsx @@ -0,0 +1,46 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import StepItem from '@components/StepItem/StepItem'; + +const meta = { + title: 'Components/StepItem', + component: StepItem, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + name: { + description: '', + control: {type: 'text'}, + }, + personCount: { + description: '', + control: {type: 'number'}, + }, + bills: { + description: '', + control: {type: 'object'}, + }, + }, + args: { + name: '으랏차차', + personCount: 8, + bills: [ + { + name: '뽕나무쟁이', + price: 150000, + }, + { + name: '인생네컷', + price: 12000, + }, + ], + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/StepItem/StepItem.style.ts b/HDesign/src/components/StepItem/StepItem.style.ts new file mode 100644 index 000000000..a82ff00e4 --- /dev/null +++ b/HDesign/src/components/StepItem/StepItem.style.ts @@ -0,0 +1,45 @@ +import {Theme} from '@/theme/theme.type'; +import {css} from '@emotion/react'; + +export const stepItemStyle = (theme: Theme) => + css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + padding: '0.5rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors.white, + }); + +export const headerStyle = css({ + display: 'flex', + justifyContent: 'space-between', + paddingInline: '0.5rem', +}); + +export const nameStyle = (theme: Theme) => + css({ + color: theme.colors.black, + }); + +export const personCountStyle = (theme: Theme) => + css({ + color: theme.colors.gray, + textDecoration: 'underline', + }); + +export const footerStyle = css({ + display: 'flex', + justifyContent: 'space-between', + paddingInline: '0.5rem', +}); + +export const totalTitleStyle = (theme: Theme) => + css({ + color: theme.colors.black, + }); + +export const totalAmountStyle = (theme: Theme) => + css({ + color: theme.colors.onSecondary, + }); diff --git a/HDesign/src/components/StepItem/StepItem.tsx b/HDesign/src/components/StepItem/StepItem.tsx new file mode 100644 index 000000000..43c52fa4c --- /dev/null +++ b/HDesign/src/components/StepItem/StepItem.tsx @@ -0,0 +1,48 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@/theme/HDesignProvider'; +import {StepItemCustomProps} from './StepItem.type'; +import { + footerStyle, + headerStyle, + nameStyle, + personCountStyle, + stepItemStyle, + totalAmountStyle, + totalTitleStyle, +} from './StepItem.style'; +import Text from '../Text/Text'; +import BillItem from '../BillItem/BillItem'; +import {BillItemCustomProps} from '../BillItem/BillItem.type'; + +export const StepItem: React.FC = ({ + name = '', + personCount = 0, + bills, + ...htmlProps +}: StepItemCustomProps) => { + const {theme} = useTheme(); + return ( +
+
+ + {name} + + + {personCount}명 + +
+ {bills.map((props: BillItemCustomProps) => ( + + ))} +
+ + 총액 + + + {bills.reduce((acc, prev) => acc + (prev.price ?? 0), 0).toLocaleString('ko-kr')} 원 + +
+
+ ); +}; +export default StepItem; diff --git a/HDesign/src/components/StepItem/StepItem.type.ts b/HDesign/src/components/StepItem/StepItem.type.ts new file mode 100644 index 000000000..516b7b675 --- /dev/null +++ b/HDesign/src/components/StepItem/StepItem.type.ts @@ -0,0 +1,13 @@ +import {BillItemCustomProps} from '../BillItem/BillItem.type'; + +export interface StepItemStyleProps {} + +export interface StepItemCustomProps { + name: string; + personCount: number; + bills: BillItemCustomProps[]; +} + +export type StepItemOptionProps = StepItemStyleProps & StepItemCustomProps; + +export type StepItemProps = React.ComponentProps<'div'> & StepItemOptionProps; diff --git a/HDesign/lib/components/Text/Text.stories.tsx b/HDesign/src/components/Text/Text.stories.tsx similarity index 94% rename from HDesign/lib/components/Text/Text.stories.tsx rename to HDesign/src/components/Text/Text.stories.tsx index 4c3b36bf2..5e5ec2287 100644 --- a/HDesign/lib/components/Text/Text.stories.tsx +++ b/HDesign/src/components/Text/Text.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import Text from './Text'; +import Text from '@components/Text/Text'; const meta = { title: 'Components/Text', diff --git a/HDesign/lib/components/Text/Text.style.ts b/HDesign/src/components/Text/Text.style.ts similarity index 93% rename from HDesign/lib/components/Text/Text.style.ts rename to HDesign/src/components/Text/Text.style.ts index b7ab8a2fe..356f9b0a0 100644 --- a/HDesign/lib/components/Text/Text.style.ts +++ b/HDesign/src/components/Text/Text.style.ts @@ -1,9 +1,9 @@ -import {css} from '@emotion/react'; - import type {TextProps} from './Text'; +import {css} from '@emotion/react'; + // TODO: (@todari) themeProvider 이용하도록 변경 -import TYPOGRAPHY from '../../token/typography'; +import TYPOGRAPHY from '@token/typography'; export const getSizeStyling = (size: Required['size']) => { const style = { diff --git a/HDesign/lib/components/Text/Text.tsx b/HDesign/src/components/Text/Text.tsx similarity index 73% rename from HDesign/lib/components/Text/Text.tsx rename to HDesign/src/components/Text/Text.tsx index a200648ea..f39428c8d 100644 --- a/HDesign/lib/components/Text/Text.tsx +++ b/HDesign/src/components/Text/Text.tsx @@ -1,15 +1,17 @@ /** @jsxImportSource @emotion/react */ -import React from 'react'; -import type {Size} from './Text.type'; +import type {Size} from '@components/Text/Text.type'; + import type {ComponentPropsWithoutRef} from 'react'; +import React from 'react'; + import {getSizeStyling} from './Text.style'; export interface TextProps extends ComponentPropsWithoutRef<'p'> { size?: Size | 'bodyBold' | 'smallBodyBold' | 'captionBold'; } -const Text: React.FC = ({size = 'body', children, ...attributes}: TextProps) => { +const Text: React.FC = ({size = 'body', children, ...attributes}: TextProps) => { return (

{children} diff --git a/HDesign/lib/components/Text/Text.type.ts b/HDesign/src/components/Text/Text.type.ts similarity index 100% rename from HDesign/lib/components/Text/Text.type.ts rename to HDesign/src/components/Text/Text.type.ts diff --git a/HDesign/src/components/Title/Title.stories.tsx b/HDesign/src/components/Title/Title.stories.tsx new file mode 100644 index 000000000..0b650b280 --- /dev/null +++ b/HDesign/src/components/Title/Title.stories.tsx @@ -0,0 +1,32 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Title from '@components/Title/Title'; + +const meta = { + title: 'Components/Title', + component: Title, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + title: { + description: '', + control: {type: 'text'}, + }, + description: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + title: '페이지 제목이에요', + description: '이곳에는 페이지 설명이 들어가요. 페이지에 대한 설명을 자세하게 적어주면 좋아요 :)', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Title/Title.style.ts b/HDesign/src/components/Title/Title.style.ts new file mode 100644 index 000000000..2b298d2cf --- /dev/null +++ b/HDesign/src/components/Title/Title.style.ts @@ -0,0 +1,21 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const titleContainerStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + + padding: '0 1rem', +}); + +export const titleStyle = (theme: Theme) => + css({ + color: theme.colors.black, + }); + +export const descriptionStyle = (theme: Theme) => + css({ + color: theme.colors.darkGray, + }); diff --git a/HDesign/src/components/Title/Title.tsx b/HDesign/src/components/Title/Title.tsx new file mode 100644 index 000000000..556c037e4 --- /dev/null +++ b/HDesign/src/components/Title/Title.tsx @@ -0,0 +1,20 @@ +/** @jsxImportSource @emotion/react */ +import Text from '@components/Text/Text'; +import {descriptionStyle, titleContainerStyle, titleStyle} from '@components/Title/Title.style'; +import {TitleProps} from '@components/Title/Title.type'; + +import {useTheme} from '@theme/HDesignProvider'; + +export const Title: React.FC = ({title, description}: TitleProps) => { + const {theme} = useTheme(); + return ( +

+ + {title} + + {description} +
+ ); +}; + +export default Title; diff --git a/HDesign/src/components/Title/Title.type.ts b/HDesign/src/components/Title/Title.type.ts new file mode 100644 index 000000000..fa3fb4e3f --- /dev/null +++ b/HDesign/src/components/Title/Title.type.ts @@ -0,0 +1,10 @@ +export interface TitleStyleProps {} + +export interface TitleCustomProps { + title: string; + description?: string; +} + +export type TitleOptionProps = TitleStyleProps & TitleCustomProps; + +export type TitleProps = React.ComponentProps<'div'> & TitleOptionProps; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx new file mode 100644 index 000000000..8c010bca0 --- /dev/null +++ b/HDesign/src/index.tsx @@ -0,0 +1,26 @@ +import BillItem from '@components/BillItem/BillItem'; +import BottomSheet from '@components/BottomSheet/BottomSheet'; +import Button from '@components/Button/Button'; +import FixedButton from '@components/FixedButton/FixedButton'; +import IconButton from '@components/IconButton/IconButton'; +import InOutItem from '@components/InOutItem/InOutItem'; +import Input from '@components/Input/Input'; +import StepItem from '@components/StepItem/StepItem'; +import Text from '@components/Text/Text'; +import Title from '@components/Title/Title'; + +import {HDesignProvider} from '@theme/HDesignProvider'; + +export { + BillItem, + BottomSheet, + Button, + FixedButton, + IconButton, + InOutItem, + Input, + StepItem, + Text, + Title, + HDesignProvider, +}; diff --git a/HDesign/lib/theme/GlobalStyle.ts b/HDesign/src/theme/GlobalStyle.ts similarity index 94% rename from HDesign/lib/theme/GlobalStyle.ts rename to HDesign/src/theme/GlobalStyle.ts index 08cd8094e..cbef1c8ea 100644 --- a/HDesign/lib/theme/GlobalStyle.ts +++ b/HDesign/src/theme/GlobalStyle.ts @@ -24,6 +24,7 @@ export const GlobalStyle = css` a, button { cursor: revert; + line-height: 0; } /* Remove list styles (bullets/numbers) */ @@ -34,12 +35,6 @@ export const GlobalStyle = css` list-style: none; } - /* For images to not be able to exceed their container */ - img { - max-inline-size: 100%; - max-block-size: 100%; - } - /* Removes spacing between cells in tables */ table { border-collapse: collapse; @@ -116,6 +111,5 @@ export const GlobalStyle = css` #root { display: flex; justify-content: center; - background-color: #eeeeee; } `; diff --git a/HDesign/lib/theme/HDesignProvider.tsx b/HDesign/src/theme/HDesignProvider.tsx similarity index 82% rename from HDesign/lib/theme/HDesignProvider.tsx rename to HDesign/src/theme/HDesignProvider.tsx index d196dba2d..6c7c571a3 100644 --- a/HDesign/lib/theme/HDesignProvider.tsx +++ b/HDesign/src/theme/HDesignProvider.tsx @@ -1,9 +1,11 @@ import React, {createContext, useContext, useState, ReactNode} from 'react'; import {Global} from '@emotion/react'; -import {COLORS} from '../token/colors'; -import {TYPOGRAPHY} from '../token/typography'; -import {Theme} from './theme.type'; -import {GlobalStyle} from './GlobalStyle'; + +import {Theme} from '@theme/theme.type'; +import {GlobalStyle} from '@theme/GlobalStyle'; + +import {COLORS} from '@token/colors'; +import {TYPOGRAPHY} from '@token/typography'; interface ThemeContextProps { theme: Theme; diff --git a/HDesign/src/theme/theme.type.ts b/HDesign/src/theme/theme.type.ts new file mode 100644 index 000000000..dffd961f0 --- /dev/null +++ b/HDesign/src/theme/theme.type.ts @@ -0,0 +1,7 @@ +import {ColorTokens} from '@token/colors'; +import {TypographyTokens} from '@token/typography'; + +export interface Theme { + colors: ColorTokens; + typography: TypographyTokens; +} diff --git a/HDesign/lib/token/colors.ts b/HDesign/src/token/colors.ts similarity index 84% rename from HDesign/lib/token/colors.ts rename to HDesign/src/token/colors.ts index 668f1c272..73f7b4f7f 100644 --- a/HDesign/lib/token/colors.ts +++ b/HDesign/src/token/colors.ts @@ -33,6 +33,8 @@ export type ColorTokens = Record; // TODO: (@soha) 대괄호 사용에 대해 논의 export const COLORS: ColorTokens = { white: PRIMITIVE_COLORS.white, + gray: PRIMITIVE_COLORS.gray[400], + darkGray: PRIMITIVE_COLORS.gray[500], black: PRIMITIVE_COLORS.gray[700], primary: PRIMITIVE_COLORS.purple[300], onPrimary: PRIMITIVE_COLORS.white, @@ -40,4 +42,6 @@ export const COLORS: ColorTokens = { onSecondary: PRIMITIVE_COLORS.purple[600], tertiary: PRIMITIVE_COLORS.gray[200], onTertiary: PRIMITIVE_COLORS.gray[700], + grayContainer: PRIMITIVE_COLORS.gray[100], + lightGrayContainer: PRIMITIVE_COLORS.gray[50], }; diff --git a/HDesign/lib/token/typography.ts b/HDesign/src/token/typography.ts similarity index 100% rename from HDesign/lib/token/typography.ts rename to HDesign/src/token/typography.ts diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json index 4f0fd007a..6cbcf91bd 100644 --- a/HDesign/tsconfig.json +++ b/HDesign/tsconfig.json @@ -1,43 +1,30 @@ { "compilerOptions": { "sourceMap": true, - "module": "ES2020", - "target": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "useDefineForClassFields": true, - "removeComments": true, + "outDir": "./dist", + "target": "ES5", "skipLibCheck": true, - - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - - "jsx": "react-jsx", + "module": "commonjs", + "moduleResolution": "node", "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true, - - // "types": ["jest"], + "declaration": true, + "declarationDir": "./dist", "esModuleInterop": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictBindCallApply": true, - "strictPropertyInitialization": true, - "noImplicitAny": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noImplicitReturns": true, "forceConsistentCasingInFileNames": true, - "jsxImportSource": "@emotion/react", - - "baseUrl": "./", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "jsx": "react-jsx", + "allowJs": true, + "baseUrl": ".", "paths": { - "components/*": ["lib/components/*"] + "@/*": ["src/*"], + "@components/*": ["src/components/*"], + "@token/*": ["src/token/*"], + "@theme/*": ["src/theme/*"], + "@assets/*": ["src/assets/*"] }, - "outDir": "./dist" + "jsxImportSource": "@emotion/react", + "allowSyntheticDefaultImports": true }, - "include": ["lib"] + "include": ["src"], + "exclude": ["./node_modules", "dist"] } diff --git a/HDesign/webpack.config.js b/HDesign/webpack.config.js deleted file mode 100644 index e179524bc..000000000 --- a/HDesign/webpack.config.js +++ /dev/null @@ -1,44 +0,0 @@ -import path from 'path'; -import {fileURLToPath} from 'url'; - -import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; -import {ModifySourcePlugin, ConcatOperation} from 'modify-source-webpack-plugin'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -export default { - mode: 'development', - entry: './lib/index.ts', - resolve: { - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }, - output: { - path: path.join(__dirname, 'dist'), - filename: 'bundle.min.js', - }, - module: { - rules: [ - { - test: /\.tsx?$/, - loader: 'ts-loader', - exclude: /node_modules/, - }, - ], - }, - plugins: [ - new ForkTsCheckerWebpackPlugin(), - new ModifySourcePlugin({ - rules: [ - { - test: /\.tsx$/i, - operations: [new ConcatOperation('start', '/** @jsxImportSource @emotion/react */\n\n')], - }, - ], - }), - ], - devServer: { - port: 3000, - hot: true, - }, -}; From e6fe89417ffd1e6293114e5c62205eda770d7d75 Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:18:52 +0900 Subject: [PATCH 045/273] =?UTF-8?q?feat:=20CI/CD=20=ED=8C=8C=EC=9D=B4?= =?UTF-8?q?=ED=94=84=EB=9D=BC=EC=9D=B8=20=EA=B5=AC=EC=B6=95=20(#42)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 --- .github/workflows/backend-pull-request.yml | 34 +++++++++++ .github/workflows/backend-push.yml | 68 ++++++++++++++++++++++ server/Dockerfile | 17 ++++++ 3 files changed, 119 insertions(+) create mode 100644 .github/workflows/backend-pull-request.yml create mode 100644 .github/workflows/backend-push.yml create mode 100644 server/Dockerfile diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml new file mode 100644 index 000000000..a5cfbfda7 --- /dev/null +++ b/.github/workflows/backend-pull-request.yml @@ -0,0 +1,34 @@ +name: backend-pull-request + +on: + pull_request: + branches: [ "main", "develop" ] + paths: + - 'server/**' + +jobs: + build: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./server + + permissions: + contents: read + + steps: + - name: CheckOut + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Test with Gradle Wrapper + run: ./gradlew clean build diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml new file mode 100644 index 000000000..5a8d5f4ef --- /dev/null +++ b/.github/workflows/backend-push.yml @@ -0,0 +1,68 @@ +name: backend-push + +on: + push: + branches: [ "main", "develop" ] + paths: + - 'server/**' + +jobs: + build: + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ./server + + permissions: + contents: read + + steps: + - name: CheckOut + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Test with Gradle Wrapper + run: ./gradlew test + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Set up Docker BuildX + uses: docker/setup-buildx-action@v3 + + - name: Build and push + run: | + docker buildx build --platform linux/arm64 -t \ + ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev --push . + + deploy: + needs: build + runs-on: self-hosted + steps: + - name: Docker remove + run: | + CONTAINER_IDS=$(sudo docker ps -qa) + if [ -n "$CONTAINER_IDS" ]; then + sudo docker rm -f $CONTAINER_IDS + else + echo "No running containers found." + fi + + - name: Docker Image pull + run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev + + - name: Docker run + run: sudo docker run -d -p 80:8080 --name haengdong-backend-dev haengdong/haengdong-backend-dev diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 000000000..38c565c85 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,17 @@ +FROM gradle:7.6.1-jdk17 AS build + +WORKDIR /app + +COPY . /app + +RUN gradle clean build -x test + +FROM openjdk:17-jdk-slim + +WORKDIR /app + +COPY --from=build /app/build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar + +EXPOSE 8080 +ENTRYPOINT ["java"] +CMD ["-jar", "haengdong-0.0.1-SNAPSHOT.jar"] From bd1b976e605b85043a3ee279b3bc0a93259f47e0 Mon Sep 17 00:00:00 2001 From: kunsanglee Date: Thu, 18 Jul 2024 14:55:05 +0900 Subject: [PATCH 046/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../haengdong/application/EventService.java | 25 +++++++++ .../application/request/EventAppRequest.java | 10 ++++ .../response/EventAppResponse.java | 10 ++++ .../java/server/haengdong/domain/Event.java | 5 ++ .../haengdong/domain/EventTokenProvider.java | 12 +++++ .../persistence/EventRepository.java | 9 ++++ .../presentation/EventController.java | 26 ++++++++++ .../request/EventSaveRequest.java | 10 ++++ .../application/EventServiceTest.java | 35 +++++++++++++ .../presentation/EventControllerTest.java | 51 +++++++++++++++++++ 10 files changed, 193 insertions(+) create mode 100644 server/src/main/java/server/haengdong/application/EventService.java create mode 100644 server/src/main/java/server/haengdong/application/request/EventAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/response/EventAppResponse.java create mode 100644 server/src/main/java/server/haengdong/domain/EventTokenProvider.java create mode 100644 server/src/main/java/server/haengdong/persistence/EventRepository.java create mode 100644 server/src/main/java/server/haengdong/presentation/EventController.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java create mode 100644 server/src/test/java/server/haengdong/application/EventServiceTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/EventControllerTest.java diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java new file mode 100644 index 000000000..deac413a4 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -0,0 +1,25 @@ +package server.haengdong.application; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.domain.Event; +import server.haengdong.domain.EventTokenProvider; +import server.haengdong.persistence.EventRepository; + +@RequiredArgsConstructor +@Service +public class EventService { + + private final EventRepository eventRepository; + private final EventTokenProvider eventTokenProvider; + + public EventAppResponse saveEvent(EventAppRequest request) { + String token = eventTokenProvider.createToken(); + Event event = request.toEvent(token); + eventRepository.save(event); + + return EventAppResponse.of(event); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java new file mode 100644 index 000000000..8db47eba9 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java @@ -0,0 +1,10 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.Event; + +public record EventAppRequest(String name) { + + public Event toEvent(String token) { + return new Event(name, token); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java new file mode 100644 index 000000000..37b63dec2 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.Event; + +public record EventAppResponse(String token) { + + public static EventAppResponse of(Event event) { + return new EventAppResponse(event.getToken()); + } +} diff --git a/server/src/main/java/server/haengdong/domain/Event.java b/server/src/main/java/server/haengdong/domain/Event.java index f4a13e4b1..8c24edc4d 100644 --- a/server/src/main/java/server/haengdong/domain/Event.java +++ b/server/src/main/java/server/haengdong/domain/Event.java @@ -20,4 +20,9 @@ public class Event { private String name; private String token; + + public Event(String name, String token) { + this.name = name; + this.token = token; + } } diff --git a/server/src/main/java/server/haengdong/domain/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/EventTokenProvider.java new file mode 100644 index 000000000..54d455f35 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/EventTokenProvider.java @@ -0,0 +1,12 @@ +package server.haengdong.domain; + +import java.util.UUID; +import org.springframework.stereotype.Component; + +@Component +public class EventTokenProvider { + + public String createToken() { + return UUID.randomUUID().toString(); + } +} diff --git a/server/src/main/java/server/haengdong/persistence/EventRepository.java b/server/src/main/java/server/haengdong/persistence/EventRepository.java new file mode 100644 index 000000000..855fc80ad --- /dev/null +++ b/server/src/main/java/server/haengdong/persistence/EventRepository.java @@ -0,0 +1,9 @@ +package server.haengdong.persistence; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.Event; + +@Repository +public interface EventRepository extends JpaRepository { +} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java new file mode 100644 index 000000000..5254a78ae --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -0,0 +1,26 @@ +package server.haengdong.presentation; + +import java.net.URI; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.EventService; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.presentation.request.EventSaveRequest; + +@RequiredArgsConstructor +@RestController +public class EventController { + + private final EventService eventService; + + @PostMapping("/api/events") + public ResponseEntity saveEvent(EventSaveRequest request) { + EventAppResponse eventAppResponse = eventService.saveEvent(request.toAppRequest()); + + return ResponseEntity.ok() + .location(URI.create("events/" + eventAppResponse.token())) + .build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java new file mode 100644 index 000000000..8bd4cfda8 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.request; + +import server.haengdong.application.request.EventAppRequest; + +public record EventSaveRequest(String name) { + + public EventAppRequest toAppRequest() { + return new EventAppRequest(name); + } +} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java new file mode 100644 index 000000000..5fef04b81 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -0,0 +1,35 @@ +package server.haengdong.application; + + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.domain.EventTokenProvider; + +@SpringBootTest +class EventServiceTest { + + @Autowired + private EventService eventService; + + @MockBean + private EventTokenProvider eventTokenProvider; + + @DisplayName("행사를 생성한다") + @Test + void saveEventTest() { + EventAppRequest request = new EventAppRequest("test"); + given(eventTokenProvider.createToken()).willReturn("TOKEN"); + + EventAppResponse response = eventService.saveEvent(request); + + assertThat(response.token()).isEqualTo("TOKEN"); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java new file mode 100644 index 000000000..bed814ae3 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java @@ -0,0 +1,51 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import server.haengdong.application.EventService; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.presentation.request.EventSaveRequest; + +@WebMvcTest(EventController.class) +class EventControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private EventService eventService; + + @DisplayName("이벤트를 생성한다") + @Test + void saveEvent() throws Exception { + EventSaveRequest eventSaveRequest = new EventSaveRequest("test"); + String requestBody = objectMapper.writeValueAsString(eventSaveRequest); + String token = "TOKEN"; + EventAppResponse eventAppResponse = new EventAppResponse(token); + given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); + + mockMvc.perform(post("/api/events") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.redirectedUrl("events/" + token)); + } +} From 891786565179354b24f6089d58a7e49a5f2846e3 Mon Sep 17 00:00:00 2001 From: Arachneee Date: Thu, 18 Jul 2024 19:39:03 +0900 Subject: [PATCH 047/273] =?UTF-8?q?feat:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/build.gradle | 1 + .../application/BillActionService.java | 48 +++++++++++++ .../haengdong/application/EventService.java | 2 +- .../request/BillActionAppRequest.java | 14 ++++ .../java/server/haengdong/domain/Action.java | 5 ++ .../server/haengdong/domain/BillAction.java | 17 +++-- .../persistence/ActionRepository.java | 21 ++++++ .../persistence/BillActionRepository.java | 13 ++++ .../persistence/EventRepository.java | 3 + .../presentation/BillActionController.java | 29 ++++++++ .../request/BillActionSaveRequest.java | 22 ++++++ .../request/BillActionsSaveRequest.java | 13 ++++ .../src/main/resources/application.properties | 1 - server/src/main/resources/application.yml | 15 ++++ .../application/BillActionServiceTest.java | 69 +++++++++++++++++++ .../BillActionControllerTest.java | 53 ++++++++++++++ 16 files changed, 320 insertions(+), 6 deletions(-) create mode 100644 server/src/main/java/server/haengdong/application/BillActionService.java create mode 100644 server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java create mode 100644 server/src/main/java/server/haengdong/persistence/ActionRepository.java create mode 100644 server/src/main/java/server/haengdong/persistence/BillActionRepository.java create mode 100644 server/src/main/java/server/haengdong/presentation/BillActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java delete mode 100644 server/src/main/resources/application.properties create mode 100644 server/src/main/resources/application.yml create mode 100644 server/src/test/java/server/haengdong/application/BillActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java diff --git a/server/build.gradle b/server/build.gradle index 43598d638..26f6ec262 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -26,6 +26,7 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java new file mode 100644 index 000000000..0aec7f6bd --- /dev/null +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -0,0 +1,48 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.BillActionAppRequest; +import server.haengdong.domain.Action; +import server.haengdong.domain.BillAction; +import server.haengdong.domain.Event; +import server.haengdong.persistence.ActionRepository; +import server.haengdong.persistence.BillActionRepository; +import server.haengdong.persistence.EventRepository; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class BillActionService { + + private final EventRepository eventRepository; + private final ActionRepository actionRepository; + private final BillActionRepository billActionRepository; + + @Transactional + public void saveAllBillAction(String eventToken, List requests) { + Event event = eventRepository.findByToken(eventToken) + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 이벤트 토큰입니다.")); + long lastSequence = getLastSequence(event); + + List billActions = new ArrayList<>(); + for (BillActionAppRequest request : requests) { + Action action = new Action(event, ++lastSequence); + BillAction billAction = request.toBillAction(action); + billActions.add(billAction); + } + billActionRepository.saveAll(billActions); + } + + private long getLastSequence(Event event) { + Optional lastAction = actionRepository.findLastByEvent(event); + if (lastAction.isPresent()) { + return lastAction.get().getSequence(); + } + return 0L; + } +} diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index deac413a4..6a5304e32 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -20,6 +20,6 @@ public EventAppResponse saveEvent(EventAppRequest request) { Event event = request.toEvent(token); eventRepository.save(event); - return EventAppResponse.of(event); + return EventAppResponse.of(event); } } diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java new file mode 100644 index 000000000..33c335737 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java @@ -0,0 +1,14 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.Action; +import server.haengdong.domain.BillAction; + +public record BillActionAppRequest( + String title, + Long price +) { + + public BillAction toBillAction(Action action) { + return new BillAction(action, title, price); + } +} diff --git a/server/src/main/java/server/haengdong/domain/Action.java b/server/src/main/java/server/haengdong/domain/Action.java index 7f782a1ac..7a47b1de5 100644 --- a/server/src/main/java/server/haengdong/domain/Action.java +++ b/server/src/main/java/server/haengdong/domain/Action.java @@ -23,4 +23,9 @@ public class Action { private Event event; private Long sequence; + + public Action(Event event, Long sequence) { + this.event = event; + this.sequence = sequence; + } } diff --git a/server/src/main/java/server/haengdong/domain/BillAction.java b/server/src/main/java/server/haengdong/domain/BillAction.java index e70abd644..8c0827445 100644 --- a/server/src/main/java/server/haengdong/domain/BillAction.java +++ b/server/src/main/java/server/haengdong/domain/BillAction.java @@ -1,12 +1,11 @@ package server.haengdong.domain; +import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToOne; -import java.math.BigDecimal; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; @@ -20,10 +19,20 @@ public class BillAction { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(fetch = FetchType.LAZY) + @OneToOne(cascade = CascadeType.PERSIST) private Action action; private String title; - private BigDecimal price; + private Long price; + + public BillAction(Action action, String title, Long price) { + this.action = action; + this.title = title; + this.price = price; + } + + public Long getSequence() { + return action.getSequence(); + } } diff --git a/server/src/main/java/server/haengdong/persistence/ActionRepository.java b/server/src/main/java/server/haengdong/persistence/ActionRepository.java new file mode 100644 index 000000000..72c573d91 --- /dev/null +++ b/server/src/main/java/server/haengdong/persistence/ActionRepository.java @@ -0,0 +1,21 @@ +package server.haengdong.persistence; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.Action; +import server.haengdong.domain.Event; + +@Repository +public interface ActionRepository extends JpaRepository { + + @Query(""" + SELECT a + FROM Action a + WHERE a.event = :event + ORDER BY a.sequence DESC + LIMIT 1 + """) + Optional findLastByEvent(Event event); +} diff --git a/server/src/main/java/server/haengdong/persistence/BillActionRepository.java b/server/src/main/java/server/haengdong/persistence/BillActionRepository.java new file mode 100644 index 000000000..96e47237a --- /dev/null +++ b/server/src/main/java/server/haengdong/persistence/BillActionRepository.java @@ -0,0 +1,13 @@ +package server.haengdong.persistence; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.BillAction; +import server.haengdong.domain.Event; + +@Repository +public interface BillActionRepository extends JpaRepository { + + List findByAction_Event(Event event); +} diff --git a/server/src/main/java/server/haengdong/persistence/EventRepository.java b/server/src/main/java/server/haengdong/persistence/EventRepository.java index 855fc80ad..8a83d751f 100644 --- a/server/src/main/java/server/haengdong/persistence/EventRepository.java +++ b/server/src/main/java/server/haengdong/persistence/EventRepository.java @@ -1,9 +1,12 @@ package server.haengdong.persistence; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import server.haengdong.domain.Event; @Repository public interface EventRepository extends JpaRepository { + + Optional findByToken(String token); } diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java new file mode 100644 index 000000000..139d6a470 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/BillActionController.java @@ -0,0 +1,29 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.BillActionService; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +@RequiredArgsConstructor +@RestController +public class BillActionController { + + private final BillActionService billActionService; + + @PostMapping("/api/events/{token}/actions/bills") + public ResponseEntity saveAllBillAction( + @PathVariable String token, + @RequestBody @Valid BillActionsSaveRequest request + ) { + billActionService.saveAllBillAction(token, request.toAppRequests()); + + return ResponseEntity.ok() + .build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java new file mode 100644 index 000000000..8d662050f --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java @@ -0,0 +1,22 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.Size; +import server.haengdong.application.request.BillActionAppRequest; + +public record BillActionSaveRequest( + + @NotNull + @Size(min = 2, max = 30) + String title, + + @NotNull + @Positive + Long price +) { + + public BillActionAppRequest toAppRequest() { + return new BillActionAppRequest(title, price); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java new file mode 100644 index 000000000..bb16dfda0 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java @@ -0,0 +1,13 @@ +package server.haengdong.presentation.request; + +import java.util.List; +import server.haengdong.application.request.BillActionAppRequest; + +public record BillActionsSaveRequest(List actions) { + + public List toAppRequests() { + return actions.stream() + .map(BillActionSaveRequest::toAppRequest) + .toList(); + } +} diff --git a/server/src/main/resources/application.properties b/server/src/main/resources/application.properties deleted file mode 100644 index df243b894..000000000 --- a/server/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=server diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml new file mode 100644 index 000000000..49c481eaa --- /dev/null +++ b/server/src/main/resources/application.yml @@ -0,0 +1,15 @@ +spring: + h2: + console: + enabled: true + path: /h2-console + datasource: + url: jdbc:h2:mem:database + jpa: + defer-datasource-initialization: true + show-sql: true + properties: + hibernate: + format_sql: true + hibernate: + ddl-auto: create-drop diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java new file mode 100644 index 000000000..ba0cfc41a --- /dev/null +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -0,0 +1,69 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; + +import java.util.Comparator; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.request.BillActionAppRequest; +import server.haengdong.domain.BillAction; +import server.haengdong.domain.Event; +import server.haengdong.persistence.BillActionRepository; +import server.haengdong.persistence.EventRepository; + +@SpringBootTest +class BillActionServiceTest { + + @Autowired + private BillActionService billActionService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @DisplayName("지출 내역을 생성한다.") + @Test + void saveAllBillAction() { + String token = "TOKEN"; + Event event = eventRepository.save(new Event("감자", token)); + + List requests = List.of( + new BillActionAppRequest("뽕족", 10_000L), + new BillActionAppRequest("인생맥주", 15_000L) + ); + + billActionService.saveAllBillAction(token, requests); + + List actions = billActionRepository.findByAction_Event(event) + .stream() + .sorted(Comparator.comparing(BillAction::getSequence).reversed()) + .limit(requests.size()) + .toList(); + + assertThat(actions).extracting("title", "price") + .containsExactly( + tuple("인생맥주", 15_000L), + tuple("뽕족", 10_000L) + ); + } + + @DisplayName("이벤트가 존재하지 않으면 지출 내역을 생성할 수 없다.") + @Test + void saveAllBillAction1() { + List requests = List.of( + new BillActionAppRequest("뽕족", 10_000L), + new BillActionAppRequest("인생맥주", 15_000L) + ); + + assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("존재하지 않는 이벤트 토큰입니다."); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java new file mode 100644 index 000000000..a3ae3d5c8 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java @@ -0,0 +1,53 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import server.haengdong.application.BillActionService; +import server.haengdong.presentation.request.BillActionSaveRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +@WebMvcTest(BillActionController.class) +class BillActionControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private BillActionService billActionService; + + @DisplayName("지출 내역을 생성한다.") + @Test + void saveAllBillAction() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("뽕족", 10_000L), + new BillActionSaveRequest("인생맥주", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String token = "TOKEN"; + doNothing().when(billActionService).saveAllBillAction(any(), any()); + + mockMvc.perform(post("/api/events/{token}/actions/bills", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } +} From 9d6aa7b2127d5cfc2e5f50b97e68137344c00cc5 Mon Sep 17 00:00:00 2001 From: juha Date: Fri, 19 Jul 2024 15:54:49 +0900 Subject: [PATCH 048/273] =?UTF-8?q?refactor:=20event=EC=9D=98=20=EB=A7=88?= =?UTF-8?q?=EC=A7=80=EB=A7=89=20action=20=EC=88=9C=EC=84=9C=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/haengdong/application/BillActionService.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java index 0aec7f6bd..3f85b0da1 100644 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -39,10 +39,8 @@ public void saveAllBillAction(String eventToken, List requ } private long getLastSequence(Event event) { - Optional lastAction = actionRepository.findLastByEvent(event); - if (lastAction.isPresent()) { - return lastAction.get().getSequence(); - } - return 0L; + return actionRepository.findLastByEvent(event) + .map(Action::getSequence) + .orElse(0L); } } From 75ee0137d3680b45cade6f9d8cb6d4e22c4ea7d1 Mon Sep 17 00:00:00 2001 From: juha Date: Fri, 19 Jul 2024 16:00:31 +0900 Subject: [PATCH 049/273] =?UTF-8?q?refactor:=20BillAction=20fetch=20type?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/main/java/server/haengdong/domain/BillAction.java | 3 ++- .../server/haengdong/persistence/BillActionRepository.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/server/haengdong/domain/BillAction.java b/server/src/main/java/server/haengdong/domain/BillAction.java index 8c0827445..24ab5a410 100644 --- a/server/src/main/java/server/haengdong/domain/BillAction.java +++ b/server/src/main/java/server/haengdong/domain/BillAction.java @@ -2,6 +2,7 @@ import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -19,7 +20,7 @@ public class BillAction { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(cascade = CascadeType.PERSIST) + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) private Action action; private String title; diff --git a/server/src/main/java/server/haengdong/persistence/BillActionRepository.java b/server/src/main/java/server/haengdong/persistence/BillActionRepository.java index 96e47237a..03db3056e 100644 --- a/server/src/main/java/server/haengdong/persistence/BillActionRepository.java +++ b/server/src/main/java/server/haengdong/persistence/BillActionRepository.java @@ -1,6 +1,7 @@ package server.haengdong.persistence; import java.util.List; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import server.haengdong.domain.BillAction; @@ -9,5 +10,6 @@ @Repository public interface BillActionRepository extends JpaRepository { + @EntityGraph(attributePaths = {"action"}) List findByAction_Event(Event event); } From ba220205f0a3d6f56459f689bd6c007bfd0dadb3 Mon Sep 17 00:00:00 2001 From: juha Date: Fri, 19 Jul 2024 16:04:56 +0900 Subject: [PATCH 050/273] =?UTF-8?q?test:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20mocking=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../haengdong/presentation/BillActionControllerTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java index a3ae3d5c8..f37ad109f 100644 --- a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java @@ -1,7 +1,5 @@ package server.haengdong.presentation; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doNothing; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -42,7 +40,6 @@ void saveAllBillAction() throws Exception { ); String requestBody = objectMapper.writeValueAsString(request); String token = "TOKEN"; - doNothing().when(billActionService).saveAllBillAction(any(), any()); mockMvc.perform(post("/api/events/{token}/actions/bills", token) .contentType(MediaType.APPLICATION_JSON) From 5ec0c4cbd7bb79523d846b7c88e6db2aa2d871c5 Mon Sep 17 00:00:00 2001 From: juha Date: Fri, 19 Jul 2024 16:09:07 +0900 Subject: [PATCH 051/273] =?UTF-8?q?refactor:=20=EC=A4=91=EC=9A=94=EB=8F=84?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=9D=BC=20=ED=95=84=EB=93=9C=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/server/haengdong/application/BillActionService.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java index 3f85b0da1..6c69e383f 100644 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -2,7 +2,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,9 +18,9 @@ @Service public class BillActionService { - private final EventRepository eventRepository; - private final ActionRepository actionRepository; private final BillActionRepository billActionRepository; + private final ActionRepository actionRepository; + private final EventRepository eventRepository; @Transactional public void saveAllBillAction(String eventToken, List requests) { From ced5660f160516954bfb0bbc50cc0bc7bf386b3a Mon Sep 17 00:00:00 2001 From: juha Date: Fri, 19 Jul 2024 16:26:14 +0900 Subject: [PATCH 052/273] =?UTF-8?q?fix:=20BillAction=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=20Dto=20=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/BillActionsSaveRequest.java | 3 ++- .../BillActionControllerTest.java | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java index bb16dfda0..68784039b 100644 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java @@ -1,9 +1,10 @@ package server.haengdong.presentation.request; +import jakarta.validation.Valid; import java.util.List; import server.haengdong.application.request.BillActionAppRequest; -public record BillActionsSaveRequest(List actions) { +public record BillActionsSaveRequest(@Valid List actions) { public List toAppRequests() { return actions.stream() diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java index f37ad109f..8bf2b292f 100644 --- a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java @@ -47,4 +47,23 @@ void saveAllBillAction() throws Exception { .andDo(print()) .andExpect(status().isOk()); } + + @DisplayName("title이 비어 있는 경우 지출 내역을 생성할 수 없다.") + @Test + void saveAllBillAction1() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("", 10_000L), + new BillActionSaveRequest("인생맥주", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String token = "TOKEN"; + + mockMvc.perform(post("/api/events/{token}/actions/bills", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isBadRequest()); + } } From 3d09f4503d4a70af3a2b685c860a0686d9799148 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:38:49 +0900 Subject: [PATCH 053/273] =?UTF-8?q?[FE]=20=EB=94=94=EC=9E=90=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=88=98=EC=A0=95=20(#46)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 Co-authored-by: Soyeon Choe Co-authored-by: pakxe --- HDesign/package-lock.json | 218 ++---------------- HDesign/package.json | 2 + HDesign/src/assets/arrow.svg | 3 + HDesign/src/assets/index.ts | 1 + HDesign/src/assets/inputDelete.svg | 6 +- .../src/components/BillItem/BillItem.style.ts | 14 -- HDesign/src/components/BillItem/BillItem.tsx | 32 +-- .../src/components/BillItem/BillItem.type.ts | 1 + .../DragHandleItem/DragHandleItem.stories.tsx | 31 +++ .../DragHandleItem/DragHandleItem.style.ts | 18 ++ .../DragHandleItem/DragHandleItem.tsx | 36 +++ .../ExpenseList/ExpenseList.stories.tsx | 29 +++ .../ExpenseList/ExpenseList.style.ts | 33 +++ .../components/ExpenseList/ExpenseList.tsx | 37 +++ .../ExpenseList/ExpenseList.type.ts | 8 + HDesign/src/components/Flex/Flex.tsx | 39 ++++ HDesign/src/components/Flex/Flex.type.ts | 18 ++ .../InOutItem/InOutItem.stories.tsx | 2 +- .../src/components/InOutItem/InOutItem.tsx | 23 +- .../components/InOutItem/InOutItem.type.ts | 1 + .../src/components/Input/Input.stories.tsx | 4 + HDesign/src/components/Input/Input.style.ts | 18 +- HDesign/src/components/Input/Input.tsx | 4 +- HDesign/src/components/Input/Input.type.ts | 6 +- .../src/components/StepItem/StepItem.style.ts | 14 +- HDesign/src/components/StepItem/StepItem.tsx | 23 +- .../src/components/Switch/Switch.stories.tsx | 39 ++++ HDesign/src/components/Switch/Switch.style.ts | 6 + HDesign/src/components/Switch/Switch.tsx | 26 +++ HDesign/src/components/Switch/Switch.type.ts | 6 + HDesign/src/components/Switch/useSwitch.ts | 24 ++ HDesign/src/components/Tab/Tab.stories.tsx | 25 ++ HDesign/src/components/Tab/Tab.style.ts | 51 ++++ HDesign/src/components/Tab/Tab.tsx | 54 +++++ HDesign/src/components/Tab/Tab.type.ts | 8 + HDesign/src/components/Text/Text.style.ts | 4 +- HDesign/src/components/Text/Text.tsx | 8 +- HDesign/src/components/Text/Text.type.ts | 22 +- .../TextButton/TextButton.stories.tsx | 50 ++++ .../components/TextButton/TextButton.style.ts | 13 ++ .../src/components/TextButton/TextButton.tsx | 23 ++ .../components/TextButton/TextButton.type.ts | 15 ++ .../src/components/Title/Title.stories.tsx | 5 + HDesign/src/components/Title/Title.style.ts | 31 ++- HDesign/src/components/Title/Title.tsx | 27 ++- HDesign/src/components/Title/Title.type.ts | 1 + .../src/components/TopNav/TopNav.stories.ts | 28 +++ HDesign/src/components/TopNav/TopNav.style.ts | 6 + HDesign/src/components/TopNav/TopNav.tsx | 24 ++ HDesign/src/components/TopNav/TopNav.type.ts | 5 + HDesign/src/token/colors.ts | 15 +- HDesign/src/types/strictPropsWithChildren.ts | 3 + .../changeCamelCaseToKebabCase.ts | 3 + 53 files changed, 843 insertions(+), 300 deletions(-) create mode 100644 HDesign/src/assets/arrow.svg create mode 100644 HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx create mode 100644 HDesign/src/components/DragHandleItem/DragHandleItem.style.ts create mode 100644 HDesign/src/components/DragHandleItem/DragHandleItem.tsx create mode 100644 HDesign/src/components/ExpenseList/ExpenseList.stories.tsx create mode 100644 HDesign/src/components/ExpenseList/ExpenseList.style.ts create mode 100644 HDesign/src/components/ExpenseList/ExpenseList.tsx create mode 100644 HDesign/src/components/ExpenseList/ExpenseList.type.ts create mode 100644 HDesign/src/components/Flex/Flex.tsx create mode 100644 HDesign/src/components/Flex/Flex.type.ts create mode 100644 HDesign/src/components/Switch/Switch.stories.tsx create mode 100644 HDesign/src/components/Switch/Switch.style.ts create mode 100644 HDesign/src/components/Switch/Switch.tsx create mode 100644 HDesign/src/components/Switch/Switch.type.ts create mode 100644 HDesign/src/components/Switch/useSwitch.ts create mode 100644 HDesign/src/components/Tab/Tab.stories.tsx create mode 100644 HDesign/src/components/Tab/Tab.style.ts create mode 100644 HDesign/src/components/Tab/Tab.tsx create mode 100644 HDesign/src/components/Tab/Tab.type.ts create mode 100644 HDesign/src/components/TextButton/TextButton.stories.tsx create mode 100644 HDesign/src/components/TextButton/TextButton.style.ts create mode 100644 HDesign/src/components/TextButton/TextButton.tsx create mode 100644 HDesign/src/components/TextButton/TextButton.type.ts create mode 100644 HDesign/src/components/TopNav/TopNav.stories.ts create mode 100644 HDesign/src/components/TopNav/TopNav.style.ts create mode 100644 HDesign/src/components/TopNav/TopNav.tsx create mode 100644 HDesign/src/components/TopNav/TopNav.type.ts create mode 100644 HDesign/src/types/strictPropsWithChildren.ts create mode 100644 HDesign/src/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase.ts diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 28469fd93..905b380c5 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", + "@svgr/webpack": "^8.1.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -27,7 +28,6 @@ "@storybook/react": "^8.2.2", "@storybook/react-webpack5": "^8.2.3", "@storybook/test": "^8.2.2", - "@svgr/webpack": "^8.1.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", @@ -65,7 +65,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -90,7 +89,6 @@ "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -99,7 +97,6 @@ "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -128,14 +125,12 @@ "node_modules/@babel/core/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 + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/@babel/core/node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -151,14 +146,12 @@ "node_modules/@babel/core/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -181,7 +174,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -193,7 +185,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", - "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -206,7 +197,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.24.8", "@babel/helper-validator-option": "^7.24.8", @@ -222,7 +212,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "dependencies": { "yallist": "^3.0.2" } @@ -231,7 +220,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -240,7 +228,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-environment-visitor": "^7.24.7", @@ -263,7 +250,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -272,7 +258,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", @@ -289,7 +274,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -298,7 +282,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -314,7 +297,6 @@ "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -330,8 +312,7 @@ "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/@babel/helper-environment-visitor": { "version": "7.24.7", @@ -371,7 +352,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", - "dev": true, "dependencies": { "@babel/traverse": "^7.24.8", "@babel/types": "^7.24.8" @@ -396,7 +376,6 @@ "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", @@ -415,7 +394,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", - "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -427,7 +405,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -436,7 +413,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-environment-visitor": "^7.24.7", @@ -453,7 +429,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.7", @@ -470,7 +445,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -483,7 +457,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", - "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -523,7 +496,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -532,7 +504,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", - "dev": true, "dependencies": { "@babel/helper-function-name": "^7.24.7", "@babel/template": "^7.24.7", @@ -547,7 +518,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", - "dev": true, "dependencies": { "@babel/template": "^7.24.7", "@babel/types": "^7.24.8" @@ -641,7 +611,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -657,7 +626,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -672,7 +640,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -689,7 +656,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -705,7 +671,6 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, "engines": { "node": ">=6.9.0" }, @@ -717,7 +682,6 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -729,7 +693,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -741,7 +704,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -756,7 +718,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -768,7 +729,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -795,7 +755,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -810,7 +769,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -825,7 +783,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -837,7 +794,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -849,7 +805,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -864,7 +819,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -876,7 +830,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -888,7 +841,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -900,7 +852,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -912,7 +863,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -924,7 +874,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -936,7 +885,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -951,7 +899,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -966,7 +913,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -981,7 +927,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -997,7 +942,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1012,7 +956,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1030,7 +973,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", - "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1047,7 +989,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1062,7 +1003,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1077,7 +1017,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1093,7 +1032,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1110,7 +1048,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-compilation-targets": "^7.24.8", @@ -1132,7 +1069,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -1141,7 +1077,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/template": "^7.24.7" @@ -1157,7 +1092,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1172,7 +1106,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1188,7 +1121,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1203,7 +1135,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1219,7 +1150,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", - "dev": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1235,7 +1165,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1267,7 +1196,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1283,7 +1211,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", - "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", "@babel/helper-function-name": "^7.24.7", @@ -1300,7 +1227,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1316,7 +1242,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1331,7 +1256,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -1347,7 +1271,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1362,7 +1285,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1378,7 +1300,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -1395,7 +1316,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", - "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.24.7", "@babel/helper-module-transforms": "^7.24.7", @@ -1413,7 +1333,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1429,7 +1348,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1445,7 +1363,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1460,7 +1377,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -1476,7 +1392,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -1492,7 +1407,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", - "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1510,7 +1424,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-replace-supers": "^7.24.7" @@ -1526,7 +1439,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -1542,7 +1454,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -1559,7 +1470,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1574,7 +1484,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1590,7 +1499,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.24.7", @@ -1608,7 +1516,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1623,7 +1530,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1638,7 +1544,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1653,7 +1558,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", @@ -1672,7 +1576,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", - "dev": true, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.24.7" }, @@ -1687,7 +1590,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1703,7 +1605,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" @@ -1719,7 +1620,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1734,7 +1634,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1749,7 +1648,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1765,7 +1663,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1780,7 +1677,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1795,7 +1691,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1810,7 +1705,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.24.8", @@ -1828,7 +1722,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1843,7 +1736,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1859,7 +1751,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1875,7 +1766,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1891,7 +1781,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.24.8", "@babel/helper-compilation-targets": "^7.24.8", @@ -1986,7 +1875,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -2012,7 +1900,6 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -2026,7 +1913,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -2046,7 +1932,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -2177,8 +2062,7 @@ "node_modules/@babel/regjsgen": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { "version": "7.24.8", @@ -4267,7 +4151,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "dev": true, "engines": { "node": ">=14" }, @@ -4283,7 +4166,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "dev": true, "engines": { "node": ">=14" }, @@ -4299,7 +4181,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "dev": true, "engines": { "node": ">=14" }, @@ -4315,7 +4196,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "dev": true, "engines": { "node": ">=14" }, @@ -4331,7 +4211,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "dev": true, "engines": { "node": ">=14" }, @@ -4347,7 +4226,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "dev": true, "engines": { "node": ">=14" }, @@ -4363,7 +4241,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "dev": true, "engines": { "node": ">=14" }, @@ -4379,7 +4256,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "dev": true, "engines": { "node": ">=12" }, @@ -4395,7 +4271,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", - "dev": true, "dependencies": { "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", @@ -4421,7 +4296,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4441,7 +4315,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dev": true, "dependencies": { "@babel/types": "^7.21.3", "entities": "^4.4.0" @@ -4458,7 +4331,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -4470,7 +4342,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4492,7 +4363,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", - "dev": true, "dependencies": { "cosmiconfig": "^8.1.3", "deepmerge": "^4.3.1", @@ -4513,7 +4383,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@babel/plugin-transform-react-constant-elements": "^7.21.3", @@ -4866,7 +4735,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -5981,8 +5849,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/aria-query": { "version": "5.1.3", @@ -6272,7 +6139,6 @@ "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -6286,7 +6152,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -6295,7 +6160,6 @@ "version": "0.10.4", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.1", "core-js-compat": "^3.36.1" @@ -6308,7 +6172,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2" }, @@ -6410,8 +6273,7 @@ "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "node_modules/brace-expansion": { "version": "2.0.1", @@ -6444,7 +6306,6 @@ "version": "4.23.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -6543,7 +6404,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, "engines": { "node": ">=10" }, @@ -6555,7 +6415,6 @@ "version": "1.0.30001642", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -6891,7 +6750,6 @@ "version": "3.37.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", - "dev": true, "dependencies": { "browserslist": "^4.23.0" }, @@ -6904,7 +6762,6 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -7022,7 +6879,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -7035,7 +6891,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, "engines": { "node": ">= 6" }, @@ -7065,7 +6920,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, "dependencies": { "css-tree": "~2.2.0" }, @@ -7078,7 +6932,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" @@ -7091,8 +6944,7 @@ "node_modules/csso/node_modules/mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" }, "node_modules/csstype": { "version": "3.1.3", @@ -7231,7 +7083,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -7391,7 +7242,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, "funding": [ { "type": "github", @@ -7432,7 +7282,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -7447,8 +7296,7 @@ "node_modules/electron-to-chromium": { "version": "1.4.827", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", - "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==", - "dev": true + "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -7794,7 +7642,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, "engines": { "node": ">=6" } @@ -8687,7 +8534,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9161,7 +9007,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -10234,7 +10079,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -10319,7 +10163,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -10470,8 +10313,7 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -10519,7 +10361,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -10587,8 +10428,7 @@ "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "node_modules/media-typer": { "version": "0.3.0", @@ -10843,7 +10683,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -10898,8 +10737,7 @@ "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -10926,7 +10764,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, "dependencies": { "boolbase": "^1.0.0" }, @@ -12134,14 +11971,12 @@ "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "node_modules/regenerate-unicode-properties": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dev": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -12158,7 +11993,6 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -12185,7 +12019,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -12202,7 +12035,6 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, "dependencies": { "jsesc": "~0.5.0" }, @@ -12214,7 +12046,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" } @@ -12638,7 +12469,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -12657,7 +12487,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -13087,14 +12916,12 @@ "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, "node_modules/svgo": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", - "dev": true, "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -13119,7 +12946,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, "engines": { "node": ">= 10" } @@ -13128,7 +12954,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", @@ -13144,7 +12969,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -13158,7 +12982,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, "dependencies": { "domelementtype": "^2.3.0" }, @@ -13173,7 +12996,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -13187,7 +13009,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "engines": { "node": ">=0.12" }, @@ -13576,8 +13397,7 @@ "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -13817,7 +13637,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, "engines": { "node": ">=4" } @@ -13826,7 +13645,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -13839,7 +13657,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true, "engines": { "node": ">=4" } @@ -13848,7 +13665,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, "engines": { "node": ">=4" } @@ -13959,7 +13775,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -14319,8 +14134,7 @@ "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { "version": "1.10.2", diff --git a/HDesign/package.json b/HDesign/package.json index afa1bc6e4..c7dbfca71 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -27,6 +27,7 @@ "@storybook/addon-interactions": "^8.2.2", "@storybook/addon-links": "^8.2.2", "@storybook/addon-onboarding": "^8.2.2", + "@storybook/addon-webpack5-compiler-swc": "^1.0.4", "@storybook/blocks": "^8.2.2", "@storybook/react": "^8.2.2", "@storybook/react-webpack5": "^8.2.3", @@ -55,6 +56,7 @@ }, "dependencies": { "@emotion/react": "^11.11.4", + "@svgr/webpack": "^8.1.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/HDesign/src/assets/arrow.svg b/HDesign/src/assets/arrow.svg new file mode 100644 index 000000000..4d8bac605 --- /dev/null +++ b/HDesign/src/assets/arrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/HDesign/src/assets/index.ts b/HDesign/src/assets/index.ts index b531ccc25..3f92063cd 100644 --- a/HDesign/src/assets/index.ts +++ b/HDesign/src/assets/index.ts @@ -1,3 +1,4 @@ export {default as InputDelete} from '@assets/inputDelete.svg'; export {default as Plus} from '@assets/plus.svg'; export {default as Buljusa} from '@assets/buljusa.svg'; +export {default as Arrow} from '@assets/arrow.svg'; diff --git a/HDesign/src/assets/inputDelete.svg b/HDesign/src/assets/inputDelete.svg index 7d3627744..06d850889 100644 --- a/HDesign/src/assets/inputDelete.svg +++ b/HDesign/src/assets/inputDelete.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/HDesign/src/components/BillItem/BillItem.style.ts b/HDesign/src/components/BillItem/BillItem.style.ts index 7d1c37c30..dceb9af92 100644 --- a/HDesign/src/components/BillItem/BillItem.style.ts +++ b/HDesign/src/components/BillItem/BillItem.style.ts @@ -1,20 +1,6 @@ import {Theme} from '@/theme/theme.type'; import {css} from '@emotion/react'; -export const billItemStyle = (theme: Theme) => - css({ - display: 'flex', - justifyContent: 'space-between', - padding: '0.5rem 0.5rem 0.5rem 0.25rem', - borderRadius: '0.5rem', - backgroundColor: theme.colors.lightGrayContainer, - }); - -export const prefixStyle = css({ - display: 'flex', - gap: '0.25rem', -}); - export const textStyle = (theme: Theme) => css({ color: theme.colors.black, diff --git a/HDesign/src/components/BillItem/BillItem.tsx b/HDesign/src/components/BillItem/BillItem.tsx index 7af1216d2..0823d8add 100644 --- a/HDesign/src/components/BillItem/BillItem.tsx +++ b/HDesign/src/components/BillItem/BillItem.tsx @@ -1,28 +1,30 @@ /** @jsxImportSource @emotion/react */ -import {css} from '@emotion/react'; import React from 'react'; - import {useTheme} from '@theme/HDesignProvider'; - import {BillItemProps} from './BillItem.type'; -import {billItemStyle, prefixStyle, textStyle} from './BillItem.style'; +import {textStyle} from './BillItem.style'; import Text from '@components/Text/Text'; -import IconButton from '../IconButton/IconButton'; +import DragHandleItem from '../DragHandleItem/DragHandleItem'; +import Flex from '../Flex/Flex'; -export const BillItem: React.FC = ({name = '', price = 0, ...htmlProps}: BillItemProps) => { +export const BillItem: React.FC = ({ + name = '', + price = 0, + hasDragHandle = false, + ...htmlProps +}: BillItemProps) => { const {theme} = useTheme(); return ( -
-
- - + + + {name} -
- - {price.toLocaleString('ko-kr')} 원 - -
+ + {price.toLocaleString('ko-kr')} 원 + + + ); }; export default BillItem; diff --git a/HDesign/src/components/BillItem/BillItem.type.ts b/HDesign/src/components/BillItem/BillItem.type.ts index 0fb48b8be..4d6487ac9 100644 --- a/HDesign/src/components/BillItem/BillItem.type.ts +++ b/HDesign/src/components/BillItem/BillItem.type.ts @@ -3,6 +3,7 @@ export interface BillItemStyleProps {} export interface BillItemCustomProps { name?: string; price?: number; + hasDragHandle?: boolean; } export type BillItemOptionProps = BillItemStyleProps & BillItemCustomProps; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx new file mode 100644 index 000000000..773c181a2 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx @@ -0,0 +1,31 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; + +const meta = { + title: 'Components/DragHandleItem', + component: DragHandleItem, + tags: ['autodocs'], + parameters: {}, + argTypes: { + backgroundColor: { + description: '', + control: {type: 'select'}, + options: ['white', 'gray', 'darkGray', 'black', 'primary', 'onPrimary', 'secondary', 'onSecondary'], + }, + hasDragHandle: { + description: '드래그할 수 있는 핸들러(불주사 자국)를 켜고 끌 수 있습니다.', + control: {type: 'boolean'}, + }, + }, + args: { + backgroundColor: 'white', + children: '이건 끌 수 있는 아이템을 위한 것', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts new file mode 100644 index 000000000..a08dfc574 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts @@ -0,0 +1,18 @@ +import {Theme} from '@/theme/theme.type'; +import {ColorKeys} from '@/token/colors'; +import {css} from '@emotion/react'; + +export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgroundColor: ColorKeys) => + css({ + display: 'flex', + justifyContent: 'space-between', + padding: hasDragHandle ? '0.5rem 0.5rem 0.5rem 0.25rem' : '0.5rem', + borderRadius: '0.5rem', + backgroundColor: theme.colors[backgroundColor], + }); + +export const prefixStyle = css({ + display: 'flex', + gap: '0.25rem', + width: '100%', +}); diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx new file mode 100644 index 000000000..8ae6aeb8c --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx @@ -0,0 +1,36 @@ +/** @jsxImportSource @emotion/react */ +import React from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import IconButton from '../IconButton/IconButton'; +import {StrictPropsWithChildren} from '@/types/strictPropsWithChildren'; +import {dragHandleItemStyle, prefixStyle} from './DragHandleItem.style'; +import {COLORS, ColorKeys} from '@/token/colors'; + +interface DragHandleItemCustomProps { + hasDragHandle?: boolean; + backgroundColor?: ColorKeys; +} + +export type DragHandleItemProps = React.ComponentProps<'div'> & DragHandleItemCustomProps; + +export const DragHandleItem = ({ + hasDragHandle = false, + backgroundColor = 'white', + children, + ...htmlProps +}: StrictPropsWithChildren) => { + const {theme} = useTheme(); + + // TODO: (@toari) : 사람 수 많을 때 UX writing 처리 + return ( +
+
+ {hasDragHandle && } + {children} +
+
+ ); +}; +export default DragHandleItem; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx b/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx new file mode 100644 index 000000000..ccf8e28de --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ExpenseList from '@components/ExpenseList/ExpenseList'; + +const meta = { + title: 'Components/ExpenseList', + component: ExpenseList, + tags: ['autodocs'], + argTypes: { + expenseList: { + description: '', + }, + }, + args: { + expenseList: [ + {name: '소하', price: 2000}, + {name: '토다리', price: 2000}, + {name: '웨디', price: 1080}, + {name: '쿠키', price: 3020}, + ], + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.style.ts b/HDesign/src/components/ExpenseList/ExpenseList.style.ts new file mode 100644 index 000000000..30d71de79 --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.style.ts @@ -0,0 +1,33 @@ +import {Theme} from '@/theme/theme.type'; +import {css} from '@emotion/react'; + +export const expenseItemStyle = () => + css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + height: '2.5rem', + padding: '0.5rem 1rem', + }); + +export const expenseItemLeftStyle = () => + css({ + display: 'flex', + alignItems: 'center', + gap: '1rem', + }); + +export const TextStyle = (theme: Theme) => + css({ + color: theme.colors.onTertiary, + }); + +export const expenseListStyle = (theme: Theme) => + css({ + width: '100%', + backgroundColor: theme.colors.white, + padding: '0.5rem 0', + borderRadius: '1rem', + height: '100%', + }); diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx new file mode 100644 index 000000000..0c1b8a771 --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.tsx @@ -0,0 +1,37 @@ +/** @jsxImportSource @emotion/react */ + +import {useTheme} from '@theme/HDesignProvider'; +import Text from '@components/Text/Text'; +import {Arrow} from '@assets/index'; + +import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; +import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle, TextStyle} from './ExpenseList.style'; + +// TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 +const ExpenseItem = ({name, price}: ExpenseItemProps) => { + const {theme} = useTheme(); + return ( + + ); +}; + +const ExpenseList = ({expenseList = []}: ExpenseListProps) => { + const {theme} = useTheme(); + return ( +
+ {expenseList.map(({name, price}, index: number) => ( + + ))} +
+ ); +}; + +export default ExpenseList; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.type.ts b/HDesign/src/components/ExpenseList/ExpenseList.type.ts new file mode 100644 index 000000000..9ab2aa8bb --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.type.ts @@ -0,0 +1,8 @@ +export interface ExpenseItemProps { + name: string; + price: number; +} + +export type ExpenseListProps = { + expenseList: ExpenseItemProps[]; +}; diff --git a/HDesign/src/components/Flex/Flex.tsx b/HDesign/src/components/Flex/Flex.tsx new file mode 100644 index 000000000..eb2530b31 --- /dev/null +++ b/HDesign/src/components/Flex/Flex.tsx @@ -0,0 +1,39 @@ +/** @jsxImportSource @emotion/react */ +import {StrictPropsWithChildren} from '@/types/strictPropsWithChildren'; +import {changeCamelCaseToKebabCase} from '@/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase'; +import {css} from '@emotion/react'; +import {FlexDirectionStrictType, FlexProps} from './Flex.type'; + +const flexStyle = ({ + justifyContent = 'flexStart', + alignItems = 'stretch', + flexDirection = 'row', + gap = '0', + padding = '0', + paddingInline = '0', + margin = '0', + width = 'auto', + height = 'auto', + ...rest +}: FlexProps) => + css({ + display: 'flex', + justifyContent: changeCamelCaseToKebabCase(justifyContent), + alignItems: changeCamelCaseToKebabCase(alignItems), + // TODO: (@weadie) as를 사용하지 않으면 방법이 없음. css의 flexDirection속성은 string을 받지 않고 명확한 속성명(ex row-reverse)를 받고 싶어함. 다만 as를 사용해도 된다고 생각한 근거는 케밥함수가 FlexDirectionType에 명시된 모든 타입을 정확하게 변환하며, 받는 문자열이 FlexDirectionType에 제한되기 때문. + flexDirection: changeCamelCaseToKebabCase(flexDirection) as FlexDirectionStrictType, + gap, + padding, + paddingInline, + margin, + width, + height, + ...rest, + }); + +// TODO: (@weadie) 지정된 프롭 말고 다른 프롭도 가져올 수 있게 하자. +const Flex = ({children, ...props}: StrictPropsWithChildren) => { + return
{children}
; +}; + +export default Flex; diff --git a/HDesign/src/components/Flex/Flex.type.ts b/HDesign/src/components/Flex/Flex.type.ts new file mode 100644 index 000000000..aeb90bc20 --- /dev/null +++ b/HDesign/src/components/Flex/Flex.type.ts @@ -0,0 +1,18 @@ +export type FlexDirectionType = 'row' | 'column' | 'rowReverse' | 'columnReverse'; +export type FlexDirectionStrictType = 'row' | 'column' | 'row-reverse' | 'column-reverse'; + +export interface FlexProps { + justifyContent?: 'flexStart' | 'center' | 'flexEnd' | 'spaceBetween' | 'spaceAround' | 'spaceEvenly'; + alignItems?: 'flexStart' | 'center' | 'flexEnd' | 'stretch' | 'baseline'; + flexDirection?: FlexDirectionType; + gap?: string; + padding?: string; + paddingInline?: string; + margin?: string; + width?: string; + height?: string; +} + +export interface ExtendedFlexProps extends FlexProps { + [key: string]: string | undefined; +} diff --git a/HDesign/src/components/InOutItem/InOutItem.stories.tsx b/HDesign/src/components/InOutItem/InOutItem.stories.tsx index 595e22b12..13ea625b5 100644 --- a/HDesign/src/components/InOutItem/InOutItem.stories.tsx +++ b/HDesign/src/components/InOutItem/InOutItem.stories.tsx @@ -12,7 +12,7 @@ const meta = { argTypes: { names: { description: '', - control: {type: 'text'}, + control: {type: 'object'}, }, inOutType: { description: '', diff --git a/HDesign/src/components/InOutItem/InOutItem.tsx b/HDesign/src/components/InOutItem/InOutItem.tsx index 97548cd40..37fd8bbd5 100644 --- a/HDesign/src/components/InOutItem/InOutItem.tsx +++ b/HDesign/src/components/InOutItem/InOutItem.tsx @@ -4,23 +4,26 @@ import React from 'react'; import {useTheme} from '@theme/HDesignProvider'; import {InOutItemProps} from './InOutItem.type'; -import {inOutItemStyle, prefixStyle, textStyle} from './InOutItem.style'; +import {prefixStyle, textStyle} from './InOutItem.style'; import Text from '@components/Text/Text'; import IconButton from '../IconButton/IconButton'; +import DragHandleItem from '../DragHandleItem/DragHandleItem'; -export const InOutItem: React.FC = ({names = [], inOutType = 'out', ...htmlProps}: InOutItemProps) => { +export const InOutItem: React.FC = ({ + names = [], + inOutType = 'out', + hasDragHandle = false, + ...htmlProps +}: InOutItemProps) => { const {theme} = useTheme(); // TODO: (@toari) : 사람 수 많을 때 UX writing 처리 return ( -
-
- - - {names.join(', ')} {inOutType === 'out' ? '나감' : '들어옴'} - -
-
+ + + {names.join(', ')} {inOutType === 'out' ? '나감' : '들어옴'} + + ); }; export default InOutItem; diff --git a/HDesign/src/components/InOutItem/InOutItem.type.ts b/HDesign/src/components/InOutItem/InOutItem.type.ts index c82fad4f8..0a7459ccc 100644 --- a/HDesign/src/components/InOutItem/InOutItem.type.ts +++ b/HDesign/src/components/InOutItem/InOutItem.type.ts @@ -5,6 +5,7 @@ export interface InOutItemStyleProps {} export interface InOutItemCustomProps { names?: string[]; inOutType?: InOutType; + hasDragHandle?: boolean; } export type InOutItemOptionProps = InOutItemStyleProps & InOutItemCustomProps; diff --git a/HDesign/src/components/Input/Input.stories.tsx b/HDesign/src/components/Input/Input.stories.tsx index da5df07ab..0f5187cb3 100644 --- a/HDesign/src/components/Input/Input.stories.tsx +++ b/HDesign/src/components/Input/Input.stories.tsx @@ -14,6 +14,10 @@ const meta = { description: '', control: {type: 'text'}, }, + inputType: { + // TODO: (@cookie) 스토리북 라디오버튼 보이도록 설정해야 함 + control: {type: 'radio'}, + }, }, args: { disabled: false, diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts index b23ba358c..f45b02ea2 100644 --- a/HDesign/src/components/Input/Input.style.ts +++ b/HDesign/src/components/Input/Input.style.ts @@ -1,15 +1,29 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; +import {InputType} from './Input.type'; -export const inputBoxStyle = (theme: Theme) => +const inputBoxBackgroundColorByInputType = (theme: Theme, inputType: InputType = 'input') => { + switch (inputType) { + case 'input': + return theme.colors.lightGrayContainer; + + case 'search': + return theme.colors.white; + + default: + return theme.colors.lightGrayContainer; + } +}; + +export const inputBoxStyle = (theme: Theme, inputType: InputType = 'input') => css({ display: 'flex', width: '100%', justifyContent: 'space-between', padding: '0.75rem 1rem', borderRadius: '1rem', - backgroundColor: theme.colors.grayContainer, + backgroundColor: inputBoxBackgroundColorByInputType(theme, inputType), }); export const inputStyle = (theme: Theme) => diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx index 8f6c35e1e..4e8ac6e5d 100644 --- a/HDesign/src/components/Input/Input.tsx +++ b/HDesign/src/components/Input/Input.tsx @@ -9,7 +9,7 @@ import {useInput} from '@components/Input/useInput'; import {useTheme} from '@theme/HDesignProvider'; export const Input: React.FC = forwardRef(function Input( - {value: propsValue, onChange, ...htmlProps}: InputProps, + {value: propsValue, onChange, inputType, ...htmlProps}: InputProps, ref, ) { const {theme} = useTheme(); @@ -20,7 +20,7 @@ export const Input: React.FC = forwardRef +
{value && }
diff --git a/HDesign/src/components/Input/Input.type.ts b/HDesign/src/components/Input/Input.type.ts index da35ca5ed..b2f2fc827 100644 --- a/HDesign/src/components/Input/Input.type.ts +++ b/HDesign/src/components/Input/Input.type.ts @@ -4,7 +4,11 @@ export interface InputStyleProps { theme?: Theme; } -export interface InputCustomProps {} +export type InputType = 'input' | 'search'; + +export interface InputCustomProps { + inputType?: InputType; +} export type InputOptionProps = InputStyleProps & InputCustomProps; diff --git a/HDesign/src/components/StepItem/StepItem.style.ts b/HDesign/src/components/StepItem/StepItem.style.ts index a82ff00e4..0cf47c7bb 100644 --- a/HDesign/src/components/StepItem/StepItem.style.ts +++ b/HDesign/src/components/StepItem/StepItem.style.ts @@ -11,12 +11,6 @@ export const stepItemStyle = (theme: Theme) => backgroundColor: theme.colors.white, }); -export const headerStyle = css({ - display: 'flex', - justifyContent: 'space-between', - paddingInline: '0.5rem', -}); - export const nameStyle = (theme: Theme) => css({ color: theme.colors.black, @@ -28,12 +22,6 @@ export const personCountStyle = (theme: Theme) => textDecoration: 'underline', }); -export const footerStyle = css({ - display: 'flex', - justifyContent: 'space-between', - paddingInline: '0.5rem', -}); - export const totalTitleStyle = (theme: Theme) => css({ color: theme.colors.black, @@ -41,5 +29,5 @@ export const totalTitleStyle = (theme: Theme) => export const totalAmountStyle = (theme: Theme) => css({ - color: theme.colors.onSecondary, + color: theme.colors.gray, }); diff --git a/HDesign/src/components/StepItem/StepItem.tsx b/HDesign/src/components/StepItem/StepItem.tsx index 43c52fa4c..c85fe61bc 100644 --- a/HDesign/src/components/StepItem/StepItem.tsx +++ b/HDesign/src/components/StepItem/StepItem.tsx @@ -1,18 +1,11 @@ /** @jsxImportSource @emotion/react */ import {useTheme} from '@/theme/HDesignProvider'; import {StepItemCustomProps} from './StepItem.type'; -import { - footerStyle, - headerStyle, - nameStyle, - personCountStyle, - stepItemStyle, - totalAmountStyle, - totalTitleStyle, -} from './StepItem.style'; +import {nameStyle, personCountStyle, stepItemStyle, totalAmountStyle, totalTitleStyle} from './StepItem.style'; import Text from '../Text/Text'; import BillItem from '../BillItem/BillItem'; import {BillItemCustomProps} from '../BillItem/BillItem.type'; +import Flex from '../Flex/Flex'; export const StepItem: React.FC = ({ name = '', @@ -23,25 +16,25 @@ export const StepItem: React.FC = ({ const {theme} = useTheme(); return (
-
+ {name} {personCount}명 -
+ {bills.map((props: BillItemCustomProps) => ( ))} -
- + + 총액 - + {bills.reduce((acc, prev) => acc + (prev.price ?? 0), 0).toLocaleString('ko-kr')} 원 -
+
); }; diff --git a/HDesign/src/components/Switch/Switch.stories.tsx b/HDesign/src/components/Switch/Switch.stories.tsx new file mode 100644 index 000000000..121e20992 --- /dev/null +++ b/HDesign/src/components/Switch/Switch.stories.tsx @@ -0,0 +1,39 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Switch from '@components/Switch/Switch'; + +const meta = { + title: 'Components/Switch', + component: Switch, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + value: { + description: '', + control: {type: 'select', options: ['홈', '관리']}, + }, + initialValue: { + description: '', + }, + values: { + description: '', + }, + onChange: { + description: '', + }, + }, + args: { + value: '홈', + initialValue: '홈', + values: ['홈', '관리'], + onChange: value => alert(`${value} 선택됨`), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Switch/Switch.style.ts b/HDesign/src/components/Switch/Switch.style.ts new file mode 100644 index 000000000..d88c18748 --- /dev/null +++ b/HDesign/src/components/Switch/Switch.style.ts @@ -0,0 +1,6 @@ +import {css} from '@emotion/react'; + +export const switchContainerStyle = css({ + display: 'flex', + gap: '0.75rem', +}); diff --git a/HDesign/src/components/Switch/Switch.tsx b/HDesign/src/components/Switch/Switch.tsx new file mode 100644 index 000000000..3ac505ff6 --- /dev/null +++ b/HDesign/src/components/Switch/Switch.tsx @@ -0,0 +1,26 @@ +/** @jsxImportSource @emotion/react */ +import TextButton from '../TextButton/TextButton'; +import {switchContainerStyle} from './Switch.style'; +import {SwitchProps} from './Switch.type'; +import {useSwitch} from './useSwitch'; + +const Switch = ({value = '', initialValue, values, onChange}: SwitchProps) => { + const {selectedValue, handleClick} = useSwitch({value, initialValue, values, onChange}); + + return ( +
+ {values.map((value, index) => ( + handleClick(index)} + > + {value} + + ))} +
+ ); +}; + +export default Switch; diff --git a/HDesign/src/components/Switch/Switch.type.ts b/HDesign/src/components/Switch/Switch.type.ts new file mode 100644 index 000000000..ec73febd0 --- /dev/null +++ b/HDesign/src/components/Switch/Switch.type.ts @@ -0,0 +1,6 @@ +export interface SwitchProps { + value?: string; + initialValue?: string; + values: string[]; + onChange: (value: string) => void; +} diff --git a/HDesign/src/components/Switch/useSwitch.ts b/HDesign/src/components/Switch/useSwitch.ts new file mode 100644 index 000000000..ecfbb0633 --- /dev/null +++ b/HDesign/src/components/Switch/useSwitch.ts @@ -0,0 +1,24 @@ +import {useEffect, useState} from 'react'; + +interface UseSwitchProps { + value: string; + initialValue?: string; + values: string[]; + onChange: (value: string) => void; +} + +export const useSwitch = ({value, initialValue, values, onChange}: UseSwitchProps) => { + const [selectedValue, setSelectedValue] = useState(initialValue ?? value); + + useEffect(() => { + setSelectedValue(value); + onChange(value); + }, [value]); + + const handleClick = (index: number) => { + setSelectedValue(values[index]); + onChange(values[index]); + }; + + return {selectedValue, handleClick}; +}; diff --git a/HDesign/src/components/Tab/Tab.stories.tsx b/HDesign/src/components/Tab/Tab.stories.tsx new file mode 100644 index 000000000..06986fec2 --- /dev/null +++ b/HDesign/src/components/Tab/Tab.stories.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import type {Meta, StoryObj} from '@storybook/react'; + +import Tab from '@components/Tab/Tab'; + +const meta = { + title: 'Components/Tab', + component: Tab, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + args: { + tabs: [ + {label: '전체 지출 내역', content:
없지롱
}, + {label: '참여자 별 정산', content:
있지롱
}, + ], + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Tab/Tab.style.ts b/HDesign/src/components/Tab/Tab.style.ts new file mode 100644 index 000000000..1e8054821 --- /dev/null +++ b/HDesign/src/components/Tab/Tab.style.ts @@ -0,0 +1,51 @@ +import {Theme} from '@/theme/theme.type'; +import {css} from '@emotion/react'; + +export const tabStyle = css({ + display: 'flex', + flexDirection: 'column', + + width: '100%', +}); + +export const tabListStyle = (theme: Theme) => + css({ + display: 'flex', + position: 'relative', + justifyContent: 'space-between', + alignItems: 'center', + + padding: '0.5rem', + + borderBottomWidth: 1, + borderBottomStyle: 'solid', + borderBottomColor: theme.colors.gray, + + backgroundColor: theme.colors.white, + + cursor: 'pointer', + }); + +export const tabItemStyle = css({ + flex: 1, + + textAlign: 'center', +}); + +export const tabTextStyle = (theme: Theme, selected: boolean) => + css({ + color: selected ? theme.colors.onTertiary : theme.colors.gray, + }); + +export const indicatorStyle = (theme: Theme, leftPosition: string, tabLength: number) => + css({ + position: 'absolute', + left: leftPosition, + bottom: 0, + + width: `calc(100% / ${tabLength})`, + height: '0.125rem', + + backgroundColor: theme.colors.onSecondary, + transition: 'left 0.3s', + }); diff --git a/HDesign/src/components/Tab/Tab.tsx b/HDesign/src/components/Tab/Tab.tsx new file mode 100644 index 000000000..313f62086 --- /dev/null +++ b/HDesign/src/components/Tab/Tab.tsx @@ -0,0 +1,54 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; +import React, {useState} from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {tabListStyle, tabTextStyle, tabStyle, tabItemStyle, indicatorStyle} from './Tab.style'; +import {TabsProps} from './Tab.type'; +import Text from '@components/Text/Text'; + +const Tab: React.FC = ({tabs}) => { + const {theme} = useTheme(); + const [activeTabIndex, setActiveTabIndex] = useState(0); + + const isActive = (index: number) => { + return activeTabIndex === index; + }; + + return ( +
+
    + {tabs.map((tab, index) => ( + + ))} +
    +
+ {tabs.map((tab, index) => ( + + ))} +
+ ); +}; + +export default Tab; diff --git a/HDesign/src/components/Tab/Tab.type.ts b/HDesign/src/components/Tab/Tab.type.ts new file mode 100644 index 000000000..80ddd4ef9 --- /dev/null +++ b/HDesign/src/components/Tab/Tab.type.ts @@ -0,0 +1,8 @@ +export interface TabProps { + label: string; + content: React.ReactNode; +} + +export interface TabsProps { + tabs: TabProps[]; +} diff --git a/HDesign/src/components/Text/Text.style.ts b/HDesign/src/components/Text/Text.style.ts index 356f9b0a0..8767cdb0f 100644 --- a/HDesign/src/components/Text/Text.style.ts +++ b/HDesign/src/components/Text/Text.style.ts @@ -1,4 +1,4 @@ -import type {TextProps} from './Text'; +import type {TextProps} from './Text.type'; import {css} from '@emotion/react'; @@ -18,6 +18,6 @@ export const getSizeStyling = (size: Required['size']) => { caption: css(TYPOGRAPHY.caption), tiny: css(TYPOGRAPHY.tiny), }; - console.log(style[size]); + return style[size]; }; diff --git a/HDesign/src/components/Text/Text.tsx b/HDesign/src/components/Text/Text.tsx index f39428c8d..e0e2a8ec8 100644 --- a/HDesign/src/components/Text/Text.tsx +++ b/HDesign/src/components/Text/Text.tsx @@ -1,16 +1,10 @@ /** @jsxImportSource @emotion/react */ -import type {Size} from '@components/Text/Text.type'; - -import type {ComponentPropsWithoutRef} from 'react'; +import type {TextProps} from '@components/Text/Text.type'; import React from 'react'; import {getSizeStyling} from './Text.style'; -export interface TextProps extends ComponentPropsWithoutRef<'p'> { - size?: Size | 'bodyBold' | 'smallBodyBold' | 'captionBold'; -} - const Text: React.FC = ({size = 'body', children, ...attributes}: TextProps) => { return (

diff --git a/HDesign/src/components/Text/Text.type.ts b/HDesign/src/components/Text/Text.type.ts index d27b9b61b..db75b09be 100644 --- a/HDesign/src/components/Text/Text.type.ts +++ b/HDesign/src/components/Text/Text.type.ts @@ -1 +1,21 @@ -export type Size = 'head' | 'title' | 'subTitle' | 'body' | 'smallBody' | 'caption' | 'tiny'; +export type TextSize = + | 'head' + | 'title' + | 'subTitle' + | 'body' + | 'smallBody' + | 'caption' + | 'tiny' + | 'bodyBold' + | 'smallBodyBold' + | 'captionBold'; + +export interface TextStyleProps { + size?: TextSize; +} + +export interface TextCustomProps {} + +export type TextOptionProps = TextStyleProps & TextCustomProps; + +export type TextProps = React.ComponentProps<'p'> & TextOptionProps; diff --git a/HDesign/src/components/TextButton/TextButton.stories.tsx b/HDesign/src/components/TextButton/TextButton.stories.tsx new file mode 100644 index 000000000..9873df3f4 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.stories.tsx @@ -0,0 +1,50 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import TextButton from '@components/TextButton/TextButton'; + +const meta = { + title: 'Components/TextButton', + component: TextButton, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + textSize: { + description: '', + control: {type: 'select'}, + options: [ + 'head', + 'title', + 'subTitle', + 'bodyBold', + 'body', + 'smallBodyBold', + 'smallBody', + 'caption', + 'captionBold', + 'tiny', + ], + }, + textColor: { + description: '', + control: {type: 'select'}, + options: ['black', 'gray'], + }, + children: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + textColor: 'black', + textSize: 'bodyBold', + children: '뒤로가기', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/TextButton/TextButton.style.ts b/HDesign/src/components/TextButton/TextButton.style.ts new file mode 100644 index 000000000..e2b602c62 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.style.ts @@ -0,0 +1,13 @@ +import {Theme} from '@/theme/theme.type'; +import {TextColor} from './TextButton.type'; +import {css} from '@emotion/react'; + +interface TextButtonStyleProps { + textColor: TextColor; + theme: Theme; +} + +export const textButtonStyle = ({textColor, theme}: TextButtonStyleProps) => + css({ + color: theme.colors[textColor], + }); diff --git a/HDesign/src/components/TextButton/TextButton.tsx b/HDesign/src/components/TextButton/TextButton.tsx new file mode 100644 index 000000000..c44b7a5c7 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.tsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef} from 'react'; +import {TextButtonProps} from './TextButton.type'; +import Text from '../Text/Text'; +import {useTheme} from '@/theme/HDesignProvider'; +import {textButtonStyle} from './TextButton.style'; + +export const TextButton: React.FC = forwardRef(function Button( + {textColor, textSize, children, ...htmlProps}: TextButtonProps, + ref, +) { + const {theme} = useTheme(); + + return ( + + ); +}); + +export default TextButton; diff --git a/HDesign/src/components/TextButton/TextButton.type.ts b/HDesign/src/components/TextButton/TextButton.type.ts new file mode 100644 index 000000000..0299d89b9 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.type.ts @@ -0,0 +1,15 @@ +import {TextSize} from '../Text/Text.type'; + +export type TextColor = 'black' | 'gray'; + +export interface TextButtonStyleProps { + textColor: TextColor; +} + +export interface TextButtonCustomProps { + textSize: TextSize; +} + +export type TextButtonOptionProps = TextButtonStyleProps & TextButtonCustomProps; + +export type TextButtonProps = React.ComponentProps<'button'> & TextButtonOptionProps; diff --git a/HDesign/src/components/Title/Title.stories.tsx b/HDesign/src/components/Title/Title.stories.tsx index 0b650b280..3973779db 100644 --- a/HDesign/src/components/Title/Title.stories.tsx +++ b/HDesign/src/components/Title/Title.stories.tsx @@ -18,10 +18,15 @@ const meta = { description: '', control: {type: 'text'}, }, + price: { + description: '', + control: {type: 'number'}, + }, }, args: { title: '페이지 제목이에요', description: '이곳에는 페이지 설명이 들어가요. 페이지에 대한 설명을 자세하게 적어주면 좋아요 :)', + price: 100000, }, } satisfies Meta; diff --git a/HDesign/src/components/Title/Title.style.ts b/HDesign/src/components/Title/Title.style.ts index 2b298d2cf..ca0a02fc3 100644 --- a/HDesign/src/components/Title/Title.style.ts +++ b/HDesign/src/components/Title/Title.style.ts @@ -2,13 +2,14 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; -export const titleContainerStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '0.5rem', - - padding: '0 1rem', -}); +export const titleContainerStyle = (theme: Theme) => + css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + backgroundColor: theme.colors.white, + padding: '1rem', + }); export const titleStyle = (theme: Theme) => css({ @@ -19,3 +20,19 @@ export const descriptionStyle = (theme: Theme) => css({ color: theme.colors.darkGray, }); + +export const priceContainerStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'end', +}); + +export const priceTitleStyle = (theme: Theme) => + css({ + color: theme.colors.gray, + }); + +export const priceStyle = (theme: Theme) => + css({ + color: theme.colors.black, + }); diff --git a/HDesign/src/components/Title/Title.tsx b/HDesign/src/components/Title/Title.tsx index 556c037e4..5901bc350 100644 --- a/HDesign/src/components/Title/Title.tsx +++ b/HDesign/src/components/Title/Title.tsx @@ -1,18 +1,37 @@ /** @jsxImportSource @emotion/react */ import Text from '@components/Text/Text'; -import {descriptionStyle, titleContainerStyle, titleStyle} from '@components/Title/Title.style'; +import { + descriptionStyle, + priceContainerStyle, + priceStyle, + priceTitleStyle, + titleContainerStyle, + titleStyle, +} from '@components/Title/Title.style'; import {TitleProps} from '@components/Title/Title.type'; import {useTheme} from '@theme/HDesignProvider'; -export const Title: React.FC = ({title, description}: TitleProps) => { +export const Title: React.FC = ({title, description, price}: TitleProps) => { const {theme} = useTheme(); return ( -

+
{title} - {description} + {description && ( + + {description} + + )} + {price && ( +
+ + 전체 지출 금액 + + {price.toLocaleString('ko-kr')} 원 +
+ )}
); }; diff --git a/HDesign/src/components/Title/Title.type.ts b/HDesign/src/components/Title/Title.type.ts index fa3fb4e3f..4b12f23b2 100644 --- a/HDesign/src/components/Title/Title.type.ts +++ b/HDesign/src/components/Title/Title.type.ts @@ -3,6 +3,7 @@ export interface TitleStyleProps {} export interface TitleCustomProps { title: string; description?: string; + price?: number; } export type TitleOptionProps = TitleStyleProps & TitleCustomProps; diff --git a/HDesign/src/components/TopNav/TopNav.stories.ts b/HDesign/src/components/TopNav/TopNav.stories.ts new file mode 100644 index 000000000..f37845346 --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.stories.ts @@ -0,0 +1,28 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import TopNav from '@components/TopNav/TopNav'; +import Switch from '../Switch/Switch'; + +const meta = { + title: 'Components/TopNav', + component: TopNav, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + navType: { + description: '', + control: {type: 'select', options: ['back', 'home']}, + }, + }, + args: { + navType: 'back', + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/HDesign/src/components/TopNav/TopNav.style.ts new file mode 100644 index 000000000..cd4244eb3 --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.style.ts @@ -0,0 +1,6 @@ +import {css} from '@emotion/react'; + +export const topNavStyle = css({ + display: 'flex', + padding: '0 1rem', +}); diff --git a/HDesign/src/components/TopNav/TopNav.tsx b/HDesign/src/components/TopNav/TopNav.tsx new file mode 100644 index 000000000..75ce368ff --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.tsx @@ -0,0 +1,24 @@ +import {useNavigate} from 'react-router-dom'; +import TextButton from '../TextButton/TextButton'; +import {topNavStyle} from './TopNav.style'; +import {TopNavProps} from './TopNav.type'; +import Switch from '../Switch/Switch'; + +// TODO: (@todari) navigation으로 인해 storybook 동작하지 않는 오류 해결해야함 +// + 페이지 정하는 것에 따라, navigate 경로 수정해 줘야 함 +const TopNav = ({navType}: TopNavProps) => { + const navigate = useNavigate(); + return ( +
+ {navType === 'back' ? ( + navigate(-1)} textSize="bodyBold" textColor="gray"> + 뒤로가기 + + ) : ( + navigate('./')}> + )} +
+ ); +}; + +export default TopNav; diff --git a/HDesign/src/components/TopNav/TopNav.type.ts b/HDesign/src/components/TopNav/TopNav.type.ts new file mode 100644 index 000000000..c84e21894 --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.type.ts @@ -0,0 +1,5 @@ +type NavType = 'back' | 'home'; + +export interface TopNavProps { + navType: NavType; +} diff --git a/HDesign/src/token/colors.ts b/HDesign/src/token/colors.ts index 73f7b4f7f..01bbf8f02 100644 --- a/HDesign/src/token/colors.ts +++ b/HDesign/src/token/colors.ts @@ -28,7 +28,20 @@ const PRIMITIVE_COLORS = { type Color = string; -export type ColorTokens = Record; +export type ColorKeys = + | 'white' + | 'gray' + | 'darkGray' + | 'black' + | 'primary' + | 'onPrimary' + | 'secondary' + | 'onSecondary' + | 'tertiary' + | 'onTertiary' + | 'grayContainer' + | 'lightGrayContainer'; +export type ColorTokens = Record; // TODO: (@soha) 대괄호 사용에 대해 논의 export const COLORS: ColorTokens = { diff --git a/HDesign/src/types/strictPropsWithChildren.ts b/HDesign/src/types/strictPropsWithChildren.ts new file mode 100644 index 000000000..684fbcc76 --- /dev/null +++ b/HDesign/src/types/strictPropsWithChildren.ts @@ -0,0 +1,3 @@ +export type StrictPropsWithChildren

= P & { + children: React.ReactNode; +}; diff --git a/HDesign/src/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase.ts b/HDesign/src/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase.ts new file mode 100644 index 000000000..2bca7c1b7 --- /dev/null +++ b/HDesign/src/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase.ts @@ -0,0 +1,3 @@ +export const changeCamelCaseToKebabCase = (str: string) => { + return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); +}; From 9c22e4724b2029f1a43726ca1452faed357627d5 Mon Sep 17 00:00:00 2001 From: juha Date: Fri, 19 Jul 2024 17:56:45 +0900 Subject: [PATCH 054/273] =?UTF-8?q?refactor:=20BillAction=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/haengdong/domain/BillAction.java | 24 +++++++- .../haengdong/domain/BillActionTest.java | 56 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 server/src/test/java/server/haengdong/domain/BillActionTest.java diff --git a/server/src/main/java/server/haengdong/domain/BillAction.java b/server/src/main/java/server/haengdong/domain/BillAction.java index 24ab5a410..3253a3edb 100644 --- a/server/src/main/java/server/haengdong/domain/BillAction.java +++ b/server/src/main/java/server/haengdong/domain/BillAction.java @@ -1,6 +1,7 @@ package server.haengdong.domain; import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; @@ -16,6 +17,11 @@ @Entity public class BillAction { + private static final int MIN_TITLE_LENGTH = 2; + private static final int MAX_TITLE_LENGTH = 30; + private static final long MIN_PRICE = 1L; + private static final long MAX_PRICE = 10_000_000L; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -23,16 +29,32 @@ public class BillAction { @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) private Action action; + @Column(length = MAX_TITLE_LENGTH) private String title; private Long price; public BillAction(Action action, String title, Long price) { + validateTitle(title); + validatePrice(price); this.action = action; - this.title = title; + this.title = title.trim(); this.price = price; } + private void validateTitle(String title) { + int titleLength = title.trim().length(); + if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { + throw new IllegalArgumentException("앞뒤 공백을 제거한 지출 내역 제목은 2 ~ 30자여야 합니다."); + } + } + + private void validatePrice(Long price) { + if (price < MIN_PRICE || price > MAX_PRICE) { + throw new IllegalArgumentException("지출 금액은 10,000,000 이하의 자연수여야 합니다."); + } + } + public Long getSequence() { return action.getSequence(); } diff --git a/server/src/test/java/server/haengdong/domain/BillActionTest.java b/server/src/test/java/server/haengdong/domain/BillActionTest.java new file mode 100644 index 000000000..93160a114 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/BillActionTest.java @@ -0,0 +1,56 @@ +package server.haengdong.domain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class BillActionTest { + + @DisplayName("앞뒤 공백을 제거한 title이 2 ~ 30자가 아니면 지출을 생성할 수 없다.") + @ParameterizedTest + @ValueSource(strings = {" 감 ", "", " ", "감자감자감자감자감자감자백호백호백호백호백호감자감자감자감자감자감자백호백호백호백호백호"}) + void validateTitle(String title) { + Event event = new Event("name", "token"); + Action action = new Action(event, 1L); + Long price = 100L; + + assertThatThrownBy(() -> new BillAction(action, title, price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("앞뒤 공백을 제거한 지출 내역 제목은 2 ~ 30자여야 합니다."); + } + + @DisplayName("금액이 10,000,000 이하의 자연수가 아니면 지출을 생성할 수 없다.") + @ParameterizedTest + @ValueSource(longs = {0, 10_000_001, 20_000_000}) + void validatePrice(long price) { + Event event = new Event("name", "token"); + Action action = new Action(event, 1L); + String title = "title"; + + assertThatThrownBy(() -> new BillAction(action, title, price)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("지출 금액은 10,000,000 이하의 자연수여야 합니다."); + } + + @DisplayName("지출 내역을 올바르게 생성한다.") + @Test + void createBillAction() { + Event event = new Event("name", "token"); + Action action = new Action(event, 1L); + String title = "title"; + Long price = 1_000L; + + BillAction billAction = new BillAction(action, title, price); + + assertAll( + () -> assertThat(billAction.getAction()).isEqualTo(action), + () -> assertThat(billAction.getTitle()).isEqualTo(title), + () -> assertThat(billAction.getPrice()).isEqualTo(price) + ); + } +} From 24ef6e4ad0f333d534eac1fdc2c8f4bac2d6ce17 Mon Sep 17 00:00:00 2001 From: Arachneee Date: Sat, 20 Jul 2024 00:56:53 +0900 Subject: [PATCH 055/273] =?UTF-8?q?refactor:=20=EC=A7=80=EC=B6=9C=20?= =?UTF-8?q?=EB=82=B4=EC=97=AD=20=EC=B6=94=EA=B0=80=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/BillActionService.java | 15 ++++------ .../java/server/haengdong/domain/Action.java | 10 +++++++ .../server/haengdong/domain/ActionTest.java | 29 +++++++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 server/src/test/java/server/haengdong/domain/ActionTest.java diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java index 6c69e383f..0c62c133f 100644 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -1,6 +1,5 @@ package server.haengdong.application; -import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -26,20 +25,18 @@ public class BillActionService { public void saveAllBillAction(String eventToken, List requests) { Event event = eventRepository.findByToken(eventToken) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 이벤트 토큰입니다.")); - long lastSequence = getLastSequence(event); + Action action = createStartAction(event); - List billActions = new ArrayList<>(); for (BillActionAppRequest request : requests) { - Action action = new Action(event, ++lastSequence); BillAction billAction = request.toBillAction(action); - billActions.add(billAction); + billActionRepository.save(billAction); + action = action.next(); } - billActionRepository.saveAll(billActions); } - private long getLastSequence(Event event) { + private Action createStartAction(Event event) { return actionRepository.findLastByEvent(event) - .map(Action::getSequence) - .orElse(0L); + .map(Action::next) + .orElse(Action.createFirst(event)); } } diff --git a/server/src/main/java/server/haengdong/domain/Action.java b/server/src/main/java/server/haengdong/domain/Action.java index 7a47b1de5..be294dac3 100644 --- a/server/src/main/java/server/haengdong/domain/Action.java +++ b/server/src/main/java/server/haengdong/domain/Action.java @@ -15,6 +15,8 @@ @Entity public class Action { + private static final long FIRST_SEQUENCE = 1L; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -28,4 +30,12 @@ public Action(Event event, Long sequence) { this.event = event; this.sequence = sequence; } + + public static Action createFirst(Event event) { + return new Action(event, FIRST_SEQUENCE); + } + + public Action next() { + return new Action(event, sequence + 1); + } } diff --git a/server/src/test/java/server/haengdong/domain/ActionTest.java b/server/src/test/java/server/haengdong/domain/ActionTest.java new file mode 100644 index 000000000..a699fb04a --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/ActionTest.java @@ -0,0 +1,29 @@ +package server.haengdong.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ActionTest { + + @DisplayName("액션의 초기 순서번호는 1이다.") + @Test + void createFirst() { + Event event = new Event("name", "token"); + Action action = Action.createFirst(event); + + assertThat(action.getSequence()).isOne(); + } + + @DisplayName("현재 액션의 다음 액션의 순서는 1만큼 증가한다.") + @Test + void next() { + Event event = new Event("name", "token"); + Action action = new Action(event, 2L); + + Action nextAction = action.next(); + + assertThat(nextAction.getSequence()).isEqualTo(3L); + } +} From ef63c604188db4b1d035f7570ba3a2fdd9871d51 Mon Sep 17 00:00:00 2001 From: Arachneee Date: Sun, 21 Jul 2024 00:30:02 +0900 Subject: [PATCH 056/273] =?UTF-8?q?feat:=20BillAction=EA=B3=BC=20Action=20?= =?UTF-8?q?cascade=20=EC=98=B5=EC=85=98=EA=B3=BC=20orphanRemoval=20?= =?UTF-8?q?=EC=98=B5=EC=85=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/src/main/java/server/haengdong/domain/BillAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/server/haengdong/domain/BillAction.java b/server/src/main/java/server/haengdong/domain/BillAction.java index 3253a3edb..557715e4b 100644 --- a/server/src/main/java/server/haengdong/domain/BillAction.java +++ b/server/src/main/java/server/haengdong/domain/BillAction.java @@ -26,7 +26,7 @@ public class BillAction { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) private Action action; @Column(length = MAX_TITLE_LENGTH) From fd926b6d9ecd8192e19c38b33c48687d08f5943a Mon Sep 17 00:00:00 2001 From: Arachneee Date: Sun, 21 Jul 2024 00:31:20 +0900 Subject: [PATCH 057/273] =?UTF-8?q?test:=20event=20save=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/haengdong/application/BillActionServiceTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java index ba0cfc41a..cae27b94b 100644 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -32,7 +32,8 @@ class BillActionServiceTest { @Test void saveAllBillAction() { String token = "TOKEN"; - Event event = eventRepository.save(new Event("감자", token)); + Event event = new Event("감자", token); + Event savedEvent = eventRepository.save(event); List requests = List.of( new BillActionAppRequest("뽕족", 10_000L), @@ -41,7 +42,7 @@ void saveAllBillAction() { billActionService.saveAllBillAction(token, requests); - List actions = billActionRepository.findByAction_Event(event) + List actions = billActionRepository.findByAction_Event(savedEvent) .stream() .sorted(Comparator.comparing(BillAction::getSequence).reversed()) .limit(requests.size()) From 926ef4060bc2b0b4f7884449c3252ea6a4559320 Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Sun, 21 Jul 2024 08:24:15 +0900 Subject: [PATCH 058/273] =?UTF-8?q?test:=20DisplayName=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> --- .../src/test/java/server/haengdong/domain/BillActionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/server/haengdong/domain/BillActionTest.java b/server/src/test/java/server/haengdong/domain/BillActionTest.java index 93160a114..d5d8132fe 100644 --- a/server/src/test/java/server/haengdong/domain/BillActionTest.java +++ b/server/src/test/java/server/haengdong/domain/BillActionTest.java @@ -11,7 +11,7 @@ class BillActionTest { - @DisplayName("앞뒤 공백을 제거한 title이 2 ~ 30자가 아니면 지출을 생성할 수 없다.") + @DisplayName("지출 내역 제목의 앞뒤 공백을 제거한 길이가 2 ~ 30자가 아니면 지출을 생성할 수 없다.") @ParameterizedTest @ValueSource(strings = {" 감 ", "", " ", "감자감자감자감자감자감자백호백호백호백호백호감자감자감자감자감자감자백호백호백호백호백호"}) void validateTitle(String title) { From 507676e2fcb07df4bf64be4783609f21ff13676e Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Sun, 21 Jul 2024 08:24:42 +0900 Subject: [PATCH 059/273] =?UTF-8?q?test:=20=EA=B2=BD=EA=B3=84=EA=B0=92=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> --- .../src/test/java/server/haengdong/domain/BillActionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/server/haengdong/domain/BillActionTest.java b/server/src/test/java/server/haengdong/domain/BillActionTest.java index d5d8132fe..5789f8c94 100644 --- a/server/src/test/java/server/haengdong/domain/BillActionTest.java +++ b/server/src/test/java/server/haengdong/domain/BillActionTest.java @@ -13,7 +13,7 @@ class BillActionTest { @DisplayName("지출 내역 제목의 앞뒤 공백을 제거한 길이가 2 ~ 30자가 아니면 지출을 생성할 수 없다.") @ParameterizedTest - @ValueSource(strings = {" 감 ", "", " ", "감자감자감자감자감자감자백호백호백호백호백호감자감자감자감자감자감자백호백호백호백호백호"}) + @ValueSource(strings = {" 감 ", "", " ", "1234567890123456789012345678901"}) void validateTitle(String title) { Event event = new Event("name", "token"); Action action = new Action(event, 1L); From a91426aa7a57502b94dbe307ab1f2c84e53fcccc Mon Sep 17 00:00:00 2001 From: JUHA <84626225+khabh@users.noreply.github.com> Date: Sun, 21 Jul 2024 10:59:07 +0900 Subject: [PATCH 060/273] =?UTF-8?q?test:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=83=9D=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/BillActionServiceTest.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java index cae27b94b..df19b9e63 100644 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -4,7 +4,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; -import java.util.Comparator; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -42,16 +41,12 @@ void saveAllBillAction() { billActionService.saveAllBillAction(token, requests); - List actions = billActionRepository.findByAction_Event(savedEvent) - .stream() - .sorted(Comparator.comparing(BillAction::getSequence).reversed()) - .limit(requests.size()) - .toList(); + List actions = billActionRepository.findByAction_Event(savedEvent); - assertThat(actions).extracting("title", "price") - .containsExactly( - tuple("인생맥주", 15_000L), - tuple("뽕족", 10_000L) + assertThat(actions).extracting(BillAction::getTitle, BillAction::getPrice, BillAction::getSequence) + .containsExactlyInAnyOrder( + tuple("뽕족", 10_000L, 1L), + tuple("인생맥주", 15_000L, 2L) ); } From 2b5345d4332bb3e2dad531858c1b46778abf3729 Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Sun, 21 Jul 2024 13:22:55 +0900 Subject: [PATCH 061/273] =?UTF-8?q?feat:=20PR=20=ED=9B=84=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=A6=AC=ED=8F=AC=ED=8A=B8=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#56)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-pull-request.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml index a5cfbfda7..113972929 100644 --- a/.github/workflows/backend-pull-request.yml +++ b/.github/workflows/backend-pull-request.yml @@ -14,9 +14,6 @@ jobs: run: working-directory: ./server - permissions: - contents: read - steps: - name: CheckOut uses: actions/checkout@v4 @@ -32,3 +29,15 @@ jobs: - name: Test with Gradle Wrapper run: ./gradlew clean build + + - name: publish unit test results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: server/build/test-results/test/TEST-*.xml + + - name: add comments to a pull request + uses: mikepenz/action-junit-report@v3 + if: always() + with: + report_paths: server/build/test-results/test/TEST-*.xml From e489d8230d2b271489a272fab5377f445dc732b0 Mon Sep 17 00:00:00 2001 From: Arachneee Date: Sun, 21 Jul 2024 13:30:29 +0900 Subject: [PATCH 062/273] =?UTF-8?q?test:=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20t?= =?UTF-8?q?est=20class=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/haengdong/ServerApplicationTests.java | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 server/src/test/java/server/haengdong/ServerApplicationTests.java diff --git a/server/src/test/java/server/haengdong/ServerApplicationTests.java b/server/src/test/java/server/haengdong/ServerApplicationTests.java deleted file mode 100644 index d4bf7167e..000000000 --- a/server/src/test/java/server/haengdong/ServerApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package server.haengdong; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class ServerApplicationTests { - - @Test - void contextLoads() { - } - -} From 7dc4e8f0c925c9effce3be72eb1a2646166b3b1e Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Sun, 21 Jul 2024 15:32:09 +0900 Subject: [PATCH 063/273] =?UTF-8?q?[BE]=20=EC=9D=B8=EC=9B=90=20=EB=B3=80?= =?UTF-8?q?=EB=8F=99=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=20(#47)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee * refactor: 메서드 분리 Co-authored-by: kunsanglee * refactor: 코드 컨벤션 Co-authored-by: kunsanglee * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee Co-authored-by: Arachne * refactor: 메서드 순서 변경 Co-authored-by: Arachne --------- Co-authored-by: kunsanglee Co-authored-by: Arachne authored-by: khabh --- .../application/MemberActionFactory.java | 80 +++++++ .../application/MemberActionService.java | 41 ++++ .../request/MemberActionSaveAppRequest.java | 12 + .../request/MemberActionsSaveAppRequest.java | 6 + .../server/haengdong/domain/EventStep.java | 2 +- .../server/haengdong/domain/MemberAction.java | 22 +- .../haengdong/domain/MemberActionStatus.java | 9 + .../domain/MemberGroupIdProvider.java | 11 + .../persistence/ActionRepository.java | 3 +- .../persistence/EventRepository.java | 2 +- .../persistence/MemberActionRepository.java | 16 ++ .../presentation/MemberActionController.java | 27 +++ .../request/MemberActionSaveRequest.java | 10 + .../request/MemberActionsSaveRequest.java | 16 ++ .../application/MemberActionFactoryTest.java | 216 ++++++++++++++++++ .../application/MemberActionServiceTest.java | 82 +++++++ .../presentation/EventControllerTest.java | 4 +- .../MemberActionControllerTest.java | 49 ++++ 18 files changed, 602 insertions(+), 6 deletions(-) create mode 100644 server/src/main/java/server/haengdong/application/MemberActionFactory.java create mode 100644 server/src/main/java/server/haengdong/application/MemberActionService.java create mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java create mode 100644 server/src/main/java/server/haengdong/domain/MemberGroupIdProvider.java create mode 100644 server/src/main/java/server/haengdong/persistence/MemberActionRepository.java create mode 100644 server/src/main/java/server/haengdong/presentation/MemberActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java create mode 100644 server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java create mode 100644 server/src/test/java/server/haengdong/application/MemberActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java new file mode 100644 index 000000000..d583967a0 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/MemberActionFactory.java @@ -0,0 +1,80 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.Action; +import server.haengdong.domain.MemberAction; +import server.haengdong.domain.MemberActionStatus; +import server.haengdong.domain.MemberGroupIdProvider; + +@RequiredArgsConstructor +@Component +public class MemberActionFactory { + + private final MemberGroupIdProvider memberGroupIdProvider; + + public List createMemberActions( + MemberActionsSaveAppRequest request, + List memberActions, + Action action + ) { + validateMemberNames(request); + validateActions(request, memberActions); + + Long memberGroupId = memberGroupIdProvider.createGroupId(); + List createdMemberActions = new ArrayList<>(); + List actions = request.actions(); + for (MemberActionSaveAppRequest appRequest : actions) { + MemberAction memberAction = appRequest.toMemberAction(action, memberGroupId); + createdMemberActions.add(memberAction); + action = action.next(); + } + + return createdMemberActions; + } + + private void validateMemberNames(MemberActionsSaveAppRequest request) { + List memberNames = request.actions().stream() + .map(MemberActionSaveAppRequest::name) + .toList(); + + long uniqueCount = memberNames.stream().distinct().count(); + if (uniqueCount != memberNames.size()) { + throw new IllegalArgumentException(); + } + } + + private void validateActions(MemberActionsSaveAppRequest request, List memberActions) { + List reverseSortedMemberActions = memberActions.stream() + .sorted(Comparator.comparing(MemberAction::getSequence).reversed()) + .toList(); + + for (MemberActionSaveAppRequest action : request.actions()) { + validateAction(action, reverseSortedMemberActions); + } + } + + private void validateAction(MemberActionSaveAppRequest request, List memberActions) { + MemberActionStatus memberActionStatus = MemberActionStatus.of(request.status()); + if (isInvalidStatus(memberActions, request.name(), memberActionStatus)) { + throw new IllegalArgumentException(); + } + } + + private boolean isInvalidStatus( + List memberActions, + String memberName, + MemberActionStatus memberActionStatus + ) { + return memberActions.stream() + .filter(action -> action.isSameName(memberName)) + .findFirst() + .map(action -> action.isSameStatus(memberActionStatus)) + .orElse(MemberActionStatus.IN != memberActionStatus); + } +} diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java new file mode 100644 index 000000000..491981b06 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/MemberActionService.java @@ -0,0 +1,41 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.Action; +import server.haengdong.domain.Event; +import server.haengdong.domain.MemberAction; +import server.haengdong.persistence.ActionRepository; +import server.haengdong.persistence.EventRepository; +import server.haengdong.persistence.MemberActionRepository; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class MemberActionService { + + private final MemberActionFactory memberActionFactory; + private final MemberActionRepository memberActionRepository; + private final EventRepository eventRepository; + private final ActionRepository actionRepository; + + @Transactional + public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new IllegalArgumentException("event not found")); + + List findMemberActions = memberActionRepository.findAllByEvent(event); + Action action = createStartAction(event); + List memberActions = memberActionFactory.createMemberActions(request, findMemberActions, action); + memberActionRepository.saveAll(memberActions); + } + + private Action createStartAction(Event event) { + return actionRepository.findLastByEvent(event) + .map(Action::next) + .orElse(Action.createFirst(event)); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java new file mode 100644 index 000000000..a7c90efe4 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java @@ -0,0 +1,12 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.Action; +import server.haengdong.domain.MemberAction; +import server.haengdong.domain.MemberActionStatus; + +public record MemberActionSaveAppRequest(String name, String status) { + + public MemberAction toMemberAction(Action action, Long memberGroupId) { + return new MemberAction(action, name, MemberActionStatus.of(status), memberGroupId); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java new file mode 100644 index 000000000..650b908df --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java @@ -0,0 +1,6 @@ +package server.haengdong.application.request; + +import java.util.List; + +public record MemberActionsSaveAppRequest(List actions) { +} diff --git a/server/src/main/java/server/haengdong/domain/EventStep.java b/server/src/main/java/server/haengdong/domain/EventStep.java index 741dcaba5..b25035fa5 100644 --- a/server/src/main/java/server/haengdong/domain/EventStep.java +++ b/server/src/main/java/server/haengdong/domain/EventStep.java @@ -21,7 +21,7 @@ public class EventStep { @ManyToOne(fetch = FetchType.LAZY) private Event event; - + private String name; private Long sequence; diff --git a/server/src/main/java/server/haengdong/domain/MemberAction.java b/server/src/main/java/server/haengdong/domain/MemberAction.java index 6d8ea9b20..eb8d8fdec 100644 --- a/server/src/main/java/server/haengdong/domain/MemberAction.java +++ b/server/src/main/java/server/haengdong/domain/MemberAction.java @@ -1,5 +1,6 @@ package server.haengdong.domain; +import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; @@ -21,7 +22,7 @@ public class MemberAction { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) private Action action; private String memberName; @@ -30,4 +31,23 @@ public class MemberAction { private MemberActionStatus status; private Long memberGroupId; + + public MemberAction(Action action, String memberName, MemberActionStatus status, Long memberGroupId) { + this.action = action; + this.memberName = memberName; + this.status = status; + this.memberGroupId = memberGroupId; + } + + public boolean isSameName(String name) { + return memberName.equals(name); + } + + public boolean isSameStatus(MemberActionStatus memberActionStatus) { + return status == memberActionStatus; + } + + public Long getSequence() { + return action.getSequence(); + } } diff --git a/server/src/main/java/server/haengdong/domain/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/MemberActionStatus.java index af7fad121..6172bdb4d 100644 --- a/server/src/main/java/server/haengdong/domain/MemberActionStatus.java +++ b/server/src/main/java/server/haengdong/domain/MemberActionStatus.java @@ -1,7 +1,16 @@ package server.haengdong.domain; +import java.util.Arrays; + public enum MemberActionStatus { IN, OUT, ; + + public static MemberActionStatus of(String status) { + return Arrays.stream(MemberActionStatus.values()) + .filter(s -> s.name().equals(status)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Invalid status: " + status)); + } } diff --git a/server/src/main/java/server/haengdong/domain/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/MemberGroupIdProvider.java new file mode 100644 index 000000000..c4166e2be --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/MemberGroupIdProvider.java @@ -0,0 +1,11 @@ +package server.haengdong.domain; + +import org.springframework.stereotype.Component; + +@Component +public class MemberGroupIdProvider { + + public Long createGroupId() { + return System.currentTimeMillis(); + } +} diff --git a/server/src/main/java/server/haengdong/persistence/ActionRepository.java b/server/src/main/java/server/haengdong/persistence/ActionRepository.java index 72c573d91..7b7b838d2 100644 --- a/server/src/main/java/server/haengdong/persistence/ActionRepository.java +++ b/server/src/main/java/server/haengdong/persistence/ActionRepository.java @@ -3,6 +3,7 @@ import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import server.haengdong.domain.Action; import server.haengdong.domain.Event; @@ -17,5 +18,5 @@ public interface ActionRepository extends JpaRepository { ORDER BY a.sequence DESC LIMIT 1 """) - Optional findLastByEvent(Event event); + Optional findLastByEvent(@Param("event") Event event); } diff --git a/server/src/main/java/server/haengdong/persistence/EventRepository.java b/server/src/main/java/server/haengdong/persistence/EventRepository.java index 8a83d751f..5c08ca98c 100644 --- a/server/src/main/java/server/haengdong/persistence/EventRepository.java +++ b/server/src/main/java/server/haengdong/persistence/EventRepository.java @@ -7,6 +7,6 @@ @Repository public interface EventRepository extends JpaRepository { - + Optional findByToken(String token); } diff --git a/server/src/main/java/server/haengdong/persistence/MemberActionRepository.java b/server/src/main/java/server/haengdong/persistence/MemberActionRepository.java new file mode 100644 index 000000000..97d06618b --- /dev/null +++ b/server/src/main/java/server/haengdong/persistence/MemberActionRepository.java @@ -0,0 +1,16 @@ +package server.haengdong.persistence; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.Event; +import server.haengdong.domain.MemberAction; + +@Repository +public interface MemberActionRepository extends JpaRepository { + + @Query("select m from MemberAction m join fetch m.action where m.action.event = :event") + List findAllByEvent(@Param("event") Event event); +} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java new file mode 100644 index 000000000..e35bcfd7b --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/MemberActionController.java @@ -0,0 +1,27 @@ +package server.haengdong.presentation; + +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.MemberActionService; +import server.haengdong.presentation.request.MemberActionsSaveRequest; + +@RequiredArgsConstructor +@RestController +public class MemberActionController { + + private final MemberActionService memberActionService; + + @PostMapping("/api/events/{token}/actions/members") + public ResponseEntity saveMemberAction( + @PathVariable("token") String token, + @RequestBody MemberActionsSaveRequest request + ) { + memberActionService.saveMemberAction(token, request.toAppRequest()); + + return ResponseEntity.ok().build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionSaveRequest.java new file mode 100644 index 000000000..a69c51d41 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberActionSaveRequest.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.request; + +import server.haengdong.application.request.MemberActionSaveAppRequest; + +public record MemberActionSaveRequest(String name, String status) { + + public MemberActionSaveAppRequest toAppRequest() { + return new MemberActionSaveAppRequest(name, status); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java new file mode 100644 index 000000000..bfe80f0ee --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java @@ -0,0 +1,16 @@ +package server.haengdong.presentation.request; + +import java.util.List; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; + +public record MemberActionsSaveRequest(List actions) { + + public MemberActionsSaveAppRequest toAppRequest() { + List appRequests = actions.stream() + .map(MemberActionSaveRequest::toAppRequest) + .toList(); + + return new MemberActionsSaveAppRequest(appRequests); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java new file mode 100644 index 000000000..a0ac9916f --- /dev/null +++ b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java @@ -0,0 +1,216 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; + +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.Action; +import server.haengdong.domain.Event; +import server.haengdong.domain.MemberAction; +import server.haengdong.domain.MemberActionStatus; +import server.haengdong.persistence.ActionRepository; +import server.haengdong.persistence.EventRepository; +import server.haengdong.persistence.MemberActionRepository; + +@SpringBootTest +class MemberActionFactoryTest { + + @Autowired + private MemberActionFactory memberActionFactory; + + @Autowired + private MemberActionRepository memberActionRepository; + + @Autowired + private ActionRepository actionRepository; + + @Autowired + private EventRepository eventRepository; + + @AfterEach + void tearDown() { + memberActionRepository.deleteAllInBatch(); + actionRepository.deleteAllInBatch(); + eventRepository.deleteAllInBatch(); + } + + @DisplayName("이전 멤버 액션이 시퀀스 기준으로 정렬되지 않은 상태에서 새로운 멤버 액션 요청을 검증한다.") + @Test + void createMemberActionsTest() { + Event event = eventRepository.save(new Event("우당탕탕 행동대장 백엔드 회식", "토다리_토큰")); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + List unorderedMemberActions = List.of(memberAction2, memberAction1); + Action startAction = new Action(event, 3L); + + assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, unorderedMemberActions, startAction)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("인원 변동 액션을 생성한다.") + @Test + void createMemberActionsTest1() { + Event event = eventRepository.save(new Event("우당탕탕 행동대장 백엔드 회식", "토다리_토큰")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest memberActionsSaveAppRequest = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + Action startAction = new Action(event, 2L); + + List memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, + List.of(memberAction), startAction); + + assertThat(memberActions).hasSize(1) + .extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus) + .containsExactly( + tuple(startAction, "토다리", MemberActionStatus.OUT) + ); + } + + @DisplayName("현재 행사에 참여 중인 경우에 퇴장할 수 있다.") + @Test + void createMemberActionsTest2() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") + @Test + void createMemberActionsTest3() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action1 = new Action(event, 1L); + MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction1); + Action action2 = new Action(event, 2L); + MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); + memberActionRepository.save(memberAction2); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "IN"))); + Action startAction = new Action(event, 3L); + + assertThatCode( + () -> memberActionFactory.createMemberActions(request, List.of(memberAction1, memberAction2), + startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장한 적 없는 경우에 입장할 수 있다.") + @Test + void createMemberActionsTest4() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") + @Test + void createMemberActionTest5() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "OUT"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("행사에 이미 참여 중인 경우 다시 입장할 수 없다.") + @Test + void createMemberActionTest6() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("한 명의 사용자는 동시에 여러 번 입장할 수 없다.") + @Test + void createMemberActionTest7() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"), + new MemberActionSaveAppRequest("쿠키", "IN"))); + Action startAction = new Action(event, 1L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("한 명의 사용자는 동시에 여러 번 퇴장할 수 없다.") + @Test + void createMemberActionTest8() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "OUT"), + new MemberActionSaveAppRequest("쿠키", "OUT"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .isInstanceOf(IllegalArgumentException.class); + } + + @DisplayName("한 명의 사용자는 입장과 퇴장을 동시에 할 수 없다.") + @Test + void createMemberActionTest9() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"), + new MemberActionSaveAppRequest("쿠키", "OUT"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java new file mode 100644 index 000000000..73a7c3d9d --- /dev/null +++ b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java @@ -0,0 +1,82 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThatCode; + +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.Action; +import server.haengdong.domain.Event; +import server.haengdong.domain.MemberAction; +import server.haengdong.domain.MemberActionStatus; +import server.haengdong.persistence.ActionRepository; +import server.haengdong.persistence.EventRepository; +import server.haengdong.persistence.MemberActionRepository; + +@SpringBootTest +class MemberActionServiceTest { + + @Autowired + private MemberActionService memberActionService; + + @Autowired + private MemberActionRepository memberActionRepository; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private ActionRepository actionRepository; + + @AfterEach + void tearDown() { + memberActionRepository.deleteAllInBatch(); + actionRepository.deleteAllInBatch(); + eventRepository.deleteAllInBatch(); + } + + @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다") + @Test + void saveMemberActionTest() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "망쵸", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("망쵸", "OUT"))))) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다") + @Test + void saveMemberActionTest1() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action actionOne = new Action(event, 1L); + MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberActionOne); + + Action actionTwo = new Action(event, 2L); + MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", MemberActionStatus.OUT, 1L); + memberActionRepository.save(memberActionTwo); + + assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("망쵸", "IN"))))) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다") + @Test + void saveMemberActionTest2() { + MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); + + assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) + .isInstanceOf(IllegalArgumentException.class); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java index bed814ae3..a1d67f0a1 100644 --- a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java @@ -32,10 +32,10 @@ class EventControllerTest { @MockBean private EventService eventService; - @DisplayName("이벤트를 생성한다") + @DisplayName("이벤트를 생성한다.") @Test void saveEvent() throws Exception { - EventSaveRequest eventSaveRequest = new EventSaveRequest("test"); + EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리"); String requestBody = objectMapper.writeValueAsString(eventSaveRequest); String token = "TOKEN"; EventAppResponse eventAppResponse = new EventAppResponse(token); diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java new file mode 100644 index 000000000..8f9e71182 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java @@ -0,0 +1,49 @@ +package server.haengdong.presentation; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import server.haengdong.application.MemberActionService; +import server.haengdong.presentation.request.MemberActionSaveRequest; +import server.haengdong.presentation.request.MemberActionsSaveRequest; + +@WebMvcTest(MemberActionController.class) +class MemberActionControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private MemberActionService memberActionService; + + @DisplayName("참여자 행동을 추가한다.") + @Test + void saveMemberActionTest() throws Exception { + MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest(List.of( + new MemberActionSaveRequest("웨디", "IN"), + new MemberActionSaveRequest("소하", "IN"), + new MemberActionSaveRequest("토다리", "IN"), + new MemberActionSaveRequest("쿠키", "IN"))); + + String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); + + mockMvc.perform(post("/api/events/TOKEN/actions/members") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } +} From 22e4af89eba091145a12f3a892e2d81b2c84d475 Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Mon, 22 Jul 2024 15:59:33 +0900 Subject: [PATCH 064/273] =?UTF-8?q?[BE]=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20(#62)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee --- .../haengdong/application/BillActionService.java | 12 ++++++------ .../server/haengdong/application/EventService.java | 6 +++--- .../haengdong/application/MemberActionFactory.java | 8 ++++---- .../haengdong/application/MemberActionService.java | 12 ++++++------ .../application/request/BillActionAppRequest.java | 4 ++-- .../application/request/EventAppRequest.java | 2 +- .../request/MemberActionSaveAppRequest.java | 6 +++--- .../application/response/EventAppResponse.java | 2 +- .../haengdong/domain/{ => action}/Action.java | 3 ++- .../action}/ActionRepository.java | 5 ++--- .../haengdong/domain/{ => action}/BillAction.java | 2 +- .../action}/BillActionRepository.java | 5 ++--- .../domain/{ => action}/MemberAction.java | 2 +- .../action}/MemberActionRepository.java | 5 ++--- .../domain/{ => action}/MemberActionStatus.java | 2 +- .../domain/{ => action}/MemberGroupIdProvider.java | 2 +- .../server/haengdong/domain/{ => event}/Event.java | 2 +- .../event}/EventRepository.java | 3 +-- .../haengdong/domain/{ => event}/EventStep.java | 2 +- .../domain/{ => event}/EventTokenProvider.java | 2 +- .../application/BillActionServiceTest.java | 8 ++++---- .../haengdong/application/EventServiceTest.java | 2 +- .../application/MemberActionFactoryTest.java | 14 +++++++------- .../application/MemberActionServiceTest.java | 14 +++++++------- .../haengdong/domain/{ => action}/ActionTest.java | 3 ++- .../domain/{ => action}/BillActionTest.java | 3 ++- 26 files changed, 65 insertions(+), 66 deletions(-) rename server/src/main/java/server/haengdong/domain/{ => action}/Action.java (91%) rename server/src/main/java/server/haengdong/{persistence => domain/action}/ActionRepository.java (83%) rename server/src/main/java/server/haengdong/domain/{ => action}/BillAction.java (97%) rename server/src/main/java/server/haengdong/{persistence => domain/action}/BillActionRepository.java (76%) rename server/src/main/java/server/haengdong/domain/{ => action}/MemberAction.java (97%) rename server/src/main/java/server/haengdong/{persistence => domain/action}/MemberActionRepository.java (80%) rename server/src/main/java/server/haengdong/domain/{ => action}/MemberActionStatus.java (90%) rename server/src/main/java/server/haengdong/domain/{ => action}/MemberGroupIdProvider.java (82%) rename server/src/main/java/server/haengdong/domain/{ => event}/Event.java (93%) rename server/src/main/java/server/haengdong/{persistence => domain/event}/EventRepository.java (78%) rename server/src/main/java/server/haengdong/domain/{ => event}/EventStep.java (94%) rename server/src/main/java/server/haengdong/domain/{ => event}/EventTokenProvider.java (84%) rename server/src/test/java/server/haengdong/domain/{ => action}/ActionTest.java (89%) rename server/src/test/java/server/haengdong/domain/{ => action}/BillActionTest.java (96%) diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java index 0c62c133f..272eee7e8 100644 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -5,12 +5,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.domain.Action; -import server.haengdong.domain.BillAction; -import server.haengdong.domain.Event; -import server.haengdong.persistence.ActionRepository; -import server.haengdong.persistence.BillActionRepository; -import server.haengdong.persistence.EventRepository; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.event.EventRepository; @RequiredArgsConstructor @Transactional(readOnly = true) diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index 6a5304e32..5fc9cd01c 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -4,9 +4,9 @@ import org.springframework.stereotype.Service; import server.haengdong.application.request.EventAppRequest; import server.haengdong.application.response.EventAppResponse; -import server.haengdong.domain.Event; -import server.haengdong.domain.EventTokenProvider; -import server.haengdong.persistence.EventRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventTokenProvider; +import server.haengdong.domain.event.EventRepository; @RequiredArgsConstructor @Service diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java index d583967a0..46fd9ed1a 100644 --- a/server/src/main/java/server/haengdong/application/MemberActionFactory.java +++ b/server/src/main/java/server/haengdong/application/MemberActionFactory.java @@ -7,10 +7,10 @@ import org.springframework.stereotype.Component; import server.haengdong.application.request.MemberActionSaveAppRequest; import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.Action; -import server.haengdong.domain.MemberAction; -import server.haengdong.domain.MemberActionStatus; -import server.haengdong.domain.MemberGroupIdProvider; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.action.MemberGroupIdProvider; @RequiredArgsConstructor @Component diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java index 491981b06..1acc88b03 100644 --- a/server/src/main/java/server/haengdong/application/MemberActionService.java +++ b/server/src/main/java/server/haengdong/application/MemberActionService.java @@ -5,12 +5,12 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.Action; -import server.haengdong.domain.Event; -import server.haengdong.domain.MemberAction; -import server.haengdong.persistence.ActionRepository; -import server.haengdong.persistence.EventRepository; -import server.haengdong.persistence.MemberActionRepository; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.action.MemberActionRepository; @RequiredArgsConstructor @Transactional(readOnly = true) diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java index 33c335737..acd0149f9 100644 --- a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java +++ b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java @@ -1,7 +1,7 @@ package server.haengdong.application.request; -import server.haengdong.domain.Action; -import server.haengdong.domain.BillAction; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; public record BillActionAppRequest( String title, diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java index 8db47eba9..1eea6adf4 100644 --- a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java +++ b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java @@ -1,6 +1,6 @@ package server.haengdong.application.request; -import server.haengdong.domain.Event; +import server.haengdong.domain.event.Event; public record EventAppRequest(String name) { diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java index a7c90efe4..f7f8d8fc2 100644 --- a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java +++ b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java @@ -1,8 +1,8 @@ package server.haengdong.application.request; -import server.haengdong.domain.Action; -import server.haengdong.domain.MemberAction; -import server.haengdong.domain.MemberActionStatus; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; public record MemberActionSaveAppRequest(String name, String status) { diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java index 37b63dec2..f331d0011 100644 --- a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java +++ b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java @@ -1,6 +1,6 @@ package server.haengdong.application.response; -import server.haengdong.domain.Event; +import server.haengdong.domain.event.Event; public record EventAppResponse(String token) { diff --git a/server/src/main/java/server/haengdong/domain/Action.java b/server/src/main/java/server/haengdong/domain/action/Action.java similarity index 91% rename from server/src/main/java/server/haengdong/domain/Action.java rename to server/src/main/java/server/haengdong/domain/action/Action.java index be294dac3..11f91fc38 100644 --- a/server/src/main/java/server/haengdong/domain/Action.java +++ b/server/src/main/java/server/haengdong/domain/action/Action.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.action; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -9,6 +9,7 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import server.haengdong.domain.event.Event; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/server/src/main/java/server/haengdong/persistence/ActionRepository.java b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java similarity index 83% rename from server/src/main/java/server/haengdong/persistence/ActionRepository.java rename to server/src/main/java/server/haengdong/domain/action/ActionRepository.java index 7b7b838d2..c2138e42f 100644 --- a/server/src/main/java/server/haengdong/persistence/ActionRepository.java +++ b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java @@ -1,12 +1,11 @@ -package server.haengdong.persistence; +package server.haengdong.domain.action; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import server.haengdong.domain.Action; -import server.haengdong.domain.Event; +import server.haengdong.domain.event.Event; @Repository public interface ActionRepository extends JpaRepository { diff --git a/server/src/main/java/server/haengdong/domain/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java similarity index 97% rename from server/src/main/java/server/haengdong/domain/BillAction.java rename to server/src/main/java/server/haengdong/domain/action/BillAction.java index 557715e4b..503715fa1 100644 --- a/server/src/main/java/server/haengdong/domain/BillAction.java +++ b/server/src/main/java/server/haengdong/domain/action/BillAction.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.action; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; diff --git a/server/src/main/java/server/haengdong/persistence/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java similarity index 76% rename from server/src/main/java/server/haengdong/persistence/BillActionRepository.java rename to server/src/main/java/server/haengdong/domain/action/BillActionRepository.java index 03db3056e..1ad7416aa 100644 --- a/server/src/main/java/server/haengdong/persistence/BillActionRepository.java +++ b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java @@ -1,11 +1,10 @@ -package server.haengdong.persistence; +package server.haengdong.domain.action; import java.util.List; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import server.haengdong.domain.BillAction; -import server.haengdong.domain.Event; +import server.haengdong.domain.event.Event; @Repository public interface BillActionRepository extends JpaRepository { diff --git a/server/src/main/java/server/haengdong/domain/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java similarity index 97% rename from server/src/main/java/server/haengdong/domain/MemberAction.java rename to server/src/main/java/server/haengdong/domain/action/MemberAction.java index eb8d8fdec..6e5f0d805 100644 --- a/server/src/main/java/server/haengdong/domain/MemberAction.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberAction.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.action; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; diff --git a/server/src/main/java/server/haengdong/persistence/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java similarity index 80% rename from server/src/main/java/server/haengdong/persistence/MemberActionRepository.java rename to server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java index 97d06618b..6c4769e61 100644 --- a/server/src/main/java/server/haengdong/persistence/MemberActionRepository.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java @@ -1,12 +1,11 @@ -package server.haengdong.persistence; +package server.haengdong.domain.action; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import server.haengdong.domain.Event; -import server.haengdong.domain.MemberAction; +import server.haengdong.domain.event.Event; @Repository public interface MemberActionRepository extends JpaRepository { diff --git a/server/src/main/java/server/haengdong/domain/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java similarity index 90% rename from server/src/main/java/server/haengdong/domain/MemberActionStatus.java rename to server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java index 6172bdb4d..afcb31337 100644 --- a/server/src/main/java/server/haengdong/domain/MemberActionStatus.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.action; import java.util.Arrays; diff --git a/server/src/main/java/server/haengdong/domain/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java similarity index 82% rename from server/src/main/java/server/haengdong/domain/MemberGroupIdProvider.java rename to server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java index c4166e2be..9e32bd733 100644 --- a/server/src/main/java/server/haengdong/domain/MemberGroupIdProvider.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.action; import org.springframework.stereotype.Component; diff --git a/server/src/main/java/server/haengdong/domain/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java similarity index 93% rename from server/src/main/java/server/haengdong/domain/Event.java rename to server/src/main/java/server/haengdong/domain/event/Event.java index 8c24edc4d..c6877e1a6 100644 --- a/server/src/main/java/server/haengdong/domain/Event.java +++ b/server/src/main/java/server/haengdong/domain/event/Event.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.event; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; diff --git a/server/src/main/java/server/haengdong/persistence/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java similarity index 78% rename from server/src/main/java/server/haengdong/persistence/EventRepository.java rename to server/src/main/java/server/haengdong/domain/event/EventRepository.java index 5c08ca98c..6038c368b 100644 --- a/server/src/main/java/server/haengdong/persistence/EventRepository.java +++ b/server/src/main/java/server/haengdong/domain/event/EventRepository.java @@ -1,9 +1,8 @@ -package server.haengdong.persistence; +package server.haengdong.domain.event; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import server.haengdong.domain.Event; @Repository public interface EventRepository extends JpaRepository { diff --git a/server/src/main/java/server/haengdong/domain/EventStep.java b/server/src/main/java/server/haengdong/domain/event/EventStep.java similarity index 94% rename from server/src/main/java/server/haengdong/domain/EventStep.java rename to server/src/main/java/server/haengdong/domain/event/EventStep.java index b25035fa5..297abdb66 100644 --- a/server/src/main/java/server/haengdong/domain/EventStep.java +++ b/server/src/main/java/server/haengdong/domain/event/EventStep.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.event; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; diff --git a/server/src/main/java/server/haengdong/domain/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java similarity index 84% rename from server/src/main/java/server/haengdong/domain/EventTokenProvider.java rename to server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java index 54d455f35..6450f0dcf 100644 --- a/server/src/main/java/server/haengdong/domain/EventTokenProvider.java +++ b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.event; import java.util.UUID; import org.springframework.stereotype.Component; diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java index df19b9e63..178e850e3 100644 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -10,10 +10,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.domain.BillAction; -import server.haengdong.domain.Event; -import server.haengdong.persistence.BillActionRepository; -import server.haengdong.persistence.EventRepository; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.event.EventRepository; @SpringBootTest class BillActionServiceTest { diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java index 5fef04b81..12a5a08a5 100644 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -11,7 +11,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import server.haengdong.application.request.EventAppRequest; import server.haengdong.application.response.EventAppResponse; -import server.haengdong.domain.EventTokenProvider; +import server.haengdong.domain.event.EventTokenProvider; @SpringBootTest class EventServiceTest { diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java index a0ac9916f..b8251a307 100644 --- a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java +++ b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java @@ -13,13 +13,13 @@ import org.springframework.boot.test.context.SpringBootTest; import server.haengdong.application.request.MemberActionSaveAppRequest; import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.Action; -import server.haengdong.domain.Event; -import server.haengdong.domain.MemberAction; -import server.haengdong.domain.MemberActionStatus; -import server.haengdong.persistence.ActionRepository; -import server.haengdong.persistence.EventRepository; -import server.haengdong.persistence.MemberActionRepository; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.action.MemberActionRepository; @SpringBootTest class MemberActionFactoryTest { diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java index 73a7c3d9d..73a1f5376 100644 --- a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java @@ -10,13 +10,13 @@ import org.springframework.boot.test.context.SpringBootTest; import server.haengdong.application.request.MemberActionSaveAppRequest; import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.Action; -import server.haengdong.domain.Event; -import server.haengdong.domain.MemberAction; -import server.haengdong.domain.MemberActionStatus; -import server.haengdong.persistence.ActionRepository; -import server.haengdong.persistence.EventRepository; -import server.haengdong.persistence.MemberActionRepository; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.action.MemberActionRepository; @SpringBootTest class MemberActionServiceTest { diff --git a/server/src/test/java/server/haengdong/domain/ActionTest.java b/server/src/test/java/server/haengdong/domain/action/ActionTest.java similarity index 89% rename from server/src/test/java/server/haengdong/domain/ActionTest.java rename to server/src/test/java/server/haengdong/domain/action/ActionTest.java index a699fb04a..199a4f628 100644 --- a/server/src/test/java/server/haengdong/domain/ActionTest.java +++ b/server/src/test/java/server/haengdong/domain/action/ActionTest.java @@ -1,9 +1,10 @@ -package server.haengdong.domain; +package server.haengdong.domain.action; import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; class ActionTest { diff --git a/server/src/test/java/server/haengdong/domain/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java similarity index 96% rename from server/src/test/java/server/haengdong/domain/BillActionTest.java rename to server/src/test/java/server/haengdong/domain/action/BillActionTest.java index 5789f8c94..d179ca6eb 100644 --- a/server/src/test/java/server/haengdong/domain/BillActionTest.java +++ b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java @@ -1,4 +1,4 @@ -package server.haengdong.domain; +package server.haengdong.domain.action; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.domain.event.Event; class BillActionTest { From e9ceb0f12bf34a5e8b9384a5d7fef70e3262df4b Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Mon, 22 Jul 2024 17:13:24 +0900 Subject: [PATCH 065/273] =?UTF-8?q?feat:=20api=20wrapping=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=83=9D=EC=84=B1=20(#68)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: JinHo Kim Co-authored-by: Pakxe Co-authored-by: Soyeon Choe --- client/src/apis/fetcher.ts | 126 +++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 client/src/apis/fetcher.ts diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts new file mode 100644 index 000000000..55c28d708 --- /dev/null +++ b/client/src/apis/fetcher.ts @@ -0,0 +1,126 @@ +type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; + +type Body = ReadableStream | XMLHttpRequestBodyInit; +type HeadersType = [string, string][] | Record | Headers; + +export type ObjectQueryParams = Record; + +type RequestProps = { + baseUrl: string; + endpoint: string; + headers?: HeadersType; + body?: Body | object | null; + queryParams?: ObjectQueryParams; + // errorMessage: string; +}; + +type FetcherProps = RequestProps & { + method: Method; +}; + +type Options = { + method: Method; + headers: HeadersType; + body?: Body | null; +}; + +const objectToQueryString = (params: ObjectQueryParams): string => { + return Object.entries(params) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) + .join('&'); +}; + +export const requestGet = async ({headers = {}, ...args}: RequestProps): Promise => { + const response = await fetcher({ + ...args, + method: 'GET', + headers, + }); + + const data: T = await response.json(); + return data; +}; + +export const requestPatch = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'PATCH', headers, ...args}); +}; + +export const requestPut = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'PUT', headers, ...args}); +}; + +export const requestPost = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'POST', headers, ...args}); +}; + +export const requestDelete = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'DELETE', headers, ...args}); +}; + +const fetcher = ({method, baseUrl, endpoint, headers, body, queryParams}: FetcherProps) => { + // const token = generateBasicToken(USER_ID, USER_PASSWORD); + const options = { + method, + headers: { + 'Content-Type': 'application/json', + // Authorization: token, + ...headers, + }, + body: body ? JSON.stringify(body) : null, + }; + + let url = `${baseUrl}${endpoint}`; + + if (queryParams) url += `?${objectToQueryString(queryParams)}`; + + return errorHandler(url, options); +}; + +// class ErrorWithHeader extends Error { +// header: string; + +// constructor(header: string, message: string) { +// super(message); +// this.name = this.constructor.name; +// this.header = header; +// } +// } + +const errorHandler = async (url: string, options: Options) => { + try { + const response = await fetch(url, options); + if (!response.ok) { + const serverErrorMessage = await response.text(); + throw new Error(serverErrorMessage || ''); // 받은 에러 메세지가 없는 경우는 서버에게.. + } + return response; + } catch (error) { + console.error(error); + throw new Error('아 에러났다;; 인생이 행복해질거에요 에러덕분에요ㅎㅎ'); + // throw new ErrorWithHeader(errorMessageHeader, getErrorMessage(error)); + } +}; + +// export const ERROR_MESSAGE = { +// SYSTEM_FAULT: 'system error. 관리자에게 문의하십시오', +// OFFLINE: '네트워크 연결이 끊어졌습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.', +// UNKNOWN: '알 수 없는 에러입니다. 관리자에게 문의해주세요. (연락처...)', +// }; + +// const getErrorMessage = (error: unknown) => { +// return ERROR_MESSAGE.UNKNOWN; + +// if (error instanceof TypeError) return ERROR_MESSAGE.OFFLINE; + +// if (error instanceof Error) { +// const mappedErrorMessage = Object.entries(SERVER_ERROR_MESSAGE).find(([key]) => { +// const upperCaseErrorMessage = convertToUpperCase(error.message.split(SERVER_ERROR_MESSAGE_DIVIDER)[0]); + +// return upperCaseErrorMessage.includes(key); +// })?.[1]; + +// return mappedErrorMessage ?? ERROR_MESSAGE.UNKNOWN; +// } + +// return ERROR_MESSAGE.UNKNOWN; +// }; From 784745e092d84e02c24bba7b297ba20374319df2 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Tue, 23 Jul 2024 10:33:50 +0900 Subject: [PATCH 066/273] =?UTF-8?q?[FE]=20@svgr/webpack=20=ED=94=8C?= =?UTF-8?q?=EB=9F=AC=EA=B7=B8=EC=9D=B8=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/package-lock.json | 2601 ++++++++++++++++++++++++++++++++++++-- client/package.json | 1 + client/webpack.config.js | 8 + 3 files changed, 2530 insertions(+), 80 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 6542cbc8d..975d4461e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -17,6 +17,7 @@ "devDependencies": { "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", + "@svgr/webpack": "^8.1.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", @@ -47,6 +48,19 @@ "npm": ">=10.7.0" } }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", @@ -59,6 +73,95 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/compat-data": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", + "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", + "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.9", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-module-transforms": "^7.24.9", + "@babel/helpers": "^7.24.8", + "@babel/parser": "^7.24.8", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/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/core/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/generator": { "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", @@ -73,6 +176,162 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", + "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", + "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", + "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/@babel/helper-environment-visitor": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", @@ -107,6 +366,19 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", @@ -119,10 +391,30 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", + "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -130,103 +422,1602 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-string-parser": { + "node_modules/@babel/helper-plugin-utils": { "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "dev": true, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-identifier": { + "node_modules/@babel/helper-remap-async-to-generator": { "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", + "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/highlight": { + "node_modules/@babel/helper-replace-supers": { "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", + "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", + "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", + "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", + "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", + "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", + "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", + "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", + "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", + "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", + "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "node_modules/@babel/preset-env": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", + "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.8", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" }, "engines": { - "node": ">=4" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", - "bin": { - "parser": "bin/babel-parser.js" + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "node_modules/@babel/runtime": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", @@ -845,41 +2636,319 @@ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", + "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" }, "engines": { - "node": ">= 8" + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", "dev": true, - "optional": true, + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, "engines": { "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "node": ">=14" }, "funding": { - "url": "https://opencollective.com/unts" + "type": "github", + "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@remix-run/router": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", - "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, "engines": { - "node": ">=14.0.0" + "node": ">=10.13.0" } }, "node_modules/@types/body-parser": { @@ -1995,6 +4064,54 @@ "node": ">=10" } }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2197,6 +4314,18 @@ "tslib": "^2.0.3" } }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001642", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", @@ -2426,6 +4555,19 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -2523,6 +4665,19 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", @@ -2547,6 +4702,39 @@ "node": ">=4" } }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -4298,6 +6486,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -5723,6 +7920,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -5755,6 +7958,12 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -6941,11 +9150,38 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -6964,6 +9200,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -7464,6 +9738,16 @@ "node": ">=8" } }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -7861,6 +10145,117 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/svgo/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/synckit": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", @@ -8246,6 +10641,46 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -8935,6 +11370,12 @@ } } }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", diff --git a/client/package.json b/client/package.json index f94bea034..ba5abcff0 100644 --- a/client/package.json +++ b/client/package.json @@ -15,6 +15,7 @@ "devDependencies": { "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", + "@svgr/webpack": "^8.1.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", diff --git a/client/webpack.config.js b/client/webpack.config.js index 10b9352b7..69df113fe 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -39,6 +39,14 @@ export default { test: /\.css$/i, use: ['style-loader', 'css-loader'], }, + { + test: /\.svg$/, + use: [ + { + loader: '@svgr/webpack', + }, + ], + }, ], }, plugins: [ From 880833a632a489cd5b503f4a85fbd3a09cdbfe14 Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Tue, 23 Jul 2024 15:55:11 +0900 Subject: [PATCH 067/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#75)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kunsanglee --- .../haengdong/application/EventService.java | 9 ++++++- .../response/EventDetailAppResponse.java | 10 ++++++++ .../presentation/EventController.java | 10 ++++++++ .../response/EventDetailResponse.java | 10 ++++++++ .../application/EventServiceTest.java | 24 +++++++++++++++++++ .../presentation/EventControllerTest.java | 16 +++++++++++++ 6 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index 5fc9cd01c..ea4384148 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -4,9 +4,10 @@ import org.springframework.stereotype.Service; import server.haengdong.application.request.EventAppRequest; import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventTokenProvider; import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.event.EventTokenProvider; @RequiredArgsConstructor @Service @@ -22,4 +23,10 @@ public EventAppResponse saveEvent(EventAppRequest request) { return EventAppResponse.of(event); } + + public EventDetailAppResponse findEvent(String token) { + Event event = eventRepository.findByToken(token).orElseThrow(() -> new IllegalArgumentException("")); + + return EventDetailAppResponse.of(event); + } } diff --git a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java new file mode 100644 index 000000000..6e38826d4 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.event.Event; + +public record EventDetailAppResponse(String eventName) { + + public static EventDetailAppResponse of(Event event) { + return new EventDetailAppResponse(event.getName()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java index 5254a78ae..1cc7dc77a 100644 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -3,11 +3,14 @@ import java.net.URI; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import server.haengdong.application.EventService; import server.haengdong.application.response.EventAppResponse; import server.haengdong.presentation.request.EventSaveRequest; +import server.haengdong.presentation.response.EventDetailResponse; @RequiredArgsConstructor @RestController @@ -23,4 +26,11 @@ public ResponseEntity saveEvent(EventSaveRequest request) { .location(URI.create("events/" + eventAppResponse.token())) .build(); } + + @GetMapping("/api/events/{token}") + public ResponseEntity findEvent(@PathVariable("token") String token) { + EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); + + return ResponseEntity.ok(eventDetailResponse); + } } diff --git a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java new file mode 100644 index 000000000..c18694393 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.EventDetailAppResponse; + +public record EventDetailResponse(String eventName) { + + public static EventDetailResponse of(EventDetailAppResponse response) { + return new EventDetailResponse(response.eventName()); + } +} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java index 12a5a08a5..31b1c650e 100644 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -11,6 +12,9 @@ import org.springframework.boot.test.mock.mockito.MockBean; import server.haengdong.application.request.EventAppRequest; import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; import server.haengdong.domain.event.EventTokenProvider; @SpringBootTest @@ -22,6 +26,14 @@ class EventServiceTest { @MockBean private EventTokenProvider eventTokenProvider; + @Autowired + private EventRepository eventRepository; + + @AfterEach + void tearDown() { + eventRepository.deleteAllInBatch(); + } + @DisplayName("행사를 생성한다") @Test void saveEventTest() { @@ -32,4 +44,16 @@ void saveEventTest() { assertThat(response.token()).isEqualTo("TOKEN"); } + + @DisplayName("토큰으로 행사를 조회한다.") + @Test + void findEventTest() { + String token = "TOKEN"; + Event event = new Event("행동대장 회식", token); + eventRepository.save(event); + + EventDetailAppResponse eventDetailAppResponse = eventService.findEvent(token); + + assertThat(eventDetailAppResponse.eventName()).isEqualTo("행동대장 회식"); + } } diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java index a1d67f0a1..c50431696 100644 --- a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java @@ -2,8 +2,10 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.fasterxml.jackson.databind.ObjectMapper; @@ -18,6 +20,7 @@ import server.haengdong.application.EventService; import server.haengdong.application.request.EventAppRequest; import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; import server.haengdong.presentation.request.EventSaveRequest; @WebMvcTest(EventController.class) @@ -48,4 +51,17 @@ void saveEvent() throws Exception { .andExpect(status().isOk()) .andExpect(MockMvcResultMatchers.redirectedUrl("events/" + token)); } + + @DisplayName("토큰으로 행사를 조회한다.") + @Test + void findEventTest() throws Exception { + String token = "TOKEN"; + EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); + given(eventService.findEvent(token)).willReturn(eventDetailAppResponse); + + mockMvc.perform(get("/api/events/" + token)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.eventName").value("행동대장 회식")); + } } From ac916e8cb31426c1fa82c21de4518e457c552deb Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Tue, 23 Jul 2024 16:30:48 +0900 Subject: [PATCH 068/273] =?UTF-8?q?[BE]=20=EC=84=A4=EC=A0=95=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=84=9C=EB=B8=8C=20=EB=AA=A8=EB=93=88=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20(#82)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh --------- Co-authored-by: kunsanglee Co-authored-by: Arachne Co-authored-by: khabh --- .github/workflows/backend-push.yml | 3 +++ .gitmodules | 3 +++ server/Dockerfile | 2 +- server/src/main/resources/application.yml | 28 +++++++++++++++-------- server/src/main/resources/config | 1 + server/src/test/resources/application.yml | 15 ++++++++++++ 6 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 .gitmodules create mode 160000 server/src/main/resources/config create mode 100644 server/src/test/resources/application.yml diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml index 5a8d5f4ef..a35eaea7b 100644 --- a/.github/workflows/backend-push.yml +++ b/.github/workflows/backend-push.yml @@ -21,6 +21,9 @@ jobs: steps: - name: CheckOut uses: actions/checkout@v4 + with: + token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} + submodules: true - name: Set up JDK 17 uses: actions/setup-java@v4 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..a067fc391 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "server/src/main/resources/config"] + path = server/src/main/resources/config + url = https://github.com/woowacourse-teams/2024-haeng-dong-config.git diff --git a/server/Dockerfile b/server/Dockerfile index 38c565c85..66a2d0ab3 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -14,4 +14,4 @@ COPY --from=build /app/build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar EXPOSE 8080 ENTRYPOINT ["java"] -CMD ["-jar", "haengdong-0.0.1-SNAPSHOT.jar"] +CMD ["-Dspring.profiles.active=dev", "-jar", "haengdong-0.0.1-SNAPSHOT.jar"] diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index 49c481eaa..aca841de8 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -1,15 +1,23 @@ spring: - h2: - console: - enabled: true - path: /h2-console datasource: - url: jdbc:h2:mem:database + url: jdbc:mysql://localhost:3306/haengdong + username: root + password: 1234 + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: - defer-datasource-initialization: true - show-sql: true + hibernate: + ddl-auto: none properties: hibernate: - format_sql: true - hibernate: - ddl-auto: create-drop + dialect: org.hibernate.dialect.MySQL8Dialect + format_sql: true + show-sql: true + +--- + +spring: + config: + import: classpath:config/application-dev.yml + activate: + on-profile: dev diff --git a/server/src/main/resources/config b/server/src/main/resources/config new file mode 160000 index 000000000..c12697b65 --- /dev/null +++ b/server/src/main/resources/config @@ -0,0 +1 @@ +Subproject commit c12697b650b8a8adf27fd66377f6e62bb6b8a49d diff --git a/server/src/test/resources/application.yml b/server/src/test/resources/application.yml new file mode 100644 index 000000000..49c481eaa --- /dev/null +++ b/server/src/test/resources/application.yml @@ -0,0 +1,15 @@ +spring: + h2: + console: + enabled: true + path: /h2-console + datasource: + url: jdbc:h2:mem:database + jpa: + defer-datasource-initialization: true + show-sql: true + properties: + hibernate: + format_sql: true + hibernate: + ddl-auto: create-drop From 8665f7a7e1e9ea8a6869c00db3ab7dd1949d1e4b Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Tue, 23 Jul 2024 17:27:29 +0900 Subject: [PATCH 069/273] =?UTF-8?q?[BE]=20=EC=9A=94=EC=B2=AD=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EA=B0=80=20=EB=A7=B5=ED=95=91=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=20(#86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kunsanglee Co-authored-by: Arachneee Co-authored-by: khabh --- .../java/server/haengdong/presentation/EventController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java index 1cc7dc77a..538ca9c1e 100644 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -6,6 +6,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import server.haengdong.application.EventService; import server.haengdong.application.response.EventAppResponse; @@ -19,7 +20,7 @@ public class EventController { private final EventService eventService; @PostMapping("/api/events") - public ResponseEntity saveEvent(EventSaveRequest request) { + public ResponseEntity saveEvent(@RequestBody EventSaveRequest request) { EventAppResponse eventAppResponse = eventService.saveEvent(request.toAppRequest()); return ResponseEntity.ok() From 22c1ab79aeeadf8f6b99b3131e79b345de9e9cde Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Wed, 24 Jul 2024 10:56:45 +0900 Subject: [PATCH 070/273] =?UTF-8?q?feat:=20=ED=98=84=EC=9E=AC=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=20=EC=9D=B8=EC=9B=90=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84=20(#70)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/MemberActionService.java | 27 +++++++++++--- .../response/CurrentMemberAppResponse.java | 10 +++++ .../domain/action/CurrentMembers.java | 37 +++++++++++++++++++ .../presentation/MemberActionController.java | 12 ++++++ .../response/CurrentMemberResponse.java | 10 +++++ .../response/CurrentMembersResponse.java | 15 ++++++++ .../application/MemberActionServiceTest.java | 29 ++++++++++----- .../domain/action/CurrentMembersTest.java | 30 +++++++++++++++ .../MemberActionControllerTest.java | 21 +++++++++++ 9 files changed, 176 insertions(+), 15 deletions(-) create mode 100644 server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java create mode 100644 server/src/main/java/server/haengdong/domain/action/CurrentMembers.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java create mode 100644 server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java index 1acc88b03..ba17b28c4 100644 --- a/server/src/main/java/server/haengdong/application/MemberActionService.java +++ b/server/src/main/java/server/haengdong/application/MemberActionService.java @@ -5,12 +5,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.application.response.CurrentMemberAppResponse; import server.haengdong.domain.action.Action; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.action.MemberAction; import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; @RequiredArgsConstructor @Transactional(readOnly = true) @@ -24,8 +26,7 @@ public class MemberActionService { @Transactional public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new IllegalArgumentException("event not found")); + Event event = findEvent(token); List findMemberActions = memberActionRepository.findAllByEvent(event); Action action = createStartAction(event); @@ -38,4 +39,20 @@ private Action createStartAction(Event event) { .map(Action::next) .orElse(Action.createFirst(event)); } + + public List getCurrentMembers(String token) { + Event event = findEvent(token); + List findMemberActions = memberActionRepository.findAllByEvent(event); + CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); + + return currentMembers.getMembers() + .stream() + .map(CurrentMemberAppResponse::new) + .toList(); + } + + private Event findEvent(String token) { + return eventRepository.findByToken(token) + .orElseThrow(() -> new IllegalArgumentException("event not found")); + } } diff --git a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java new file mode 100644 index 000000000..6c682d3e9 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.MemberAction; + +public record CurrentMemberAppResponse(String name) { + + public static CurrentMemberAppResponse of(MemberAction memberAction) { + return new CurrentMemberAppResponse(memberAction.getMemberName()); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java new file mode 100644 index 000000000..e6843a404 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java @@ -0,0 +1,37 @@ +package server.haengdong.domain.action; + +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class CurrentMembers { + + private final Set members; + + public static CurrentMembers of(List memberActions) { + List sortedMemberActions = getSortedMemberActions(memberActions); + Set members = new HashSet<>(); + for (MemberAction memberAction : sortedMemberActions) { + String member = memberAction.getMemberName(); + if (memberAction.isSameStatus(MemberActionStatus.IN)) { + members.add(member); + continue; + } + members.remove(member); + } + + return new CurrentMembers(members); + } + + private static List getSortedMemberActions(List memberActions) { + return memberActions.stream() + .sorted(Comparator.comparing(MemberAction::getSequence)) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java index e35bcfd7b..cd45e3237 100644 --- a/server/src/main/java/server/haengdong/presentation/MemberActionController.java +++ b/server/src/main/java/server/haengdong/presentation/MemberActionController.java @@ -1,13 +1,17 @@ package server.haengdong.presentation; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import server.haengdong.application.MemberActionService; +import server.haengdong.application.response.CurrentMemberAppResponse; import server.haengdong.presentation.request.MemberActionsSaveRequest; +import server.haengdong.presentation.response.CurrentMembersResponse; @RequiredArgsConstructor @RestController @@ -24,4 +28,12 @@ public ResponseEntity saveMemberAction( return ResponseEntity.ok().build(); } + + @GetMapping("/api/events/{token}/members/current") + public ResponseEntity getCurrentMembers(@PathVariable("token") String token) { + List currentMembers = memberActionService.getCurrentMembers(token); + + return ResponseEntity.ok() + .body(CurrentMembersResponse.of(currentMembers)); + } } diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java new file mode 100644 index 000000000..4308c7d17 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.CurrentMemberAppResponse; + +public record CurrentMemberResponse(String name) { + + public static CurrentMemberResponse of(CurrentMemberAppResponse response) { + return new CurrentMemberResponse(response.name()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java new file mode 100644 index 000000000..4eb915dd4 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.CurrentMemberAppResponse; + +public record CurrentMembersResponse(List members) { + + public static CurrentMembersResponse of(List currentMembers) { + List responses = currentMembers.stream() + .map(CurrentMemberResponse::of) + .toList(); + + return new CurrentMembersResponse(responses); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java index 73a1f5376..378aa6006 100644 --- a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java @@ -1,6 +1,9 @@ package server.haengdong.application; import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; import java.util.List; import org.junit.jupiter.api.AfterEach; @@ -11,12 +14,11 @@ import server.haengdong.application.request.MemberActionSaveAppRequest; import server.haengdong.application.request.MemberActionsSaveAppRequest; import server.haengdong.domain.action.Action; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.action.MemberAction; import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; @SpringBootTest class MemberActionServiceTest { @@ -40,12 +42,12 @@ void tearDown() { eventRepository.deleteAllInBatch(); } - @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다") + @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다.") @Test void saveMemberActionTest() { Event event = eventRepository.save(new Event("test", "TOKEN")); Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "망쵸", MemberActionStatus.IN, 1L); + MemberAction memberAction = new MemberAction(action, "망쵸", IN, 1L); memberActionRepository.save(memberAction); assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( @@ -53,16 +55,16 @@ void saveMemberActionTest() { .doesNotThrowAnyException(); } - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다") + @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") @Test void saveMemberActionTest1() { Event event = eventRepository.save(new Event("test", "TOKEN")); Action actionOne = new Action(event, 1L); - MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", MemberActionStatus.IN, 1L); + MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", IN, 1L); memberActionRepository.save(memberActionOne); Action actionTwo = new Action(event, 2L); - MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", MemberActionStatus.OUT, 1L); + MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", OUT, 1L); memberActionRepository.save(memberActionTwo); assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( @@ -70,7 +72,7 @@ void saveMemberActionTest1() { .doesNotThrowAnyException(); } - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다") + @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") @Test void saveMemberActionTest2() { MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( @@ -79,4 +81,11 @@ void saveMemberActionTest2() { assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) .isInstanceOf(IllegalArgumentException.class); } + + @DisplayName("이벤트가 없으면 현재 참여 인원을 조회할 수 없다.") + @Test + void getCurrentMembers() { + assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) + .isInstanceOf(IllegalArgumentException.class); + } } diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java new file mode 100644 index 000000000..37ddca432 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java @@ -0,0 +1,30 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; + +class CurrentMembersTest { + + @DisplayName("인원 변동 이력으로 현재 참여 인원을 계산한다.") + @Test + void of() { + Event event = new Event("test", "TOKEN"); + List memberActions = List.of( + new MemberAction(new Action(event, 1L), "망쵸", IN, 1L), + new MemberAction(new Action(event, 2L), "백호", IN, 1L), + new MemberAction(new Action(event, 3L), "백호", OUT, 1L), + new MemberAction(new Action(event, 4L), "웨디", IN, 1L) + ); + + CurrentMembers currentMembers = CurrentMembers.of(memberActions); + + assertThat(currentMembers.getMembers()) + .containsExactlyInAnyOrder("망쵸", "웨디"); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java index 8f9e71182..be8b89182 100644 --- a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java @@ -1,5 +1,9 @@ package server.haengdong.presentation; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -13,7 +17,9 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import server.haengdong.application.MemberActionService; +import server.haengdong.application.response.CurrentMemberAppResponse; import server.haengdong.presentation.request.MemberActionSaveRequest; import server.haengdong.presentation.request.MemberActionsSaveRequest; @@ -46,4 +52,19 @@ void saveMemberActionTest() throws Exception { .andDo(print()) .andExpect(status().isOk()); } + + @DisplayName("현재 참여 인원을 조회합니다.") + @Test + void getCurrentMembers() throws Exception { + List currentMemberAppResponses = List.of(new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); + + given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); + + mockMvc.perform(get("/api/events/{token}/members/current", "token") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.members[0].name").value(equalTo("소하"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.members[1].name").value(equalTo("토다리"))); + } } From 45861924b1fa71069cf619b9fb1ecf293889ef8b Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:41:04 +0900 Subject: [PATCH 071/273] =?UTF-8?q?design:=20=ED=83=AD=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20height=20=EC=86=8C=EC=88=98?= =?UTF-8?q?=EC=A0=90=20=EB=AC=B8=EC=A0=9C=20(#51)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 --- HDesign/src/components/Tab/Tab.style.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/HDesign/src/components/Tab/Tab.style.ts b/HDesign/src/components/Tab/Tab.style.ts index 1e8054821..2242261b5 100644 --- a/HDesign/src/components/Tab/Tab.style.ts +++ b/HDesign/src/components/Tab/Tab.style.ts @@ -17,13 +17,23 @@ export const tabListStyle = (theme: Theme) => padding: '0.5rem', - borderBottomWidth: 1, - borderBottomStyle: 'solid', - borderBottomColor: theme.colors.gray, - backgroundColor: theme.colors.white, cursor: 'pointer', + + '&::after': { + position: 'absolute', + left: 0, + bottom: 0, + zIndex: 1, + + width: '100%', + height: '0.0625rem', + + backgroundColor: theme.colors.gray, + + content: '""', + }, }); export const tabItemStyle = css({ @@ -42,6 +52,7 @@ export const indicatorStyle = (theme: Theme, leftPosition: string, tabLength: nu position: 'absolute', left: leftPosition, bottom: 0, + zIndex: 2, width: `calc(100% / ${tabLength})`, height: '0.125rem', From 165618a4cf77022676dba4bf93a010a3770067e8 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:43:26 +0900 Subject: [PATCH 072/273] =?UTF-8?q?chore:=20=EB=B0=B0=ED=8F=AC,=20CI=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=A0=84=EB=9E=B5=20?= =?UTF-8?q?=EC=88=98=EB=A6=BD=20#32?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 --- .github/workflows/frontend-pll-request.yml | 34 +++++++++ client/eslint.config.mjs | 2 - client/package-lock.json | 70 +++++++++++++++++++ client/package.json | 1 + .../SetActionModalContent.tsx | 3 +- .../SetActionModalContent/SetPurchase.tsx | 1 + .../CompleteCreateEvent.tsx | 1 + client/src/pages/CreateEvent/CreateEvent.tsx | 1 + client/src/pages/Event/Event.tsx | 6 +- client/src/pages/Main/Main.tsx | 1 + client/src/router.tsx | 4 +- client/tsconfig.json | 4 +- 12 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/frontend-pll-request.yml diff --git a/.github/workflows/frontend-pll-request.yml b/.github/workflows/frontend-pll-request.yml new file mode 100644 index 000000000..b94c4ceeb --- /dev/null +++ b/.github/workflows/frontend-pll-request.yml @@ -0,0 +1,34 @@ +name: frontend-pull-request + +on: + pull_request: + types: [opened, synchronize] + branches: [main, develop] + paths: + - 'client/**' + +jobs: + test: + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ./client + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '20.15.1' + + - name: Install dependencies + working-directory: ./client + run: npm install + + - name: Run lint + working-directory: ./client + run: npm run lint diff --git a/client/eslint.config.mjs b/client/eslint.config.mjs index 23794c081..46d23de19 100644 --- a/client/eslint.config.mjs +++ b/client/eslint.config.mjs @@ -32,8 +32,6 @@ export default [ 'react/react-in-jsx-scope': 'off', 'react/prop-types': 'off', 'react/jsx-uses-vars': 'error', - '@typescript-eslint/no-use-before-define': ['error'], - '@typescript-eslint/explicit-module-boundary-types': 'error', 'import/order': [ 'error', { diff --git a/client/package-lock.json b/client/package-lock.json index 975d4461e..781d96620 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -24,6 +24,7 @@ "@typescript-eslint/parser": "^7.16.0", "css-loader": "^7.1.2", "eslint": "^9.6.0", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-prettier": "^5.1.3", @@ -5454,6 +5455,54 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/eslint-module-utils": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", @@ -6543,6 +6592,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -9312,6 +9373,15 @@ "node": ">=8" } }, + "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, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", diff --git a/client/package.json b/client/package.json index ba5abcff0..7b5875adc 100644 --- a/client/package.json +++ b/client/package.json @@ -22,6 +22,7 @@ "@typescript-eslint/parser": "^7.16.0", "css-loader": "^7.1.2", "eslint": "^9.6.0", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-prettier": "^5.1.3", diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx index 5f052ce5c..2c293abc8 100644 --- a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx +++ b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx @@ -1,6 +1,7 @@ -import {Switch} from '@components/Switch'; import {useState} from 'react'; +import {Switch} from '@components/Switch'; + import SetPurchase from './SetPurchase'; import UpdateParticipants from './UpdateParticipants'; import {switchContainerStyle} from './SetActionModalContent.style'; diff --git a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx index a71c5559b..3112f2d41 100644 --- a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx +++ b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx @@ -1,4 +1,5 @@ import {useState} from 'react'; + import {PurchaseInformation} from '@pages/Event/Event'; interface SetPurchaseProps { diff --git a/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx b/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx index 8c98d710e..083273c8a 100644 --- a/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx +++ b/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx @@ -1,5 +1,6 @@ import {useEffect, useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; + import {ROUTER_URLS} from '@constants/routerUrls'; const CompleteCreateEvent = () => { diff --git a/client/src/pages/CreateEvent/CreateEvent.tsx b/client/src/pages/CreateEvent/CreateEvent.tsx index d44cd5119..5ae0c8d5b 100644 --- a/client/src/pages/CreateEvent/CreateEvent.tsx +++ b/client/src/pages/CreateEvent/CreateEvent.tsx @@ -1,5 +1,6 @@ import {useState} from 'react'; import {useNavigate} from 'react-router-dom'; + import {ROUTER_URLS} from '@constants/routerUrls'; const CreateEvent = () => { diff --git a/client/src/pages/Event/Event.tsx b/client/src/pages/Event/Event.tsx index 20ae6b265..bded81860 100644 --- a/client/src/pages/Event/Event.tsx +++ b/client/src/pages/Event/Event.tsx @@ -1,9 +1,11 @@ -import {SetInitialParticipants} from '@components/Modal/SetInitialParticipants'; -import {Modal} from '@components/Modal'; import {useState} from 'react'; import {useParams} from 'react-router-dom'; + +import {SetInitialParticipants} from '@components/Modal/SetInitialParticipants'; import {SetActionModalContent} from '@components/Modal/SetActionModalContent'; +import {Modal} from '@components/Modal'; + import {orderHeaderStyle} from './Event.style'; export type PurchaseInformation = { diff --git a/client/src/pages/Main/Main.tsx b/client/src/pages/Main/Main.tsx index 13501b755..acaa4a167 100644 --- a/client/src/pages/Main/Main.tsx +++ b/client/src/pages/Main/Main.tsx @@ -1,4 +1,5 @@ import {useNavigate} from 'react-router-dom'; + import {ROUTER_URLS} from '@constants/routerUrls'; const Main = () => { diff --git a/client/src/router.tsx b/client/src/router.tsx index c9c1ea56f..04e1dfc5e 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -1,10 +1,12 @@ import {createBrowserRouter} from 'react-router-dom'; -import {ROUTER_URLS} from '@constants/routerUrls'; + import {MainPage} from '@pages/Main'; import {CreateEventPage} from '@pages/CreateEvent'; import {CompleteCreateEventPage} from '@pages/CompleteCreateEvent'; import {EventPage} from '@pages/Event'; +import {ROUTER_URLS} from '@constants/routerUrls'; + import App from './App'; const router = createBrowserRouter([ diff --git a/client/tsconfig.json b/client/tsconfig.json index 9f0da087d..f285f4d89 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -16,8 +16,8 @@ "jsx": "react-jsx", "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "types": ["jest"], From ce65a4c1d25d9c13da06d3491915f54f27878444 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:55:29 +0900 Subject: [PATCH 073/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(#87)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 --- client/.prettierrc | 2 +- client/package-lock.json | 193 ++++++++---------- client/package.json | 3 + client/src/App.tsx | 7 +- client/src/apis/fetcher.ts | 6 +- client/src/apis/requestPostEvent.ts | 13 ++ client/src/constants/routerUrls.ts | 4 +- client/src/index.css | 6 +- client/src/pages/CompleteCreateEvent/index.ts | 1 - .../Complete.tsx} | 20 +- client/src/pages/Create/Name.tsx | 36 ++++ client/src/pages/Create/index.ts | 2 + client/src/pages/CreateEvent/CreateEvent.tsx | 27 --- client/src/pages/CreateEvent/index.ts | 1 - client/src/pages/Main/Main.tsx | 10 +- client/src/router.tsx | 11 +- client/tsconfig.json | 3 +- client/webpack.config.js | 2 + 18 files changed, 182 insertions(+), 165 deletions(-) create mode 100644 client/src/apis/requestPostEvent.ts delete mode 100644 client/src/pages/CompleteCreateEvent/index.ts rename client/src/pages/{CompleteCreateEvent/CompleteCreateEvent.tsx => Create/Complete.tsx} (50%) create mode 100644 client/src/pages/Create/Name.tsx create mode 100644 client/src/pages/Create/index.ts delete mode 100644 client/src/pages/CreateEvent/CreateEvent.tsx delete mode 100644 client/src/pages/CreateEvent/index.ts diff --git a/client/.prettierrc b/client/.prettierrc index a661f29c2..94ad823ef 100644 --- a/client/.prettierrc +++ b/client/.prettierrc @@ -9,4 +9,4 @@ "jsxSingleQuote": false, "bracketSpacing": false, "proseWrap": "preserve" -} +} \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 781d96620..2fda2f9e6 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,6 +10,9 @@ "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", + "@types/dotenv-webpack": "^7.0.7", + "dotenv-webpack": "^8.1.0", + "haengdong-design": "^0.1.3", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -2529,7 +2532,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -2990,11 +2992,20 @@ "@types/node": "*" } }, + "node_modules/@types/dotenv-webpack": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", + "integrity": "sha512-tltVokFUeYuSjNmHc6N892Asu/JIQcnH2iUF5A29/VKqv9opq6KlrmnKd/Lt/bBikV/z0YN2K0kguTwWirYCMQ==", + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, "node_modules/@types/eslint": { "version": "8.56.10", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -3004,7 +3015,6 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -3013,8 +3023,7 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/express": { "version": "4.17.21", @@ -3064,8 +3073,7 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -3083,7 +3091,6 @@ "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -3451,7 +3458,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -3460,26 +3466,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -3489,14 +3491,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -3508,7 +3508,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -3517,7 +3516,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -3525,14 +3523,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -3548,7 +3544,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -3561,7 +3556,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -3573,7 +3567,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -3587,7 +3580,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" @@ -3640,14 +3632,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/accepts": { "version": "1.3.8", @@ -3666,7 +3656,6 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -3678,7 +3667,6 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, "peerDependencies": { "acorn": "^8" } @@ -3696,7 +3684,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3751,7 +3738,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -3808,8 +3794,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/aria-query": { "version": "5.1.3", @@ -4192,8 +4177,7 @@ "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "node_modules/brace-expansion": { "version": "2.0.1", @@ -4220,7 +4204,6 @@ "version": "4.23.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -4251,8 +4234,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/bundle-name": { "version": "4.1.0", @@ -4331,7 +4313,6 @@ "version": "1.0.30001642", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -4403,7 +4384,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, "engines": { "node": ">=6.0" } @@ -4461,8 +4441,7 @@ "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/compressible": { "version": "2.0.18", @@ -4579,7 +4558,6 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -4683,7 +4661,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, "engines": { "node": ">= 6" }, @@ -4855,7 +4832,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -5034,7 +5010,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, "funding": [ { "type": "github", @@ -5075,12 +5050,41 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, + "node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-defaults": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz", + "integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==", + "dependencies": { + "dotenv": "^8.2.0" + } + }, + "node_modules/dotenv-webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz", + "integrity": "sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag==", + "dependencies": { + "dotenv-defaults": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "webpack": "^4 || ^5" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -5096,8 +5100,7 @@ "node_modules/electron-to-chromium": { "version": "1.4.827", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", - "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==", - "dev": true + "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -5127,7 +5130,6 @@ "version": "5.17.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -5300,8 +5302,7 @@ "node_modules/es-module-lexer": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -5359,7 +5360,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, "engines": { "node": ">=6" } @@ -5799,7 +5799,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -6041,7 +6040,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -6053,7 +6051,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -6062,7 +6059,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -6071,7 +6067,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6095,7 +6090,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -6168,8 +6162,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-diff": { "version": "1.3.0", @@ -6196,8 +6189,7 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -6639,8 +6631,7 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/globals": { "version": "15.8.0", @@ -6705,8 +6696,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", @@ -6714,6 +6704,22 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/haengdong-design": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.3.tgz", + "integrity": "sha512-l/ED7kcE/LAZkuXxEFDU0j5k7Bac+t4dTJIxAAH8Ij9byaxdblzJF4DiRQ10AZ2RfuDzHYuI5MULq+18sU2cXA==", + "dependencies": { + "@emotion/react": "^11.11.4", + "@svgr/webpack": "^8.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -6733,7 +6739,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -7763,7 +7768,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -7782,7 +7786,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -7815,8 +7818,7 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -7931,7 +7933,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -8008,7 +8009,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -8062,8 +8062,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -8112,7 +8111,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -8121,7 +8119,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -8298,14 +8295,12 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -8329,8 +8324,7 @@ "node_modules/node-releases": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -8357,7 +8351,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, "dependencies": { "boolbase": "^1.0.0" }, @@ -9012,7 +9005,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -9056,7 +9048,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -9482,7 +9473,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -9533,7 +9523,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -9612,7 +9601,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -9833,7 +9821,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9842,7 +9829,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9851,7 +9837,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -10193,7 +10178,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -10346,7 +10330,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -10355,7 +10338,6 @@ "version": "5.31.2", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", - "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -10373,7 +10355,6 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -10528,8 +10509,7 @@ "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/type-check": { "version": "0.4.0", @@ -10773,7 +10753,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -10803,7 +10782,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -10851,7 +10829,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", - "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -10873,7 +10850,6 @@ "version": "5.93.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", - "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -11182,7 +11158,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -11467,4 +11442,4 @@ } } } -} +} \ No newline at end of file diff --git a/client/package.json b/client/package.json index 7b5875adc..f25247dc3 100644 --- a/client/package.json +++ b/client/package.json @@ -44,6 +44,9 @@ }, "dependencies": { "@emotion/react": "^11.11.4", + "@types/dotenv-webpack": "^7.0.7", + "dotenv-webpack": "^8.1.0", + "haengdong-design": "^0.1.3", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/App.tsx b/client/src/App.tsx index b6c73d8be..46618d881 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,7 +1,12 @@ +import {HDesignProvider} from 'haengdong-design'; import {Outlet} from 'react-router-dom'; const App: React.FC = () => { - return ; + return ( + + + + ); }; export default App; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 55c28d708..8df81a2c2 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -6,7 +6,7 @@ type HeadersType = [string, string][] | Record | Headers; export type ObjectQueryParams = Record; type RequestProps = { - baseUrl: string; + baseUrl?: string; endpoint: string; headers?: HeadersType; body?: Body | object | null; @@ -24,6 +24,8 @@ type Options = { body?: Body | null; }; +const API_BASE_URL = process.env.API_BASE_URL; + const objectToQueryString = (params: ObjectQueryParams): string => { return Object.entries(params) .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) @@ -57,7 +59,7 @@ export const requestDelete = ({headers = {}, ...args}: RequestProps) => { return fetcher({method: 'DELETE', headers, ...args}); }; -const fetcher = ({method, baseUrl, endpoint, headers, body, queryParams}: FetcherProps) => { +const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: FetcherProps) => { // const token = generateBasicToken(USER_ID, USER_PASSWORD); const options = { method, diff --git a/client/src/apis/requestPostEvent.ts b/client/src/apis/requestPostEvent.ts new file mode 100644 index 000000000..cf6b4716e --- /dev/null +++ b/client/src/apis/requestPostEvent.ts @@ -0,0 +1,13 @@ +import {requestPost} from './fetcher'; + +interface RequestPostEventProps { + name: string; +} + +export const requestPostEvent = async ({name}: RequestPostEventProps) => { + requestPost({ + headers: {'Content-Type': 'application/json'}, + body: {name}, + endpoint: '/api/events', + }); +}; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index c93f9fefe..eb4f6938b 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -1,7 +1,7 @@ export const ROUTER_URLS = { main: '', - createEvent: '/create-event', - completeCreateEvent: '/create-event/complete', + eventCreateName: '/event/create/name', + eventCreateComplete: '/event/create/complete', event: '/event', eventManage: '/event/:eventId', }; diff --git a/client/src/index.css b/client/src/index.css index c6eed01ac..936bdd319 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -1,5 +1,9 @@ body { max-width: 768px; + height: 100lvh; margin: 0 auto; - border: 1px solid gray; +} + +section { + width: 100%; } diff --git a/client/src/pages/CompleteCreateEvent/index.ts b/client/src/pages/CompleteCreateEvent/index.ts deleted file mode 100644 index a1e4fa117..000000000 --- a/client/src/pages/CompleteCreateEvent/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as CompleteCreateEventPage} from './CompleteCreateEvent'; diff --git a/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx b/client/src/pages/Create/Complete.tsx similarity index 50% rename from client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx rename to client/src/pages/Create/Complete.tsx index 083273c8a..c2f499cb6 100644 --- a/client/src/pages/CompleteCreateEvent/CompleteCreateEvent.tsx +++ b/client/src/pages/Create/Complete.tsx @@ -1,5 +1,6 @@ import {useEffect, useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, Title} from 'haengdong-design'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -11,7 +12,7 @@ const CompleteCreateEvent = () => { useEffect(() => { const getUrl = async () => { const eventTitle = location.search; - console.log(eventTitle); + // console.log(eventTitle); // const url = await fetch(); setUrl('hangsapage'); @@ -21,14 +22,15 @@ const CompleteCreateEvent = () => { }, []); return ( -

-

행사 개시

-

- 행사가 성공적으로 개시됐어요 :) 행사 링크를 통해서 참여자 관리가 가능해요. 관리를 위해서 행사 관리 링크를 보관해 - 주세요. -

- -
+ + {/* */} + + <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${url}`)}>관리 페이지로 이동</FixedButton> + </MainLayout> ); }; diff --git a/client/src/pages/Create/Name.tsx b/client/src/pages/Create/Name.tsx new file mode 100644 index 000000000..ee847e258 --- /dev/null +++ b/client/src/pages/Create/Name.tsx @@ -0,0 +1,36 @@ +import {useState} from 'react'; +import {useNavigate} from 'react-router-dom'; +import {FixedButton, Input, MainLayout, TextButton, Title, TopNav} from 'haengdong-design'; + +import {requestPostEvent} from '@apis/requestPostEvent'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const CreateEvent = () => { + const [eventTitle, setEventTitle] = useState(''); + const navigate = useNavigate(); + + const submitEventTitle = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + const result = await requestPostEvent({name: eventTitle}); + + navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({title: eventTitle})}`); + }; + + return ( + <MainLayout> + <TopNav navType="back" /> + <Title title="행사 이름 입력" description="시작할 행사 이름을 입력해 주세요." /> + <form onSubmit={submitEventTitle}> + <Input + value={eventTitle} + onChange={event => setEventTitle(event.target.value)} + placeholder="ex) 행동대장 야유회" + /> + <FixedButton>행동 개시!</FixedButton> + </form> + </MainLayout> + ); +}; + +export default CreateEvent; diff --git a/client/src/pages/Create/index.ts b/client/src/pages/Create/index.ts new file mode 100644 index 000000000..5ce37a93e --- /dev/null +++ b/client/src/pages/Create/index.ts @@ -0,0 +1,2 @@ +export {default as CreateNamePage} from './Name'; +export {default as CreateCompletePage} from './Complete'; diff --git a/client/src/pages/CreateEvent/CreateEvent.tsx b/client/src/pages/CreateEvent/CreateEvent.tsx deleted file mode 100644 index 5ae0c8d5b..000000000 --- a/client/src/pages/CreateEvent/CreateEvent.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import {useState} from 'react'; -import {useNavigate} from 'react-router-dom'; - -import {ROUTER_URLS} from '@constants/routerUrls'; - -const CreateEvent = () => { - const [eventTitle, setEventTitle] = useState(''); - const navigate = useNavigate(); - - const submitEventTitle = (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - navigate(`${ROUTER_URLS.completeCreateEvent}?${new URLSearchParams({title: eventTitle})}`); - }; - - return ( - <section> - <h1>행사 생성하기</h1> - <h3>시작할 행사 이름을 입력해 주세요.</h3> - <form onSubmit={submitEventTitle}> - <input value={eventTitle} onChange={event => setEventTitle(event.target.value)} /> - <button>행동 개시!</button> - </form> - </section> - ); -}; - -export default CreateEvent; diff --git a/client/src/pages/CreateEvent/index.ts b/client/src/pages/CreateEvent/index.ts deleted file mode 100644 index ac2c26d0c..000000000 --- a/client/src/pages/CreateEvent/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as CreateEventPage} from './CreateEvent'; diff --git a/client/src/pages/Main/Main.tsx b/client/src/pages/Main/Main.tsx index acaa4a167..1cb9f6b26 100644 --- a/client/src/pages/Main/Main.tsx +++ b/client/src/pages/Main/Main.tsx @@ -1,4 +1,5 @@ import {useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, Title} from 'haengdong-design'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -6,10 +7,11 @@ const Main = () => { const navigate = useNavigate(); return ( - <section> - <h1>행동대장</h1> - <button onClick={() => navigate(ROUTER_URLS.createEvent)}>행사 생성하기</button> - </section> + <MainLayout> + {/* <TopNav navType="back" /> */} + <Title title="행동대장" description="랜딩페이지입니다." /> + <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateName)}>행사 생성하기</FixedButton> + </MainLayout> ); }; diff --git a/client/src/router.tsx b/client/src/router.tsx index 04e1dfc5e..b6883623b 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -1,8 +1,7 @@ import {createBrowserRouter} from 'react-router-dom'; import {MainPage} from '@pages/Main'; -import {CreateEventPage} from '@pages/CreateEvent'; -import {CompleteCreateEventPage} from '@pages/CompleteCreateEvent'; +import {CreateNamePage, CreateCompletePage} from '@pages/Create'; import {EventPage} from '@pages/Event'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -20,12 +19,12 @@ const router = createBrowserRouter([ element: <MainPage />, }, { - path: ROUTER_URLS.createEvent, - element: <CreateEventPage />, + path: ROUTER_URLS.eventCreateName, + element: <CreateNamePage />, }, { - path: ROUTER_URLS.completeCreateEvent, - element: <CompleteCreateEventPage />, + path: ROUTER_URLS.eventCreateComplete, + element: <CreateCompletePage />, }, { path: ROUTER_URLS.eventManage, diff --git a/client/tsconfig.json b/client/tsconfig.json index f285f4d89..b049bf464 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -20,7 +20,7 @@ // "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "types": ["jest"], + "types": ["node", "jest"], "esModuleInterop": true, "strictNullChecks": true, "strictFunctionTypes": true, @@ -46,5 +46,6 @@ }, "outDir": "./dist" }, + "node": true, "include": ["src"] } diff --git a/client/webpack.config.js b/client/webpack.config.js index 69df113fe..b729f1020 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -3,6 +3,7 @@ import HtmlWebpackPlugin from 'html-webpack-plugin'; import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import {ModifySourcePlugin, ConcatOperation} from 'modify-source-webpack-plugin'; import {fileURLToPath} from 'url'; +import Dotenv from 'dotenv-webpack'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -62,6 +63,7 @@ export default { }, ], }), + new Dotenv(), ], devServer: { port: 3000, From 1be9c4e9a92fe01d74bfd3397ebf01be91b51620 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Wed, 24 Jul 2024 13:50:47 +0900 Subject: [PATCH 074/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=20=ED=99=88?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84=20(#88)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 --- client/package-lock.json | 2300 +++++++---------- client/package.json | 3 +- client/src/apis/baseUrl.ts | 3 + client/src/apis/request/bill.ts | 19 + client/src/apis/request/event.ts | 17 + client/src/apis/request/member.ts | 19 + client/src/apis/request/report.ts | 18 + client/src/apis/request/stepList.ts | 14 + client/src/apis/tempPrefix.ts | 2 + client/src/apis/withEventId.type.ts | 3 + .../MemberReportList/MemberReportList.tsx | 21 + client/src/components/StepList/StepList.tsx | 24 + client/src/constants/routerUrls.ts | 1 + .../useSearchMemberReportList.tsx | 42 + client/src/hooks/useStepList/useStepList.tsx | 47 + client/src/mocks/memberReportSearchList.json | 10 + client/src/mocks/stepList.json | 86 + client/src/pages/CreateEvent/CreateEvent.tsx | 26 + client/src/pages/Home/HomeContent.tsx | 20 + client/src/pages/Home/HomeLayout.tsx | 19 + client/src/pages/Home/index.ts | 1 + client/src/router.tsx | 5 + client/src/types/stepList.ts | 52 + client/webpack.config.js | 2 + 24 files changed, 1448 insertions(+), 1306 deletions(-) create mode 100644 client/src/apis/baseUrl.ts create mode 100644 client/src/apis/request/bill.ts create mode 100644 client/src/apis/request/event.ts create mode 100644 client/src/apis/request/member.ts create mode 100644 client/src/apis/request/report.ts create mode 100644 client/src/apis/request/stepList.ts create mode 100644 client/src/apis/tempPrefix.ts create mode 100644 client/src/apis/withEventId.type.ts create mode 100644 client/src/components/MemberReportList/MemberReportList.tsx create mode 100644 client/src/components/StepList/StepList.tsx create mode 100644 client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx create mode 100644 client/src/hooks/useStepList/useStepList.tsx create mode 100644 client/src/mocks/memberReportSearchList.json create mode 100644 client/src/mocks/stepList.json create mode 100644 client/src/pages/CreateEvent/CreateEvent.tsx create mode 100644 client/src/pages/Home/HomeContent.tsx create mode 100644 client/src/pages/Home/HomeLayout.tsx create mode 100644 client/src/pages/Home/index.ts create mode 100644 client/src/types/stepList.ts diff --git a/client/package-lock.json b/client/package-lock.json index 2fda2f9e6..d66f61a8b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.3", + "haengdong-design": "^0.1.20", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -26,6 +26,7 @@ "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "css-loader": "^7.1.2", + "dotenv": "^16.4.5", "eslint": "^9.6.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", @@ -56,7 +57,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -81,7 +81,6 @@ "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -90,7 +89,6 @@ "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -119,57 +117,12 @@ "node_modules/@babel/core/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/core/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/@babel/generator": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", - "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", + "version": "7.24.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", + "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", "dependencies": { "@babel/types": "^7.24.9", "@jridgewell/gen-mapping": "^0.3.5", @@ -184,7 +137,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -196,7 +148,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", - "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -209,7 +160,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.24.8", "@babel/helper-validator-option": "^7.24.8", @@ -221,29 +171,10 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-environment-visitor": "^7.24.7", @@ -262,20 +193,10 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", @@ -288,20 +209,10 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-define-polyfill-provider": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -313,29 +224,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@babel/helper-environment-visitor": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", @@ -374,7 +262,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", - "dev": true, "dependencies": { "@babel/traverse": "^7.24.8", "@babel/types": "^7.24.8" @@ -399,7 +286,6 @@ "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", @@ -418,7 +304,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", - "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -430,7 +315,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -439,7 +323,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-environment-visitor": "^7.24.7", @@ -456,7 +339,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.7", @@ -473,7 +355,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -486,7 +367,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", - "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -526,7 +406,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -535,7 +414,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", - "dev": true, "dependencies": { "@babel/helper-function-name": "^7.24.7", "@babel/template": "^7.24.7", @@ -550,7 +428,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", - "dev": true, "dependencies": { "@babel/template": "^7.24.7", "@babel/types": "^7.24.8" @@ -573,62 +450,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", @@ -644,7 +465,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -660,7 +480,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -675,7 +494,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -692,7 +510,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -708,7 +525,6 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, "engines": { "node": ">=6.9.0" }, @@ -720,7 +536,6 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -732,7 +547,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -744,7 +558,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -759,7 +572,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -771,7 +583,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -783,7 +594,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -798,7 +608,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -813,7 +622,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -825,7 +633,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -837,7 +644,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -852,7 +658,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -864,7 +669,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -876,7 +680,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -888,7 +691,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -900,7 +702,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -912,7 +713,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -924,7 +724,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -939,7 +738,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -954,7 +752,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -969,7 +766,6 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -985,7 +781,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1000,7 +795,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1018,7 +812,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", - "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1035,7 +828,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1050,7 +842,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1065,7 +856,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1081,7 +871,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1098,7 +887,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-compilation-targets": "^7.24.8", @@ -1120,7 +908,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -1129,7 +916,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/template": "^7.24.7" @@ -1145,7 +931,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1160,7 +945,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1176,7 +960,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1191,7 +974,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1207,7 +989,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", - "dev": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1223,7 +1004,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1239,7 +1019,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1255,7 +1034,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", - "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", "@babel/helper-function-name": "^7.24.7", @@ -1272,7 +1050,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1288,7 +1065,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1303,7 +1079,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -1319,7 +1094,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1334,7 +1108,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1350,7 +1123,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -1367,7 +1139,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", - "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.24.7", "@babel/helper-module-transforms": "^7.24.7", @@ -1385,7 +1156,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", - "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1401,7 +1171,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1417,7 +1186,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1432,7 +1200,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -1448,7 +1215,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -1464,7 +1230,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", - "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1482,7 +1247,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-replace-supers": "^7.24.7" @@ -1498,7 +1262,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -1514,7 +1277,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -1531,7 +1293,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1546,7 +1307,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", - "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1562,7 +1322,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.24.7", @@ -1580,7 +1339,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1595,7 +1353,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1610,7 +1367,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1625,7 +1381,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", @@ -1644,7 +1399,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", - "dev": true, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.24.7" }, @@ -1659,7 +1413,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1675,7 +1428,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" @@ -1691,7 +1443,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1706,7 +1457,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1721,7 +1471,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1737,7 +1486,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1752,7 +1500,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1767,7 +1514,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1782,7 +1528,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", - "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.24.8", @@ -1800,7 +1545,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1815,7 +1559,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1831,7 +1574,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1847,7 +1589,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", - "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1863,7 +1604,6 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.24.8", "@babel/helper-compilation-targets": "^7.24.8", @@ -1954,20 +1694,10 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -1981,7 +1711,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -2001,7 +1730,6 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -2019,8 +1747,7 @@ "node_modules/@babel/regjsgen": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { "version": "7.24.8", @@ -2066,22 +1793,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/@babel/traverse/node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -2090,11 +1801,6 @@ "node": ">=4" } }, - "node_modules/@babel/traverse/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/@babel/types": { "version": "7.24.9", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", @@ -2118,15 +1824,15 @@ } }, "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", @@ -2135,59 +1841,40 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, "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.13.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.0.tgz", + "integrity": "sha512-hPV345J/tH0Cwk2wnU/3PBzORQ9HeX+kQSbwI+jslzpRCHE6fSGTohswksA/Ensr8znPzwfzKZCmAM9Lmlhp7g==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" }, "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" }, "node_modules/@emotion/react": { - "version": "11.11.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", - "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", + "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", "dependencies": { "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { @@ -2200,44 +1887,44 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", - "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", "csstype": "^3.0.2" } }, "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==" }, "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", "peerDependencies": { "react": ">=16.8.0" } }, "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.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==" }, "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + "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==" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", @@ -2264,18 +1951,18 @@ } }, "node_modules/@eslint/compat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", - "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", + "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@eslint/config-array": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.0.tgz", - "integrity": "sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==", + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", "dev": true, "dependencies": { "@eslint/object-schema": "^2.1.4", @@ -2296,23 +1983,6 @@ "concat-map": "0.0.1" } }, - "node_modules/@eslint/config-array/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/@eslint/config-array/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2325,12 +1995,6 @@ "node": "*" } }, - "node_modules/@eslint/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -2364,23 +2028,6 @@ "concat-map": "0.0.1" } }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -2405,16 +2052,10 @@ "node": "*" } }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@eslint/js": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", - "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", + "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2669,9 +2310,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", - "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", + "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==", "engines": { "node": ">=14.0.0" } @@ -2680,7 +2321,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "dev": true, "engines": { "node": ">=14" }, @@ -2696,7 +2336,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "dev": true, "engines": { "node": ">=14" }, @@ -2712,7 +2351,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "dev": true, "engines": { "node": ">=14" }, @@ -2728,7 +2366,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "dev": true, "engines": { "node": ">=14" }, @@ -2744,7 +2381,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "dev": true, "engines": { "node": ">=14" }, @@ -2760,7 +2396,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "dev": true, "engines": { "node": ">=14" }, @@ -2776,7 +2411,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "dev": true, "engines": { "node": ">=14" }, @@ -2792,7 +2426,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "dev": true, "engines": { "node": ">=12" }, @@ -2808,7 +2441,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", - "dev": true, "dependencies": { "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", @@ -2834,7 +2466,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -2854,7 +2485,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dev": true, "dependencies": { "@babel/types": "^7.21.3", "entities": "^4.4.0" @@ -2867,23 +2497,10 @@ "url": "https://github.com/sponsors/gregberge" } }, - "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/@svgr/plugin-jsx": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -2905,7 +2522,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", - "dev": true, "dependencies": { "cosmiconfig": "^8.1.3", "deepmerge": "^4.3.1", @@ -2926,7 +2542,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", - "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@babel/plugin-transform-react-constant-elements": "^7.21.3", @@ -2949,7 +2564,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -3003,9 +2617,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -3088,9 +2702,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.14.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", + "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", "dependencies": { "undici-types": "~5.26.4" } @@ -3192,25 +2806,25 @@ } }, "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", + "version": "8.5.11", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.11.tgz", + "integrity": "sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", + "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/type-utils": "7.17.0", + "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -3233,16 +2847,17 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "node_modules/@typescript-eslint/parser": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", + "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/typescript-estree": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", + "debug": "^4.3.4" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3260,16 +2875,14 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", + "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3277,45 +2890,18 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "node_modules/@typescript-eslint/type-utils": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", + "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4" + "@typescript-eslint/typescript-estree": "7.17.0", + "@typescript-eslint/utils": "7.17.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3333,50 +2919,10 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", + "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3387,13 +2933,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", + "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/visitor-keys": "7.17.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3414,36 +2960,47 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/@typescript-eslint/typescript-estree/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", + "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", "dev": true, "dependencies": { - "ms": "2.1.2" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.17.0", + "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/typescript-estree": "7.17.0" }, "engines": { - "node": ">=6.0" + "node": "^18.18.0 || >=20.0.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", + "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/types": "7.17.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3713,15 +3270,15 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -3764,18 +3321,14 @@ } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dependencies": { - "color-convert": "^2.0.1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4" } }, "node_modules/anymatch": { @@ -3932,18 +3485,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, "node_modules/array.prototype.tosorted": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", @@ -4054,7 +3595,6 @@ "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -4064,20 +3604,10 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/babel-plugin-polyfill-corejs3": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.1", "core-js-compat": "^3.36.1" @@ -4090,7 +3620,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2" }, @@ -4164,11 +3693,26 @@ "node": ">= 0.8" } }, - "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", - "dev": true, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" @@ -4301,7 +3845,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, "engines": { "node": ">=10" }, @@ -4310,9 +3853,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001642", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", - "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "version": "1.0.30001643", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", + "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", "funding": [ { "type": "opencollective", @@ -4329,31 +3872,24 @@ ] }, "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=4" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "engines": { - "node": ">=8" + "node": ">=0.8.0" } }, "node_modules/chokidar": { @@ -4380,6 +3916,18 @@ "fsevents": "~2.3.2" } }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -4400,6 +3948,15 @@ "node": ">= 10.0" } }, + "node_modules/clean-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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -4415,22 +3972,17 @@ } }, "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "color-name": "1.1.3" } }, "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/colorette": { "version": "2.0.20", @@ -4439,9 +3991,13 @@ "dev": true }, "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } }, "node_modules/compressible": { "version": "2.0.18", @@ -4473,6 +4029,21 @@ "node": ">= 0.8.0" } }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/compression/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -4539,7 +4110,6 @@ "version": "3.37.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", - "dev": true, "dependencies": { "browserslist": "^4.23.0" }, @@ -4628,6 +4198,18 @@ } } }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -4648,7 +4230,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -4684,7 +4265,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, "dependencies": { "css-tree": "~2.2.0" }, @@ -4697,7 +4277,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" @@ -4710,8 +4289,7 @@ "node_modules/csso/node_modules/mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" }, "node_modules/csstype": { "version": "3.1.3", @@ -4776,12 +4354,19 @@ } }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/deep-equal": { @@ -4816,12 +4401,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -5006,6 +4585,15 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -5056,11 +4644,15 @@ } }, "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/dotenv-defaults": { @@ -5071,6 +4663,14 @@ "dotenv": "^8.2.0" } }, + "node_modules/dotenv-defaults/node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "engines": { + "node": ">=10" + } + }, "node_modules/dotenv-webpack": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz", @@ -5098,9 +4698,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.827", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", - "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz", + "integrity": "sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -5127,9 +4727,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -5139,10 +4739,12 @@ } }, "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -5268,12 +4870,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/es-iterator-helpers": { "version": "1.0.19", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", @@ -5371,24 +4967,27 @@ "dev": true }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.6.0.tgz", - "integrity": "sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.7.0.tgz", + "integrity": "sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", + "@eslint-community/regexpp": "^4.11.0", "@eslint/config-array": "^0.17.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.6.0", + "@eslint/js": "9.7.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -5397,7 +4996,7 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.1", + "eslint-scope": "^8.0.2", "eslint-visitor-keys": "^4.0.0", "espree": "^10.1.0", "esquery": "^1.5.0", @@ -5449,12 +5048,6 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-import-resolver-node/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 - }, "node_modules/eslint-import-resolver-typescript": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", @@ -5480,29 +5073,6 @@ "eslint-plugin-import": "*" } }, - "node_modules/eslint-import-resolver-typescript/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/eslint-module-utils": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", @@ -5529,12 +5099,6 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-module-utils/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 - }, "node_modules/eslint-plugin-import": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", @@ -5597,21 +5161,6 @@ "node": "*" } }, - "node_modules/eslint-plugin-import/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 - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-jsx-a11y": { "version": "6.9.0", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", @@ -5665,13 +5214,13 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" + "synckit": "^0.9.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -5695,35 +5244,35 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.34.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz", - "integrity": "sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA==", + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", "dev": true, "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", + "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", - "object.hasown": "^1.1.4", "object.values": "^1.2.0", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11" + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "node_modules/eslint-plugin-react-hooks": { @@ -5748,15 +5297,6 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint-plugin-react/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/eslint-plugin-react/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5786,25 +5326,20 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/eslint-scope": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { @@ -5819,6 +5354,21 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5829,51 +5379,40 @@ "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", - "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "color-name": "~1.1.4" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=7.0.0" } }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", @@ -5886,56 +5425,13 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/eslint/node_modules/minimatch": { @@ -5950,40 +5446,16 @@ "node": "*" } }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/espree": { @@ -6027,15 +5499,6 @@ "node": ">=0.10" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", @@ -6047,7 +5510,7 @@ "node": ">=4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { + "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", @@ -6055,14 +5518,6 @@ "node": ">=4.0" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -6159,6 +5614,21 @@ "node": ">= 0.10.0" } }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -6186,6 +5656,18 @@ "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -6275,22 +5757,40 @@ "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" }, "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -6406,6 +5906,21 @@ "webpack": "^5.11.0" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -6416,16 +5931,47 @@ "concat-map": "0.0.1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "fs-monkey": "^1.0.4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { @@ -6440,6 +5986,30 @@ "node": "*" } }, + "node_modules/fork-ts-checker-webpack-plugin/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -6531,7 +6101,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -6617,15 +6186,15 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, "node_modules/glob-to-regexp": { @@ -6705,9 +6274,9 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.3.tgz", - "integrity": "sha512-l/ED7kcE/LAZkuXxEFDU0j5k7Bac+t4dTJIxAAH8Ij9byaxdblzJF4DiRQ10AZ2RfuDzHYuI5MULq+18sU2cXA==", + "version": "0.1.20", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.20.tgz", + "integrity": "sha512-MB4L5lP0eDKhm5hU/XROKNE/H0pj9Zaf/uiLUUhtvOzS6bzHd2guYlE/LI0G2bvA7v65APD1Bzp3KXGi/Z8nNw==", "dependencies": { "@emotion/react": "^11.11.4", "@svgr/webpack": "^8.1.0", @@ -6736,11 +6305,11 @@ } }, "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=8" + "node": ">=4" } }, "node_modules/has-property-descriptors": { @@ -6834,6 +6403,12 @@ "wbuf": "^1.1.0" } }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/hpack.js/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -6900,28 +6475,7 @@ "webpack": "^5.0.0" } }, - "node_modules/html-loader/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/html-loader/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/html-loader/node_modules/html-minifier-terser": { + "node_modules/html-minifier-terser": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", @@ -6942,36 +6496,6 @@ "node": "^14.13.1 || >=16.0.0" } }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, "node_modules/html-webpack-plugin": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", @@ -7004,6 +6528,36 @@ } } }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/htmlparser2": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", @@ -7023,6 +6577,15 @@ "entities": "^2.0.0" } }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/http-deceiver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", @@ -7155,18 +6718,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "dependencies": { "pkg-dir": "^4.2.0", @@ -7334,9 +6889,9 @@ } }, "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", "dependencies": { "hasown": "^2.0.2" }, @@ -7716,9 +7271,9 @@ } }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, "node_modules/isexe": { @@ -7777,6 +7332,28 @@ "node": ">= 10.13.0" } }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7827,15 +7404,14 @@ "dev": true }, "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "bin": { "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/jsonfile": { @@ -7943,37 +7519,28 @@ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/loader-utils-webpack-v4/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": ">=6" + "node": ">=8.9.0" } }, "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -7985,8 +7552,7 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -8014,16 +7580,17 @@ } }, "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "node_modules/media-typer": { "version": "0.3.0", @@ -8035,22 +7602,15 @@ } }, "node_modules/memfs": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", - "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", "dev": true, "dependencies": { - "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.1.2", - "tree-dump": "^1.0.1", - "tslib": "^2.0.0" + "fs-monkey": "^1.0.4" }, "engines": { "node": ">= 4.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" } }, "node_modules/merge-descriptors": { @@ -8241,10 +7801,9 @@ } }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -8322,9 +7881,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -8468,23 +8027,6 @@ "node": ">= 0.4" } }, - "node_modules/object.hasown": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.4.tgz", - "integrity": "sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object.values": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", @@ -8580,30 +8122,33 @@ } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-retry": { @@ -8688,18 +8233,6 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/parse5/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -8758,6 +8291,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -8801,6 +8340,58 @@ "node": ">=8" } }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "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", @@ -9114,11 +8705,11 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-router": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", - "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", + "integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==", "dependencies": { - "@remix-run/router": "1.17.1" + "@remix-run/router": "1.18.0" }, "engines": { "node": ">=14.0.0" @@ -9128,12 +8719,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", - "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", + "version": "6.25.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz", + "integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==", "dependencies": { - "@remix-run/router": "1.17.1", - "react-router": "6.24.1" + "@remix-run/router": "1.18.0", + "react-router": "6.25.1" }, "engines": { "node": ">=14.0.0" @@ -9205,14 +8796,12 @@ "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" }, "node_modules/regenerate-unicode-properties": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dev": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -9229,7 +8818,6 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -9256,7 +8844,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -9273,7 +8860,6 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, "dependencies": { "jsesc": "~0.5.0" }, @@ -9285,7 +8871,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" } @@ -9355,7 +8940,7 @@ "node": ">=8" } }, - "node_modules/resolve-from": { + "node_modules/resolve-cwd/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", @@ -9364,6 +8949,14 @@ "node": ">=8" } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "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", @@ -9463,12 +9056,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -9556,15 +9143,11 @@ } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/send": { @@ -9591,6 +9174,21 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -9623,6 +9221,15 @@ "node": ">= 0.8.0" } }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, "node_modules/serve-index/node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -9653,6 +9260,12 @@ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", "dev": true }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/serve-index/node_modules/setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", @@ -9800,7 +9413,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -9818,9 +9430,9 @@ } }, "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==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "engines": { "node": ">=0.10.0" } @@ -9842,6 +9454,14 @@ "source-map": "^0.6.0" } }, + "node_modules/source-map-support/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==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -9861,63 +9481,17 @@ "node_modules/spdy-transport": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/spdy-transport/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/spdy-transport/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/spdy/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" } }, - "node_modules/spdy/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -10049,6 +9623,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "node_modules/string.prototype.trim": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", @@ -10175,17 +9759,14 @@ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dependencies": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=4" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -10202,14 +9783,12 @@ "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", - "dev": true + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" }, "node_modules/svgo": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", - "dev": true, "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -10234,7 +9813,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, "engines": { "node": ">= 10" } @@ -10243,7 +9821,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dev": true, "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", @@ -10259,7 +9836,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -10273,7 +9849,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, "dependencies": { "domelementtype": "^2.3.0" }, @@ -10288,7 +9863,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dev": true, "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -10298,22 +9872,10 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/svgo/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", "dev": true, "dependencies": { "@pkgr/core": "^0.1.0", @@ -10335,9 +9897,9 @@ } }, "node_modules/terser": { - "version": "5.31.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", - "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", + "version": "5.31.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", + "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -10384,6 +9946,11 @@ } } }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -10485,6 +10052,76 @@ "webpack": "^5.0.0" } }, + "node_modules/ts-loader/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ts-loader/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ts-loader/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ts-loader/node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -10494,6 +10131,18 @@ "node": ">= 8" } }, + "node_modules/ts-loader/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -10506,6 +10155,18 @@ "strip-bom": "^3.0.0" } }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", @@ -10610,9 +10271,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -10623,14 +10284,14 @@ } }, "node_modules/typescript-eslint": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", - "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.17.0.tgz", + "integrity": "sha512-spQxsQvPguduCUfyUvLItvKqK3l8KJ/kqs5Pb/URtzQ5AC53Z6us32St37rpmlt2uESG23lOFpV4UErrmy4dZQ==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "7.16.0", - "@typescript-eslint/parser": "7.16.0", - "@typescript-eslint/utils": "7.16.0" + "@typescript-eslint/eslint-plugin": "7.17.0", + "@typescript-eslint/parser": "7.17.0", + "@typescript-eslint/utils": "7.17.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -10648,28 +10309,6 @@ } } }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -10688,14 +10327,12 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, "engines": { "node": ">=4" } @@ -10704,7 +10341,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -10717,7 +10353,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true, "engines": { "node": ">=4" } @@ -10726,7 +10361,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, "engines": { "node": ">=4" } @@ -10937,19 +10571,10 @@ } } }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, "node_modules/webpack-dev-middleware": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.2.1.tgz", - "integrity": "sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.3.0.tgz", + "integrity": "sha512-xD2qnNew+F6KwOGZR7kWdbIou/ud7cVqLEXeK1q0nHcNsX/u7ul/fSdlOTX4ntSL5FNFy7ZJJXbf0piF591JYw==", "dev": true, "dependencies": { "colorette": "^2.0.10", @@ -10976,15 +10601,15 @@ } }, "node_modules/webpack-dev-middleware/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -11009,6 +10634,25 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, + "node_modules/webpack-dev-middleware/node_modules/memfs": { + "version": "4.9.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", + "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", + "dev": true, + "dependencies": { + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.1.2", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, "node_modules/webpack-dev-middleware/node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -11088,15 +10732,15 @@ } }, "node_modules/webpack-dev-server/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -11162,6 +10806,26 @@ "node": ">=10.13.0" } }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -11242,12 +10906,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/which-collection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", @@ -11335,6 +10993,39 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -11418,8 +11109,7 @@ "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { "version": "1.10.2", @@ -11442,4 +11132,4 @@ } } } -} \ No newline at end of file +} diff --git a/client/package.json b/client/package.json index f25247dc3..8155d4dc9 100644 --- a/client/package.json +++ b/client/package.json @@ -21,6 +21,7 @@ "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "css-loader": "^7.1.2", + "dotenv": "^16.4.5", "eslint": "^9.6.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", @@ -44,9 +45,9 @@ }, "dependencies": { "@emotion/react": "^11.11.4", + "haengdong-design": "^0.1.20", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.3", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/apis/baseUrl.ts b/client/src/apis/baseUrl.ts new file mode 100644 index 000000000..e508ba375 --- /dev/null +++ b/client/src/apis/baseUrl.ts @@ -0,0 +1,3 @@ +export const BASE_URL = { + HD: process.env.API_BASE_URL ?? '', +}; diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts new file mode 100644 index 000000000..31c097276 --- /dev/null +++ b/client/src/apis/request/bill.ts @@ -0,0 +1,19 @@ +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestPost} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; +import {Bill} from 'types/stepList'; + +type RequestAddBillList = { + BillList: Bill[]; +}; + +export const requestAddBillList = async ({eventId, BillList}: WithEventId<RequestAddBillList>) => { + await requestPost({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/actions/bills`, + body: { + actions: BillList, + }, + }); +}; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts new file mode 100644 index 000000000..c941f31d4 --- /dev/null +++ b/client/src/apis/request/event.ts @@ -0,0 +1,17 @@ +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet} from '@apis/fetcher'; +import {StepList} from 'types/stepList'; + +type RequestCreateNewEvent = { + name: string; +}; + +export const requestCreateNewEvent = async ({name}: RequestCreateNewEvent) => { + // TODO: (@weadie) 뼈대만 둔 것. header값을 꺼내오는 로직이 필요하다. 또는 바디에 달라고 부탁할 수 있다. + return await requestGet<StepList>({ + baseUrl: BASE_URL.HD, + endpoint: TEMP_PREFIX, + body: {name}, + }); +}; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts new file mode 100644 index 000000000..af8b6c689 --- /dev/null +++ b/client/src/apis/request/member.ts @@ -0,0 +1,19 @@ +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestPost} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; +import {Member} from 'types/stepList'; + +type RequestUpdateMemberList = { + MemberList: Member[]; +}; + +export const requestUpdateMemberList = async ({eventId, MemberList}: WithEventId<RequestUpdateMemberList>) => { + await requestPost({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/actions/members`, + body: { + actions: MemberList, + }, + }); +}; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts new file mode 100644 index 000000000..cc9b0ad66 --- /dev/null +++ b/client/src/apis/request/report.ts @@ -0,0 +1,18 @@ +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; +import {MemberReport} from 'types/stepList'; + +type ResponseMemberReportList = { + reports: MemberReport[]; +}; + +export const requestMemberReportList = async ({eventId}: WithEventId) => { + const {reports} = await requestGet<ResponseMemberReportList>({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/actions`, + }); + + return reports; +}; diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts new file mode 100644 index 000000000..d696c69aa --- /dev/null +++ b/client/src/apis/request/stepList.ts @@ -0,0 +1,14 @@ +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet, requestPost} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; +import {Bill, Member, StepList} from 'types/stepList'; + +// TODO: (@weadie) 현재 토큰을 어떻게 관리할지.. 계속 사용되는데 +export const requestStepList = async ({eventId}: WithEventId) => { + // TODO: (@weadie) response가 어떻게 오는지 안나와서 data로만 써뒀어요. + return await requestGet<StepList>({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/actions`, + }); +}; diff --git a/client/src/apis/tempPrefix.ts b/client/src/apis/tempPrefix.ts new file mode 100644 index 000000000..949981b73 --- /dev/null +++ b/client/src/apis/tempPrefix.ts @@ -0,0 +1,2 @@ +// TODO: (@weadie) 반복되서 쓰이는 이 api/events가 추후 수정 가능성이 있어서 일단 편집하기 편하게 이 변수를 재사용하도록 했습니다. +export const TEMP_PREFIX = '/api/events'; diff --git a/client/src/apis/withEventId.type.ts b/client/src/apis/withEventId.type.ts new file mode 100644 index 000000000..b88160e3e --- /dev/null +++ b/client/src/apis/withEventId.type.ts @@ -0,0 +1,3 @@ +export type WithEventId<P = unknown> = P & { + eventId: string; +}; diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx new file mode 100644 index 000000000..17a26f9ca --- /dev/null +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -0,0 +1,21 @@ +import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; +import {ExpenseList, Flex, Input} from 'haengdong-design'; +import React, {useState} from 'react'; + +const MemberReportList = () => { + const [name, setName] = useState(''); + const {memberReportSearchList} = useSearchMemberReportList({name, eventId: '므와아아아'}); + + const changeName = ({target}: React.ChangeEvent<HTMLInputElement>) => { + setName(target.value); + }; + + return ( + <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem" padding="1rem 0 0 0"> + <Input inputType="search" value={name} onChange={changeName} /> + <ExpenseList expenseList={memberReportSearchList} /> + </Flex> + ); +}; + +export default MemberReportList; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx new file mode 100644 index 000000000..2ea9c0bc5 --- /dev/null +++ b/client/src/components/StepList/StepList.tsx @@ -0,0 +1,24 @@ +import {useStepList} from '@hooks/useStepList/useStepList'; +import {Flex, InOutItem, StepItem} from 'haengdong-design'; +import {MemberType} from 'types/stepList'; + +const StepList = () => { + const {stepList} = useStepList(); + + // TODO: (@weadie) if else 구문이 지저분하므로 리펙터링이 필요합니다. + return ( + <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem" padding="1rem 0 0 0"> + {stepList.map(step => { + if (step.type === 'BILL') { + return <StepItem name={step.stepName} bills={step.actions} personCount={0} />; + } else if (step.type === 'IN' || step.type === 'OUT') { + return <InOutItem inOutType={step.type} names={step.actions.map(({name}) => name)} />; + } else { + return <></>; + } + })} + </Flex> + ); +}; + +export default StepList; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index eb4f6938b..f0a910d5b 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -4,4 +4,5 @@ export const ROUTER_URLS = { eventCreateComplete: '/event/create/complete', event: '/event', eventManage: '/event/:eventId', + home: '/event/:eventId/home', }; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx new file mode 100644 index 000000000..bdd1e3cf2 --- /dev/null +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -0,0 +1,42 @@ +import {useEffect, useState} from 'react'; +import {MemberReport} from 'types/stepList'; +import memberReportSearchJsonList from '@mocks/memberReportSearchList.json'; +import {requestMemberReportList} from '@apis/request/report'; +import {WithEventId} from '@apis/withEventId.type'; + +const memberReportSearchMockList = memberReportSearchJsonList as MemberReport[]; + +type UseSearchMemberReportListParams = { + name: string; +}; + +const useSearchMemberReportList = ({name, eventId}: WithEventId<UseSearchMemberReportListParams>) => { + const [memberReportList, setMemberReportList] = useState<MemberReport[]>(memberReportSearchMockList); + const [memberReportSearchList, setMemberReportSearchList] = useState<MemberReport[]>([]); + + useEffect(() => { + const fetchMemberReportList = async () => { + // TODO: (@weadie) cors 고쳐지면 주석 풀게요. + // const memberReportListData = await requestMemberReportList({eventId}); + + const memberReportListData = memberReportSearchMockList; + + setMemberReportList(memberReportListData); + }; + + fetchMemberReportList(); + }, []); + + // TODO: (@weadie) 글자가 완성될 때마다 아래 로직이 실행되어야 합니다. + useEffect(() => { + if (name === '') setMemberReportSearchList(memberReportList); + + setMemberReportSearchList(memberReportList.filter(memberReport => memberReport.name.includes(name))); + }, [name]); + + return { + memberReportSearchList, + }; +}; + +export default useSearchMemberReportList; diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx new file mode 100644 index 000000000..842794f0f --- /dev/null +++ b/client/src/hooks/useStepList/useStepList.tsx @@ -0,0 +1,47 @@ +import {PropsWithChildren, createContext, useEffect, useState} from 'react'; +import {BillAction, MemberType, StepList} from 'types/stepList'; +import stepListJsonData from '@mocks/stepList.json'; + +const stepListMockData = stepListJsonData as StepList; + +const useStepList = () => { + const [stepList, setStepList] = useState<StepList>(stepListMockData); + + useEffect(() => { + // TODO: (@weadie) useEffect를 꼭 써야하는가? + // 초기 리스트 불러서 setActionList + }, []); + + const updateMemberList = (type: MemberType, memberList: string[]) => { + // api를 호출하고 set한다 + }; + + const addBill = (title: string, price: number) => { + // api를 호출하고 set한다. + }; + + const calculateBillSum = (actions: BillAction[]) => { + return actions.reduce((sum, {price}) => sum + price, 0); + }; + + const getTotalPrice = () => { + return stepList.reduce((sum, {type, actions}) => { + if (type === 'BILL') { + return sum + calculateBillSum(actions); + } + return sum; + }, 0); + }; + + return {stepList, getTotalPrice}; +}; + +const StepListContext = createContext<StepList>([]); // TODO: (@weadie) 인자를 어떻게 줘야 하는지 고민하기. + +const StepListProvider = ({children}: PropsWithChildren) => { + const {stepList} = useStepList(); + + return <StepListContext.Provider value={stepList}>{children}</StepListContext.Provider>; +}; + +export {useStepList, StepListProvider}; diff --git a/client/src/mocks/memberReportSearchList.json b/client/src/mocks/memberReportSearchList.json new file mode 100644 index 000000000..dfcb684b1 --- /dev/null +++ b/client/src/mocks/memberReportSearchList.json @@ -0,0 +1,10 @@ +[ + {"name": "망쵸", "price": 1033200}, + {"name": "이상", "price": 10100}, + {"name": "소하", "price": 10000}, + {"name": "쿠키", "price": 100012}, + {"name": "토다리", "price": 1001230}, + {"name": "감자", "price": 1012300}, + {"name": "백호", "price": 10300}, + {"name": "웨디", "price": 1000} +] diff --git a/client/src/mocks/stepList.json b/client/src/mocks/stepList.json new file mode 100644 index 000000000..cc3815a75 --- /dev/null +++ b/client/src/mocks/stepList.json @@ -0,0 +1,86 @@ +[ + { + "type": "IN", + "stepName": null, + "actions": [ + { + "actionId": 3, + "name": "망쵸", + "price": null, + "sequence": 3 + }, + { + "actionId": 4, + "name": "백호", + "price": null, + "sequence": 4 + } + ] + }, + { + "type": "BILL", + "stepName": "1차", + "actions": [ + { + "actionId": 1, + "name": "감자탕", + "price": 10000, + "sequence": 1 + }, + { + "actionId": 2, + "name": "인생네컷", + "price": 10000, + "sequence": 2 + } + ] + }, + { + "type": "IN", + "stepName": null, + "actions": [ + { + "actionId": 3, + "name": "망쵸", + "price": null, + "sequence": 3 + }, + { + "actionId": 4, + "name": "백호", + "price": null, + "sequence": 4 + } + ] + }, + { + "type": "OUT", + "stepName": null, + "actions": [ + { + "actionId": 5, + "name": "소하", + "price": null, + "sequence": 5 + }, + { + "actionId": 6, + "name": "웨디", + "price": null, + "sequence": 6 + } + ] + }, + { + "type": "BILL", + "stepName": "2차", + "actions": [ + { + "actionId": 8, + "name": "노래방", + "price": 20000, + "sequence": 7 + } + ] + } +] diff --git a/client/src/pages/CreateEvent/CreateEvent.tsx b/client/src/pages/CreateEvent/CreateEvent.tsx new file mode 100644 index 000000000..eb25c1faf --- /dev/null +++ b/client/src/pages/CreateEvent/CreateEvent.tsx @@ -0,0 +1,26 @@ +import {useState} from 'react'; +import {useNavigate} from 'react-router-dom'; +import {ROUTER_URLS} from '@constants/routerUrls'; + +const CreateEvent = () => { + const [eventTitle, setEventTitle] = useState(''); + const navigate = useNavigate(); + + const submitEventTitle = (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + navigate(`${ROUTER_URLS.eventCreateName}?${new URLSearchParams({title: eventTitle})}`); + }; + + return ( + <section> + <h1>행사 생성하기</h1> + <h3>시작할 행사 이름을 입력해 주세요.</h3> + <form onSubmit={submitEventTitle}> + <input value={eventTitle} onChange={event => setEventTitle(event.target.value)} /> + <button>행동 개시!</button> + </form> + </section> + ); +}; + +export default CreateEvent; diff --git a/client/src/pages/Home/HomeContent.tsx b/client/src/pages/Home/HomeContent.tsx new file mode 100644 index 000000000..c13829222 --- /dev/null +++ b/client/src/pages/Home/HomeContent.tsx @@ -0,0 +1,20 @@ +import MemberReportList from '@components/MemberReportList/MemberReportList'; +import StepList from '@components/StepList/StepList'; +import {useStepList} from '@hooks/useStepList/useStepList'; +import {Tab, Tabs, Title} from 'haengdong-design'; + +const HomeContent = () => { + const {getTotalPrice} = useStepList(); + + return ( + <div> + <Title title="행동대장 야유회" price={getTotalPrice()} /> + <Tabs> + <Tab label="전체 지출 내역" content={<StepList />} /> + <Tab label="참여자 별 내역" content={<MemberReportList />} /> + </Tabs> + </div> + ); +}; + +export default HomeContent; diff --git a/client/src/pages/Home/HomeLayout.tsx b/client/src/pages/Home/HomeLayout.tsx new file mode 100644 index 000000000..c204f3da1 --- /dev/null +++ b/client/src/pages/Home/HomeLayout.tsx @@ -0,0 +1,19 @@ +import {Flex, MainLayout, TopNav} from 'haengdong-design'; +import {StepListProvider} from '@hooks/useStepList/useStepList'; + +import HomeContent from './HomeContent'; + +const HomeLayout = () => { + return ( + <StepListProvider> + <MainLayout backgroundColor="gray"> + <TopNav navType="home" /> + <Flex flexDirection="column" gap="1rem"> + <HomeContent /> + </Flex> + </MainLayout> + </StepListProvider> + ); +}; + +export default HomeLayout; diff --git a/client/src/pages/Home/index.ts b/client/src/pages/Home/index.ts new file mode 100644 index 000000000..fde362f5c --- /dev/null +++ b/client/src/pages/Home/index.ts @@ -0,0 +1 @@ +export {default as HomePage} from './HomeLayout'; diff --git a/client/src/router.tsx b/client/src/router.tsx index b6883623b..a84ea18e5 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -3,6 +3,7 @@ import {createBrowserRouter} from 'react-router-dom'; import {MainPage} from '@pages/Main'; import {CreateNamePage, CreateCompletePage} from '@pages/Create'; import {EventPage} from '@pages/Event'; +import {HomePage} from '@pages/Home'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -30,6 +31,10 @@ const router = createBrowserRouter([ path: ROUTER_URLS.eventManage, element: <EventPage />, }, + { + path: ROUTER_URLS.home, + element: <HomePage />, + }, ], }, ]); diff --git a/client/src/types/stepList.ts b/client/src/types/stepList.ts new file mode 100644 index 000000000..f106306e9 --- /dev/null +++ b/client/src/types/stepList.ts @@ -0,0 +1,52 @@ +export type MemberType = 'IN' | 'OUT'; + +// TODO: (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. +export type StepList = (MemberStep | BillStep)[]; + +export type Step = { + type: MemberType | 'BILL'; + stepName: string | null; + actions: (BillAction | MemberAction)[]; +}; + +export type MemberStep = Omit<Step, 'type' | 'stepName' | 'actions'> & { + type: MemberType; + stepName: null; + actions: MemberAction[]; +}; + +export type BillStep = Omit<Step, 'type' | 'stepName' | 'actions'> & { + type: 'BILL'; + stepName: string; + actions: BillAction[]; +}; + +export type Action = { + actionId: number; + name: string; + price: number | null; + sequence?: number; +}; + +export type BillAction = Omit<Action, 'price'> & { + price: number; +}; + +export type MemberAction = Omit<Action, 'price'> & { + price: null; +}; + +export type Member = { + name: string; + status: MemberType; +}; + +export type Bill = { + title: string; + price: number; +}; + +export type MemberReport = { + name: string; + price: number; +}; diff --git a/client/webpack.config.js b/client/webpack.config.js index b729f1020..9545ecf2f 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -8,6 +8,8 @@ import Dotenv from 'dotenv-webpack'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +// dotenv.config({path: path.join(__dirname, '.env')}); + export default { mode: 'development', entry: './src/index.tsx', From fc4138c3a43987ea1a525979e3026c7035e74cb0 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:01:23 +0900 Subject: [PATCH 075/273] =?UTF-8?q?feat:=20=ED=98=84=EC=9E=AC=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20=EA=B2=80=EC=83=89=20component=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20(#78)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- HDesign/package-lock.json | 4 +- HDesign/package.json | 2 +- HDesign/src/components/Input/Input.style.ts | 2 +- .../src/components/Search/Search.stories.tsx | 34 +++++++++++++++ HDesign/src/components/Search/Search.style.ts | 39 +++++++++++++++++ HDesign/src/components/Search/Search.tsx | 42 +++++++++++++++++++ HDesign/src/components/Search/useSearch.ts | 39 +++++++++++++++++ HDesign/src/components/Title/Title.style.ts | 1 + HDesign/src/components/TopNav/TopNav.style.ts | 1 + HDesign/src/index.tsx | 19 +++++++++ HDesign/src/layouts/MainLayout.tsx | 12 ++++++ HDesign/tsconfig.json | 1 + 12 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 HDesign/src/components/Search/Search.stories.tsx create mode 100644 HDesign/src/components/Search/Search.style.ts create mode 100644 HDesign/src/components/Search/Search.tsx create mode 100644 HDesign/src/components/Search/useSearch.ts create mode 100644 HDesign/src/layouts/MainLayout.tsx diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 905b380c5..9a18cd5ff 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.0", + "version": "0.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.0", + "version": "0.1.3", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index c7dbfca71..42f857a3e 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.0", + "version": "0.1.3", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts index f45b02ea2..be05abb5b 100644 --- a/HDesign/src/components/Input/Input.style.ts +++ b/HDesign/src/components/Input/Input.style.ts @@ -19,8 +19,8 @@ const inputBoxBackgroundColorByInputType = (theme: Theme, inputType: InputType = export const inputBoxStyle = (theme: Theme, inputType: InputType = 'input') => css({ display: 'flex', - width: '100%', justifyContent: 'space-between', + marginInline: '1rem', padding: '0.75rem 1rem', borderRadius: '1rem', backgroundColor: inputBoxBackgroundColorByInputType(theme, inputType), diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx new file mode 100644 index 000000000..40f7df4b1 --- /dev/null +++ b/HDesign/src/components/Search/Search.stories.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import type {Meta, StoryObj} from '@storybook/react'; + +import Search from '@components/Search/Search'; + +const meta = { + title: 'Components/Search', + component: Search, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + value: { + description: '', + control: {type: 'text'}, + }, + inputType: { + control: {type: 'radio'}, + }, + }, + args: { + disabled: false, + placeholder: 'placeholder', + searchTerms: ['todari', 'cookie'], + setKeyword: keyword => console.log(keyword), + }, +} satisfies Meta<typeof Search>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Search/Search.style.ts b/HDesign/src/components/Search/Search.style.ts new file mode 100644 index 000000000..413655bd5 --- /dev/null +++ b/HDesign/src/components/Search/Search.style.ts @@ -0,0 +1,39 @@ +import {Theme} from '@/theme/theme.type'; +import {css} from '@emotion/react'; + +export const searchStyle = css({ + position: 'relative', + + width: '100%', +}); + +export const searchTermsStyle = (theme: Theme) => + css({ + position: 'absolute', + top: '3.5rem', + + width: 'calc(100% - 2rem)', + margin: '0 1rem', + padding: '0.5rem 0', + + borderRadius: '1rem', + + backgroundColor: theme.colors.white, + }); + +export const searchTermStyle = (theme: Theme) => + css( + { + width: '100%', + padding: '0.5rem 1rem', + + color: theme.colors.onTertiary, + + '&:hover': { + borderRadius: '0.5rem', + + backgroundColor: theme.colors.lightGrayContainer, + }, + }, + theme.typography.body, + ); diff --git a/HDesign/src/components/Search/Search.tsx b/HDesign/src/components/Search/Search.tsx new file mode 100644 index 000000000..68fc02209 --- /dev/null +++ b/HDesign/src/components/Search/Search.tsx @@ -0,0 +1,42 @@ +/** @jsxImportSource @emotion/react */ +import Input from '../Input/Input'; +import {InputProps} from '../Input/Input.type'; +import {searchStyle, searchTermsStyle} from './Search.style'; +import useSearch from './useSearch'; +import {searchTermStyle} from './Search.style'; +import {useTheme} from '@theme/HDesignProvider'; +import Flex from '@components/Flex/Flex'; + +export interface SearchProps extends InputProps { + searchTerms: string[]; + setState: React.Dispatch<React.SetStateAction<string>>; +} + +const Search: React.FC<SearchProps> = ({searchTerms, setState, ...inputProps}: SearchProps) => { + const {theme} = useTheme(); + const {value, showSearchTerms, handleOnChange, handleOnClick, filterSearchTerms} = useSearch({ + searchTerms, + setState, + }); + + return ( + <fieldset css={searchStyle}> + <Input inputType="search" value={value} onChange={handleOnChange} {...inputProps} /> + {showSearchTerms && ( + <ul css={searchTermsStyle(theme)}> + <Flex flexDirection="column" gap="0.5rem"> + {filterSearchTerms(value).map((searchTerm, index) => ( + <li key={`${searchTerm}-${index}`}> + <button type="button" css={searchTermStyle(theme)} onClick={() => handleOnClick(searchTerm)}> + {searchTerm} + </button> + </li> + ))} + </Flex> + </ul> + )} + </fieldset> + ); +}; + +export default Search; diff --git a/HDesign/src/components/Search/useSearch.ts b/HDesign/src/components/Search/useSearch.ts new file mode 100644 index 000000000..fbb9cf4c3 --- /dev/null +++ b/HDesign/src/components/Search/useSearch.ts @@ -0,0 +1,39 @@ +import {useState} from 'react'; + +interface UseSearchProps { + searchTerms: string[]; + setState: React.Dispatch<React.SetStateAction<string>>; +} + +const useSearch = ({searchTerms, setState}: UseSearchProps) => { + const [value, setValue] = useState(''); + const [showSearchTerms, setShowSearchTerms] = useState(false); + + const handleOnClick = (searchTerm: string) => { + setValue(searchTerm); + setState(searchTerm); + setShowSearchTerms(false); + }; + + const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const {value} = event.target; + setValue(value); + setShowSearchTerms(value.trim() !== '' && filterSearchTerms(value).length !== 0); + }; + + const filterSearchTerms = (keyword: string) => { + if (keyword.trim() === '') return []; + + return searchTerms.filter(terms => terms.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1); + }; + + return { + value, + showSearchTerms, + handleOnClick, + handleOnChange, + filterSearchTerms, + }; +}; + +export default useSearch; diff --git a/HDesign/src/components/Title/Title.style.ts b/HDesign/src/components/Title/Title.style.ts index ca0a02fc3..700128c02 100644 --- a/HDesign/src/components/Title/Title.style.ts +++ b/HDesign/src/components/Title/Title.style.ts @@ -6,6 +6,7 @@ export const titleContainerStyle = (theme: Theme) => css({ display: 'flex', flexDirection: 'column', + width: '100%', gap: '0.5rem', backgroundColor: theme.colors.white, padding: '1rem', diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/HDesign/src/components/TopNav/TopNav.style.ts index cd4244eb3..88910da47 100644 --- a/HDesign/src/components/TopNav/TopNav.style.ts +++ b/HDesign/src/components/TopNav/TopNav.style.ts @@ -3,4 +3,5 @@ import {css} from '@emotion/react'; export const topNavStyle = css({ display: 'flex', padding: '0 1rem', + width: '100%', }); diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index 8c010bca0..7f941ad5f 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -1,13 +1,23 @@ import BillItem from '@components/BillItem/BillItem'; import BottomSheet from '@components/BottomSheet/BottomSheet'; import Button from '@components/Button/Button'; +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import ExpenseList from '@components/ExpenseList/ExpenseList'; import FixedButton from '@components/FixedButton/FixedButton'; +import Flex from '@components/Flex/Flex'; import IconButton from '@components/IconButton/IconButton'; import InOutItem from '@components/InOutItem/InOutItem'; import Input from '@components/Input/Input'; +import Search from '@components/Search/Search'; import StepItem from '@components/StepItem/StepItem'; +import Switch from '@components/Switch/Switch'; +import Tab from '@components/Tab/Tab'; import Text from '@components/Text/Text'; +import TextButton from '@components/TextButton/TextButton'; import Title from '@components/Title/Title'; +import TopNav from '@components/TopNav/TopNav'; + +import {MainLayout} from '@layouts/MainLayout'; import {HDesignProvider} from '@theme/HDesignProvider'; @@ -15,12 +25,21 @@ export { BillItem, BottomSheet, Button, + DragHandleItem, + ExpenseList, FixedButton, + Flex, IconButton, InOutItem, Input, + Search, StepItem, + Switch, + Tab, Text, + TextButton, Title, + TopNav, + MainLayout, HDesignProvider, }; diff --git a/HDesign/src/layouts/MainLayout.tsx b/HDesign/src/layouts/MainLayout.tsx new file mode 100644 index 000000000..825aca175 --- /dev/null +++ b/HDesign/src/layouts/MainLayout.tsx @@ -0,0 +1,12 @@ +import {PropsWithChildren} from 'react'; +import {Flex} from '..'; + +interface MainLayoutInterface extends PropsWithChildren {} + +export const MainLayout = ({children}: MainLayoutInterface) => { + return ( + <Flex justifyContent="flexStart" flexDirection="column" margin="1rem 0 0 0" gap="1rem" width="100%" height="100%"> + {children} + </Flex> + ); +}; diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json index 6cbcf91bd..371b40efe 100644 --- a/HDesign/tsconfig.json +++ b/HDesign/tsconfig.json @@ -18,6 +18,7 @@ "paths": { "@/*": ["src/*"], "@components/*": ["src/components/*"], + "@layouts/*": ["src/layouts/*"], "@token/*": ["src/token/*"], "@theme/*": ["src/theme/*"], "@assets/*": ["src/assets/*"] From 20519e755a4d63db2c00b2780a0ecea751196e4c Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:04:41 +0900 Subject: [PATCH 076/273] =?UTF-8?q?feat:=20CORS=20=EC=84=A4=EC=A0=95=20(#9?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> --- .../server/haengdong/config/WebConfig.java | 27 +++++++++++++++++++ server/src/main/resources/application.yml | 4 +++ server/src/test/resources/application.yml | 3 +++ 3 files changed, 34 insertions(+) create mode 100644 server/src/main/java/server/haengdong/config/WebConfig.java diff --git a/server/src/main/java/server/haengdong/config/WebConfig.java b/server/src/main/java/server/haengdong/config/WebConfig.java new file mode 100644 index 000000000..129d8b790 --- /dev/null +++ b/server/src/main/java/server/haengdong/config/WebConfig.java @@ -0,0 +1,27 @@ +package server.haengdong.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@RequiredArgsConstructor +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Value("${cors.max-age}") + private Long maxAge; + + @Value("${cors.allowed-origins}") + private String[] allowedOrigins; + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins(allowedOrigins) + .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") + .allowedHeaders("*") + .maxAge(maxAge); + } +} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index aca841de8..e1bdd7f79 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -14,6 +14,10 @@ spring: format_sql: true show-sql: true +cors: + max-age: 3600 + allowed-origins: http://localhost:3000, https://haengdong.pro, https://dev.haengdong.pro, https://app.haengdong.pro + --- spring: diff --git a/server/src/test/resources/application.yml b/server/src/test/resources/application.yml index 49c481eaa..2d02b2712 100644 --- a/server/src/test/resources/application.yml +++ b/server/src/test/resources/application.yml @@ -13,3 +13,6 @@ spring: format_sql: true hibernate: ddl-auto: create-drop +cors: + max-age: 3600 + allowed-origins: http://localhost:8080 From cf90b45a68c3167b68e3031363a345c01680db54 Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:06:13 +0900 Subject: [PATCH 077/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?(#92)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 --- ...ication.java => HaengdongApplication.java} | 4 +- .../application/BillActionService.java | 4 +- .../haengdong/application/EventService.java | 5 ++- .../application/MemberActionFactory.java | 6 ++- .../haengdong/exception/ErrorResponse.java | 10 +++++ .../exception/GlobalExceptionHandler.java | 43 +++++++++++++++++++ .../exception/HaengdongErrorCode.java | 24 +++++++++++ .../exception/HaengdongException.java | 32 ++++++++++++++ .../application/BillActionServiceTest.java | 4 +- .../application/MemberActionFactoryTest.java | 13 +++--- 10 files changed, 131 insertions(+), 14 deletions(-) rename server/src/main/java/server/haengdong/{ServerApplication.java => HaengdongApplication.java} (69%) create mode 100644 server/src/main/java/server/haengdong/exception/ErrorResponse.java create mode 100644 server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java create mode 100644 server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java create mode 100644 server/src/main/java/server/haengdong/exception/HaengdongException.java diff --git a/server/src/main/java/server/haengdong/ServerApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java similarity index 69% rename from server/src/main/java/server/haengdong/ServerApplication.java rename to server/src/main/java/server/haengdong/HaengdongApplication.java index 784978356..31b6e46e7 100644 --- a/server/src/main/java/server/haengdong/ServerApplication.java +++ b/server/src/main/java/server/haengdong/HaengdongApplication.java @@ -4,10 +4,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class ServerApplication { +public class HaengdongApplication { public static void main(String[] args) { - SpringApplication.run(ServerApplication.class, args); + SpringApplication.run(HaengdongApplication.class, args); } } diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java index 272eee7e8..257d33a3e 100644 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -11,6 +11,8 @@ import server.haengdong.domain.action.ActionRepository; import server.haengdong.domain.action.BillActionRepository; import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; @RequiredArgsConstructor @Transactional(readOnly = true) @@ -24,7 +26,7 @@ public class BillActionService { @Transactional public void saveAllBillAction(String eventToken, List<BillActionAppRequest> requests) { Event event = eventRepository.findByToken(eventToken) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 이벤트 토큰입니다.")); + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); Action action = createStartAction(event); for (BillActionAppRequest request : requests) { diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index ea4384148..dee023fbc 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -8,6 +8,8 @@ import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; import server.haengdong.domain.event.EventTokenProvider; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; @RequiredArgsConstructor @Service @@ -25,7 +27,8 @@ public EventAppResponse saveEvent(EventAppRequest request) { } public EventDetailAppResponse findEvent(String token) { - Event event = eventRepository.findByToken(token).orElseThrow(() -> new IllegalArgumentException("")); + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); return EventDetailAppResponse.of(event); } diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java index 46fd9ed1a..cbe34f0ef 100644 --- a/server/src/main/java/server/haengdong/application/MemberActionFactory.java +++ b/server/src/main/java/server/haengdong/application/MemberActionFactory.java @@ -11,6 +11,8 @@ import server.haengdong.domain.action.MemberAction; import server.haengdong.domain.action.MemberActionStatus; import server.haengdong.domain.action.MemberGroupIdProvider; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; @RequiredArgsConstructor @Component @@ -45,7 +47,7 @@ private void validateMemberNames(MemberActionsSaveAppRequest request) { long uniqueCount = memberNames.stream().distinct().count(); if (uniqueCount != memberNames.size()) { - throw new IllegalArgumentException(); + throw new HaengdongException(HaengdongErrorCode.DUPLICATED_MEMBER_ACTION); } } @@ -62,7 +64,7 @@ private void validateActions(MemberActionsSaveAppRequest request, List<MemberAct private void validateAction(MemberActionSaveAppRequest request, List<MemberAction> memberActions) { MemberActionStatus memberActionStatus = MemberActionStatus.of(request.status()); if (isInvalidStatus(memberActions, request.name(), memberActionStatus)) { - throw new IllegalArgumentException(); + throw new HaengdongException(HaengdongErrorCode.INVALID_MEMBER_ACTION); } } diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java new file mode 100644 index 000000000..5d1e33c9b --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/ErrorResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.exception; + +public record ErrorResponse( + String message +) { + + public static ErrorResponse of(HaengdongErrorCode errorCode) { + return new ErrorResponse(errorCode.getMessage()); + } +} diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java new file mode 100644 index 000000000..7985721cd --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java @@ -0,0 +1,43 @@ +package server.haengdong.exception; + +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ResponseEntity<ErrorResponse> haengdongException() { + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.BAD_REQUEST)); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + String errorMessage = e.getFieldErrors().stream() + .map(error -> error.getField() + " " + error.getDefaultMessage()) + .collect(Collectors.joining(", ")); + + return ResponseEntity.badRequest() + .body(new ErrorResponse(errorMessage)); + } + + @ExceptionHandler(HaengdongException.class) + public ResponseEntity<ErrorResponse> haengdongException(HaengdongException e) { + return ResponseEntity.status(e.getStatusCode()) + .body(ErrorResponse.of(e.getErrorCode())); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity<ErrorResponse> handleException(Exception e) { + log.error(e.getMessage(), e); + return ResponseEntity.internalServerError() + .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR)); + } +} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java new file mode 100644 index 000000000..792baa838 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java @@ -0,0 +1,24 @@ +package server.haengdong.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public enum HaengdongErrorCode { + BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."), + DUPLICATED_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "올바르지 않은 인원 요청입니다."), + INVALID_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "잘못된 맴버 액션입니다."), + + NOT_FOUND_EVENT(HttpStatus.NOT_FOUND, "존재하지 않는 행사입니다."), + + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 내부에서 에러가 발생했습니다."), + ; + + private final HttpStatus httpStatus; + private final String message; + + HaengdongErrorCode(HttpStatus httpStatus, String message) { + this.httpStatus = httpStatus; + this.message = message; + } +} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongException.java b/server/src/main/java/server/haengdong/exception/HaengdongException.java new file mode 100644 index 000000000..812df50f8 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/HaengdongException.java @@ -0,0 +1,32 @@ +package server.haengdong.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatusCode; + +@Getter +public class HaengdongException extends RuntimeException { + + private final HaengdongErrorCode errorCode; + private final String message; + + public HaengdongException(HaengdongErrorCode errorCode) { + this(errorCode, null); + } + + public HaengdongException(HaengdongErrorCode errorCode, String message) { + this.errorCode = errorCode; + this.message = message; + } + + public HttpStatusCode getStatusCode() { + return errorCode.getHttpStatus(); + } + + @Override + public String getMessage() { + if (message == null) { + return errorCode.getMessage(); + } + return message; + } +} diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java index 178e850e3..195d4bdd9 100644 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -14,6 +14,7 @@ import server.haengdong.domain.event.Event; import server.haengdong.domain.action.BillActionRepository; import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; @SpringBootTest class BillActionServiceTest { @@ -59,7 +60,6 @@ void saveAllBillAction1() { ); assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("존재하지 않는 이벤트 토큰입니다."); + .isInstanceOf(HaengdongException.class); } } diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java index b8251a307..40bee2ff6 100644 --- a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java +++ b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java @@ -20,6 +20,7 @@ import server.haengdong.domain.action.ActionRepository; import server.haengdong.domain.event.EventRepository; import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.exception.HaengdongException; @SpringBootTest class MemberActionFactoryTest { @@ -59,7 +60,7 @@ void createMemberActionsTest() { Action startAction = new Action(event, 3L); assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, unorderedMemberActions, startAction)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(HaengdongException.class); } @DisplayName("인원 변동 액션을 생성한다.") @@ -147,7 +148,7 @@ void createMemberActionTest5() { Action startAction = new Action(event, 2L); assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(HaengdongException.class); } @DisplayName("행사에 이미 참여 중인 경우 다시 입장할 수 없다.") @@ -163,7 +164,7 @@ void createMemberActionTest6() { Action startAction = new Action(event, 2L); assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(HaengdongException.class); } @DisplayName("한 명의 사용자는 동시에 여러 번 입장할 수 없다.") @@ -177,7 +178,7 @@ void createMemberActionTest7() { Action startAction = new Action(event, 1L); assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(HaengdongException.class); } @DisplayName("한 명의 사용자는 동시에 여러 번 퇴장할 수 없다.") @@ -194,7 +195,7 @@ void createMemberActionTest8() { Action startAction = new Action(event, 2L); assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(HaengdongException.class); } @DisplayName("한 명의 사용자는 입장과 퇴장을 동시에 할 수 없다.") @@ -211,6 +212,6 @@ void createMemberActionTest9() { Action startAction = new Action(event, 2L); assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(HaengdongException.class); } } From a6e9ea2ef4e1a59a97c318d078530771a6f538c7 Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:26:27 +0900 Subject: [PATCH 078/273] =?UTF-8?q?feat:=20=EC=B0=B8=EC=97=AC=EC=9E=90?= =?UTF-8?q?=EB=B3=84=20=EC=A0=95=EC=82=B0=20=ED=98=84=ED=99=A9=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20(#77)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../haengdong/application/ActionService.java | 38 +++++++++ .../response/MemberBillReportAppResponse.java | 4 + .../haengdong/domain/action/BillAction.java | 7 +- .../haengdong/domain/action/MemberAction.java | 7 +- .../domain/action/MemberBillReports.java | 83 +++++++++++++++++++ .../presentation/ActionController.java | 26 ++++++ .../response/MemberBillReportResponse.java | 10 +++ .../response/MemberBillReportsResponse.java | 15 ++++ .../application/ActionServiceTest.java | 68 +++++++++++++++ .../domain/action/MemberBillReportsTest.java | 43 ++++++++++ .../presentation/ActionControllerTest.java | 49 +++++++++++ 11 files changed, 348 insertions(+), 2 deletions(-) create mode 100644 server/src/main/java/server/haengdong/application/ActionService.java create mode 100644 server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberBillReports.java create mode 100644 server/src/main/java/server/haengdong/presentation/ActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java create mode 100644 server/src/test/java/server/haengdong/application/ActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/domain/action/MemberBillReportsTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/ActionControllerTest.java diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java new file mode 100644 index 000000000..22ca43a6b --- /dev/null +++ b/server/src/main/java/server/haengdong/application/ActionService.java @@ -0,0 +1,38 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberBillReports; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; + +@RequiredArgsConstructor +@Service +public class ActionService { + + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + private final EventRepository eventRepository; + + public List<MemberBillReportAppResponse> getMemberBillReports(String token) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new IllegalArgumentException("event not found")); + List<BillAction> billActions = billActionRepository.findByAction_Event(event); + List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); + + MemberBillReports memberBillReports = MemberBillReports.createByActions(billActions, memberActions); + + List<MemberBillReportAppResponse> memberBillReportResponses = new ArrayList<>(); + memberBillReports.getReports().forEach( + (member, price) -> memberBillReportResponses.add(new MemberBillReportAppResponse(member, price)) + ); + return memberBillReportResponses; + } +} diff --git a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java new file mode 100644 index 000000000..21b6cef56 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java @@ -0,0 +1,4 @@ +package server.haengdong.application.response; + +public record MemberBillReportAppResponse(String name, Long price) { +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java index 503715fa1..f0e82c409 100644 --- a/server/src/main/java/server/haengdong/domain/action/BillAction.java +++ b/server/src/main/java/server/haengdong/domain/action/BillAction.java @@ -15,7 +15,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity -public class BillAction { +public class BillAction implements Comparable<BillAction> { private static final int MIN_TITLE_LENGTH = 2; private static final int MAX_TITLE_LENGTH = 30; @@ -58,4 +58,9 @@ private void validatePrice(Long price) { public Long getSequence() { return action.getSequence(); } + + @Override + public int compareTo(BillAction o) { + return Long.compare(this.getSequence(), o.getSequence()); + } } diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java index 6e5f0d805..af340de3f 100644 --- a/server/src/main/java/server/haengdong/domain/action/MemberAction.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberAction.java @@ -16,7 +16,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity -public class MemberAction { +public class MemberAction implements Comparable<MemberAction> { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -50,4 +50,9 @@ public boolean isSameStatus(MemberActionStatus memberActionStatus) { public Long getSequence() { return action.getSequence(); } + + @Override + public int compareTo(MemberAction o) { + return Long.compare(this.getSequence(), o.getSequence()); + } } diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReports.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReports.java new file mode 100644 index 000000000..aa928d2e4 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberBillReports.java @@ -0,0 +1,83 @@ +package server.haengdong.domain.action; + +import static java.util.stream.Collectors.toMap; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.Set; +import java.util.function.Function; +import lombok.Getter; + +@Getter +public class MemberBillReports { + + private final Map<String, Long> reports; + + private MemberBillReports(Map<String, Long> reports) { + this.reports = reports; + } + + public static MemberBillReports createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { + PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); + PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); + + Map<String, Long> memberBillReports = initReports(memberActions); + Set<String> currentMembers = new HashSet<>(); + + while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { + if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { + addMemberAction(sortedMemberActions, currentMembers); + continue; + } + addBillAction(sortedBillActions, currentMembers, memberBillReports); + } + + while (!sortedBillActions.isEmpty()) { + addBillAction(sortedBillActions, currentMembers, memberBillReports); + } + + return new MemberBillReports(memberBillReports); + } + + private static Map<String, Long> initReports(List<MemberAction> memberActions) { + return memberActions.stream() + .map(MemberAction::getMemberName) + .distinct() + .collect(toMap(Function.identity(), i -> 0L)); + } + + private static boolean isMemberActionTurn( + PriorityQueue<MemberAction> memberActions, + PriorityQueue<BillAction> billActions + ) { + MemberAction memberAction = memberActions.peek(); + BillAction billAction = billActions.peek(); + + return memberAction.getSequence() < billAction.getSequence(); + } + + private static void addMemberAction(PriorityQueue<MemberAction> sortedMemberActions, Set<String> currentMembers) { + MemberAction memberAction = sortedMemberActions.poll(); + String memberName = memberAction.getMemberName(); + if (memberAction.isSameStatus(MemberActionStatus.IN)) { + currentMembers.add(memberName); + return; + } + currentMembers.remove(memberAction.getMemberName()); + } + + private static void addBillAction( + PriorityQueue<BillAction> sortedBillActions, + Set<String> currentMembers, + Map<String, Long> memberBillReports + ) { + BillAction billAction = sortedBillActions.poll(); + Long pricePerMember = billAction.getPrice() / currentMembers.size(); + for (String currentMember : currentMembers) { + Long price = memberBillReports.getOrDefault(currentMember, 0L) + pricePerMember; + memberBillReports.put(currentMember, price); + } + } +} diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java new file mode 100644 index 000000000..fbde65a24 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/ActionController.java @@ -0,0 +1,26 @@ +package server.haengdong.presentation; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.ActionService; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.presentation.response.MemberBillReportsResponse; + +@RequiredArgsConstructor +@RestController +public class ActionController { + + private final ActionService actionService; + + @GetMapping("/api/events/{token}/actions/reports") + public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("token") String token) { + List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); + + return ResponseEntity.ok() + .body(MemberBillReportsResponse.of(memberBillReports)); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java new file mode 100644 index 000000000..0ea409202 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.MemberBillReportAppResponse; + +public record MemberBillReportResponse(String name, Long price) { + + public static MemberBillReportResponse of(MemberBillReportAppResponse memberBillReportAppResponse) { + return new MemberBillReportResponse(memberBillReportAppResponse.name(), memberBillReportAppResponse.price()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java new file mode 100644 index 000000000..d350c4009 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.MemberBillReportAppResponse; + +public record MemberBillReportsResponse(List<MemberBillReportResponse> reports) { + + public static MemberBillReportsResponse of(List<MemberBillReportAppResponse> memberBillReports) { + List<MemberBillReportResponse> reports = memberBillReports.stream() + .map(MemberBillReportResponse::of) + .toList(); + + return new MemberBillReportsResponse(reports); + } +} diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java new file mode 100644 index 000000000..3680b10d5 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/ActionServiceTest.java @@ -0,0 +1,68 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; + +@SpringBootTest +class ActionServiceTest { + + @Autowired + private ActionService actionService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @DisplayName("참여자별 정산 현황을 조회한다.") + @Test + void getMemberBillReports() { + String token = "tOkEn1"; + Event event = new Event("행동대장", token); + Event savedEvent = eventRepository.save(event); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(savedEvent, 1L), "소하", IN, 1L), + new MemberAction(new Action(savedEvent, 2L), "감자", IN, 1L), + new MemberAction(new Action(savedEvent, 3L), "쿠키", IN, 1L), + new MemberAction(new Action(savedEvent, 5L), "감자", OUT, 2L) + ); + List<BillAction> billActions = List.of( + new BillAction(new Action(savedEvent, 4L), "뽕족", 60_000L), + new BillAction(new Action(savedEvent, 6L), "인생맥주", 40_000L), + new BillAction(new Action(savedEvent, 7L), "인생네컷", 20_000L) + ); + memberActionRepository.saveAll(memberActions); + billActionRepository.saveAll(billActions); + + List<MemberBillReportAppResponse> responses = actionService.getMemberBillReports(token); + + assertThat(responses) + .hasSize(3) + .extracting(MemberBillReportAppResponse::name, MemberBillReportAppResponse::price) + .containsExactlyInAnyOrder( + tuple("감자", 20_000L), + tuple("쿠키", 50_000L), + tuple("소하", 50_000L) + ); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportsTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportsTest.java new file mode 100644 index 000000000..db0e2ff37 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/MemberBillReportsTest.java @@ -0,0 +1,43 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; + +class MemberBillReportsTest { + + @DisplayName("액션 목록으로 참가자 정산 리포트를 생성한다.") + @Test + void createByActions() { + String token = "TOK2N"; + Event event = new Event("행동대장", token); + List<BillAction> billActions = List.of( + new BillAction(new Action(event, 4L), "뽕족", 60_000L), + new BillAction(new Action(event, 6L), "인생맥주", 40_000L), + new BillAction(new Action(event, 7L), "인생네컷", 20_000L) + ); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(event, 1L), "소하", IN, 1L), + new MemberAction(new Action(event, 2L), "감자", IN, 1L), + new MemberAction(new Action(event, 3L), "쿠키", IN, 1L), + new MemberAction(new Action(event, 5L), "감자", OUT, 2L) + ); + + MemberBillReports memberBillReports = MemberBillReports.createByActions(billActions, memberActions); + + assertThat(memberBillReports.getReports()) + .containsAllEntriesOf( + Map.of( + "감자", 20_000L, + "쿠키", 50_000L, + "소하", 50_000L + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java new file mode 100644 index 000000000..739ac4962 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java @@ -0,0 +1,49 @@ +package server.haengdong.presentation; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import server.haengdong.application.ActionService; +import server.haengdong.application.response.MemberBillReportAppResponse; + +@WebMvcTest(ActionController.class) +class ActionControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ActionService actionService; + + @DisplayName("참여자별 정산 현황을 조회한다.") + @Test + void getMemberBillReports() throws Exception { + List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( + new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); + + given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); + + mockMvc.perform(get("/api/events/{token}/actions/reports", "token") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))); + + } +} From 8ed9900339b82cef0232ca78c6ad856539eb885f Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Wed, 24 Jul 2024 19:25:11 +0900 Subject: [PATCH 079/273] =?UTF-8?q?feat:=20api=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=96=89=EC=82=AC=20url=EC=9D=84=20?= =?UTF-8?q?=ED=91=9C=ED=98=84=ED=95=98=EB=8A=94=20=EC=9A=A9=EC=96=B4?= =?UTF-8?q?=EC=99=80=20=EC=A0=84=EB=8B=AC=20=EB=B0=A9=EC=8B=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#98)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 --- .../haengdong/presentation/ActionController.java | 4 ++-- .../presentation/BillActionController.java | 4 ++-- .../haengdong/presentation/EventController.java | 15 ++++++--------- .../presentation/MemberActionController.java | 8 ++++---- .../presentation/response/EventResponse.java | 10 ++++++++++ .../presentation/EventControllerTest.java | 3 +-- 6 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 server/src/main/java/server/haengdong/presentation/response/EventResponse.java diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java index fbde65a24..657cb567e 100644 --- a/server/src/main/java/server/haengdong/presentation/ActionController.java +++ b/server/src/main/java/server/haengdong/presentation/ActionController.java @@ -16,8 +16,8 @@ public class ActionController { private final ActionService actionService; - @GetMapping("/api/events/{token}/actions/reports") - public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("token") String token) { + @GetMapping("/api/events/{eventId}/actions/reports") + public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("eventId") String token) { List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); return ResponseEntity.ok() diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java index 139d6a470..fcdacb270 100644 --- a/server/src/main/java/server/haengdong/presentation/BillActionController.java +++ b/server/src/main/java/server/haengdong/presentation/BillActionController.java @@ -16,9 +16,9 @@ public class BillActionController { private final BillActionService billActionService; - @PostMapping("/api/events/{token}/actions/bills") + @PostMapping("/api/events/{eventId}/actions/bills") public ResponseEntity<Void> saveAllBillAction( - @PathVariable String token, + @PathVariable("eventId") String token, @RequestBody @Valid BillActionsSaveRequest request ) { billActionService.saveAllBillAction(token, request.toAppRequests()); diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java index 538ca9c1e..263bc35aa 100644 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -1,6 +1,5 @@ package server.haengdong.presentation; -import java.net.URI; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -9,9 +8,9 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import server.haengdong.application.EventService; -import server.haengdong.application.response.EventAppResponse; import server.haengdong.presentation.request.EventSaveRequest; import server.haengdong.presentation.response.EventDetailResponse; +import server.haengdong.presentation.response.EventResponse; @RequiredArgsConstructor @RestController @@ -20,16 +19,14 @@ public class EventController { private final EventService eventService; @PostMapping("/api/events") - public ResponseEntity<Void> saveEvent(@RequestBody EventSaveRequest request) { - EventAppResponse eventAppResponse = eventService.saveEvent(request.toAppRequest()); + public ResponseEntity<EventResponse> saveEvent(@RequestBody EventSaveRequest request) { + EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); - return ResponseEntity.ok() - .location(URI.create("events/" + eventAppResponse.token())) - .build(); + return ResponseEntity.ok(eventResponse); } - @GetMapping("/api/events/{token}") - public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("token") String token) { + @GetMapping("/api/events/{eventId}") + public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") String token) { EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); return ResponseEntity.ok(eventDetailResponse); diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java index cd45e3237..c12370d86 100644 --- a/server/src/main/java/server/haengdong/presentation/MemberActionController.java +++ b/server/src/main/java/server/haengdong/presentation/MemberActionController.java @@ -19,9 +19,9 @@ public class MemberActionController { private final MemberActionService memberActionService; - @PostMapping("/api/events/{token}/actions/members") + @PostMapping("/api/events/{eventId}/actions/members") public ResponseEntity<Void> saveMemberAction( - @PathVariable("token") String token, + @PathVariable("eventId") String token, @RequestBody MemberActionsSaveRequest request ) { memberActionService.saveMemberAction(token, request.toAppRequest()); @@ -29,8 +29,8 @@ public ResponseEntity<Void> saveMemberAction( return ResponseEntity.ok().build(); } - @GetMapping("/api/events/{token}/members/current") - public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("token") String token) { + @GetMapping("/api/events/{eventId}/members/current") + public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("eventId") String token) { List<CurrentMemberAppResponse> currentMembers = memberActionService.getCurrentMembers(token); return ResponseEntity.ok() diff --git a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java new file mode 100644 index 000000000..506f5e814 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.EventAppResponse; + +public record EventResponse(String eventId) { + + public static EventResponse of(EventAppResponse eventAppResponse) { + return new EventResponse(eventAppResponse.token()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java index c50431696..55a48630f 100644 --- a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java @@ -16,7 +16,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import server.haengdong.application.EventService; import server.haengdong.application.request.EventAppRequest; import server.haengdong.application.response.EventAppResponse; @@ -49,7 +48,7 @@ void saveEvent() throws Exception { .content(requestBody)) .andDo(print()) .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.redirectedUrl("events/" + token)); + .andExpect(jsonPath("$.eventId").value("TOKEN")); } @DisplayName("토큰으로 행사를 조회한다.") From 2eaeb4b14445141f3f425d892442e63eb2652f93 Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Wed, 24 Jul 2024 23:42:10 +0900 Subject: [PATCH 080/273] =?UTF-8?q?feat:=20=EA=B8=B0=EB=B3=B8=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=8C=8C=EC=9D=BC=EC=97=90=EC=84=9C=20DB=EB=A5=BC=20M?= =?UTF-8?q?ySQL=EC=9D=84=20H2=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#102)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 --- server/src/main/resources/application.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml index e1bdd7f79..faf7a36f1 100644 --- a/server/src/main/resources/application.yml +++ b/server/src/main/resources/application.yml @@ -1,17 +1,21 @@ spring: datasource: - url: jdbc:mysql://localhost:3306/haengdong - username: root - password: 1234 - driver-class-name: com.mysql.cj.jdbc.Driver + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:database + username: sa + password: + + h2: + console: + enabled: true + path: /h2-console jpa: hibernate: - ddl-auto: none + ddl-auto: create properties: hibernate: - dialect: org.hibernate.dialect.MySQL8Dialect - format_sql: true + format_sql: true show-sql: true cors: From 2248e9d95535d0b19e083b87322f28cc457cbf9c Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:21:46 +0900 Subject: [PATCH 081/273] =?UTF-8?q?refactor:=20=EC=A7=80=EC=B6=9C=20?= =?UTF-8?q?=EB=82=B4=EC=97=AD=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=20=EC=B0=B8=EC=97=AC=20=EC=9D=B8=EC=9B=90=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=98=88=EC=99=B8=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#100)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 --- .../server/haengdong/application/MemberActionService.java | 4 +++- .../java/server/haengdong/domain/action/BillAction.java | 8 ++++++-- .../presentation/request/BillActionSaveRequest.java | 7 ++----- .../haengdong/application/MemberActionServiceTest.java | 5 +++-- .../server/haengdong/domain/action/BillActionTest.java | 5 +++-- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java index ba17b28c4..5094bf2c0 100644 --- a/server/src/main/java/server/haengdong/application/MemberActionService.java +++ b/server/src/main/java/server/haengdong/application/MemberActionService.java @@ -13,6 +13,8 @@ import server.haengdong.domain.action.MemberActionRepository; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; @RequiredArgsConstructor @Transactional(readOnly = true) @@ -53,6 +55,6 @@ public List<CurrentMemberAppResponse> getCurrentMembers(String token) { private Event findEvent(String token) { return eventRepository.findByToken(token) - .orElseThrow(() -> new IllegalArgumentException("event not found")); + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); } } diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java index f0e82c409..1027206f5 100644 --- a/server/src/main/java/server/haengdong/domain/action/BillAction.java +++ b/server/src/main/java/server/haengdong/domain/action/BillAction.java @@ -11,6 +11,8 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -45,13 +47,15 @@ public BillAction(Action action, String title, Long price) { private void validateTitle(String title) { int titleLength = title.trim().length(); if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { - throw new IllegalArgumentException("앞뒤 공백을 제거한 지출 내역 제목은 2 ~ 30자여야 합니다."); + throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", MIN_TITLE_LENGTH, MAX_TITLE_LENGTH)); } } private void validatePrice(Long price) { if (price < MIN_PRICE || price > MAX_PRICE) { - throw new IllegalArgumentException("지출 금액은 10,000,000 이하의 자연수여야 합니다."); + throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", MAX_PRICE)); } } diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java index 8d662050f..a0d878f7f 100644 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java @@ -1,18 +1,15 @@ package server.haengdong.presentation.request; +import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Positive; -import jakarta.validation.constraints.Size; import server.haengdong.application.request.BillActionAppRequest; public record BillActionSaveRequest( - @NotNull - @Size(min = 2, max = 30) + @NotBlank String title, @NotNull - @Positive Long price ) { diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java index 378aa6006..7212e300d 100644 --- a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java @@ -19,6 +19,7 @@ import server.haengdong.domain.action.MemberActionRepository; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; @SpringBootTest class MemberActionServiceTest { @@ -79,13 +80,13 @@ void saveMemberActionTest2() { List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(HaengdongException.class); } @DisplayName("이벤트가 없으면 현재 참여 인원을 조회할 수 없다.") @Test void getCurrentMembers() { assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) - .isInstanceOf(IllegalArgumentException.class); + .isInstanceOf(HaengdongException.class); } } diff --git a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java index d179ca6eb..601ca95d7 100644 --- a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java +++ b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java @@ -9,6 +9,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongException; class BillActionTest { @@ -21,7 +22,7 @@ void validateTitle(String title) { Long price = 100L; assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(IllegalArgumentException.class) + .isInstanceOf(HaengdongException.class) .hasMessage("앞뒤 공백을 제거한 지출 내역 제목은 2 ~ 30자여야 합니다."); } @@ -34,7 +35,7 @@ void validatePrice(long price) { String title = "title"; assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(IllegalArgumentException.class) + .isInstanceOf(HaengdongException.class) .hasMessage("지출 금액은 10,000,000 이하의 자연수여야 합니다."); } From 2610de813b66cb699e61f2984f8f3bd28f18f64a Mon Sep 17 00:00:00 2001 From: JUHA <84626225+khabh@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:22:37 +0900 Subject: [PATCH 082/273] =?UTF-8?q?refactor:=20=EC=B0=B8=EC=97=AC=EC=9E=90?= =?UTF-8?q?=EB=B3=84=20=EC=A0=95=EC=82=B0=20=ED=98=84=ED=99=A9=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=98=88=EC=99=B8=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#106)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/haengdong/application/ActionService.java | 4 +++- .../haengdong/application/ActionServiceTest.java | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java index 22ca43a6b..b28374bb9 100644 --- a/server/src/main/java/server/haengdong/application/ActionService.java +++ b/server/src/main/java/server/haengdong/application/ActionService.java @@ -12,6 +12,8 @@ import server.haengdong.domain.action.MemberBillReports; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; @RequiredArgsConstructor @Service @@ -23,7 +25,7 @@ public class ActionService { public List<MemberBillReportAppResponse> getMemberBillReports(String token) { Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new IllegalArgumentException("event not found")); + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); List<BillAction> billActions = billActionRepository.findByAction_Event(event); List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java index 3680b10d5..ac2dc4f4f 100644 --- a/server/src/test/java/server/haengdong/application/ActionServiceTest.java +++ b/server/src/test/java/server/haengdong/application/ActionServiceTest.java @@ -1,6 +1,7 @@ package server.haengdong.application; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; import static server.haengdong.domain.action.MemberActionStatus.IN; import static server.haengdong.domain.action.MemberActionStatus.OUT; @@ -18,6 +19,8 @@ import server.haengdong.domain.action.MemberActionRepository; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; @SpringBootTest class ActionServiceTest { @@ -65,4 +68,12 @@ void getMemberBillReports() { tuple("소하", 50_000L) ); } + + @DisplayName("존재하지 않는 이벤트의 참여자별 정산 현황을 조회하는 경우 예외가 발생한다.") + @Test + void getMemberBillReports1() { + assertThatThrownBy(() -> actionService.getMemberBillReports("invalid token")) + .isInstanceOf(HaengdongException.class) + .hasMessage(HaengdongErrorCode.NOT_FOUND_EVENT.getMessage()); + } } From 3e2c5b07a54a6efe24081e0d20fb6e93656f0981 Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:30:29 +0900 Subject: [PATCH 083/273] =?UTF-8?q?refactor:=20=ED=96=89=EC=82=AC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20API=20=EC=98=88=EC=99=B8=20=EB=A9=94?= =?UTF-8?q?=EC=84=B8=EC=A7=80=20=EB=B0=8F=20DTO=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=95=A0=EB=84=88=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#103)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 --- .../server/haengdong/domain/event/Event.java | 26 +++++++++++++ .../presentation/EventController.java | 3 +- .../request/EventSaveRequest.java | 9 ++++- .../haengdong/domain/event/EventTest.java | 37 +++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 server/src/test/java/server/haengdong/domain/event/EventTest.java diff --git a/server/src/main/java/server/haengdong/domain/event/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java index c6877e1a6..24369a184 100644 --- a/server/src/main/java/server/haengdong/domain/event/Event.java +++ b/server/src/main/java/server/haengdong/domain/event/Event.java @@ -7,12 +7,18 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity public class Event { + private static final int MIN_NAME_LENGTH = 2; + private static final int MAX_NAME_LENGTH = 20; + private static final String SPACES = " "; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -22,7 +28,27 @@ public class Event { private String token; public Event(String name, String token) { + validateName(name); this.name = name; this.token = token; } + + private void validateName(String name) { + int nameLength = name.length(); + if (nameLength < MIN_NAME_LENGTH || MAX_NAME_LENGTH < nameLength) { + throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", + MIN_NAME_LENGTH, + MAX_NAME_LENGTH, + name.length())); + } + if (isBlankContinuous(name)) { + throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", name)); + } + } + + private boolean isBlankContinuous(String name) { + return name.contains(SPACES); + } } diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java index 263bc35aa..260253e8b 100644 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -1,5 +1,6 @@ package server.haengdong.presentation; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -19,7 +20,7 @@ public class EventController { private final EventService eventService; @PostMapping("/api/events") - public ResponseEntity<EventResponse> saveEvent(@RequestBody EventSaveRequest request) { + public ResponseEntity<EventResponse> saveEvent(@Valid @RequestBody EventSaveRequest request) { EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); return ResponseEntity.ok(eventResponse); diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java index 8bd4cfda8..b28572332 100644 --- a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java +++ b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java @@ -1,10 +1,15 @@ package server.haengdong.presentation.request; +import jakarta.validation.constraints.NotBlank; import server.haengdong.application.request.EventAppRequest; -public record EventSaveRequest(String name) { +public record EventSaveRequest( + + @NotBlank + String eventName +) { public EventAppRequest toAppRequest() { - return new EventAppRequest(name); + return new EventAppRequest(eventName); } } diff --git a/server/src/test/java/server/haengdong/domain/event/EventTest.java b/server/src/test/java/server/haengdong/domain/event/EventTest.java new file mode 100644 index 000000000..98f6c7050 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/event/EventTest.java @@ -0,0 +1,37 @@ +package server.haengdong.domain.event; + +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.exception.HaengdongException; + +class EventTest { + + @DisplayName("공백 문자가 연속되지 않고, 이름이 2자 이상 20자 이하인 행사를 생성하면 예외가 발생하지 않는다.") + @ParameterizedTest + @ValueSource(strings = {"12", "12345678901234567890", "공 백", " 공백", "공백 ", " 공 백 "}) + void createSuccessTest(String eventName) { + assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) + .doesNotThrowAnyException(); + } + + @DisplayName("공백 문자가 연속되면 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {" 공백", "공백 ", "공백 연속", "공 백"}) + void createFailTest1(String eventName) { + assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class) + .hasMessage(String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", eventName)); + } + + @DisplayName("이름이 2자 미만이거나 20자 초과인 경우 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"", " ", "123456789012345678901"}) + void createFilTest2(String eventName) { + assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class) + .hasMessage(String.format("행사 이름은 2자 이상 20자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", eventName.length())); + } +} From 7b92958ac4abbc82b2ecbaa0074edf5fada9403b Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:16:44 +0900 Subject: [PATCH 084/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 --- client/eslint.config.mjs | 3 + client/package-lock.json | 8 +- client/package.json | 2 +- client/src/apis/request/bill.ts | 3 +- client/src/apis/request/event.ts | 3 +- client/src/apis/request/member.ts | 3 +- client/src/apis/request/report.ts | 3 +- client/src/apis/request/stepList.ts | 3 +- .../MemberReportList/MemberReportList.tsx | 3 +- client/src/components/Modal/Modal.tsx | 20 --- .../SetActionModalContent.style.ts | 16 ++ .../SetActionModalContent.style.tsx | 24 --- .../SetActionModalContent.tsx | 76 +++++---- .../SetPurchase.style.ts | 23 +++ .../SetActionModalContent/SetPurchase.tsx | 69 ++++---- .../UpdateParticipants.style.ts | 18 ++ .../UpdateParticipants.tsx | 76 +++++---- .../SetInitialParticipants.style.ts | 49 ++---- .../SetInitialParticipants.tsx | 75 +++++---- client/src/components/Modal/index.ts | 3 +- client/src/components/StepList/StepList.tsx | 3 +- client/src/components/Switch/Switch.style.tsx | 17 -- client/src/components/Switch/Switch.tsx | 28 ---- client/src/components/Switch/index.tsx | 1 - .../src/hooks/useDynamicAdditionalInput.tsx | 52 ++++++ client/src/hooks/useDynamicInputPairs.tsx | 42 +++++ .../useSearchMemberReportList.tsx | 5 +- client/src/hooks/useStepList/useStepList.tsx | 2 + client/src/index.css | 6 + client/src/pages/CreateEvent/CreateEvent.tsx | 1 + client/src/pages/Event/Event.style.ts | 22 +-- client/src/pages/Event/Event.tsx | 158 ++++++++++-------- client/src/pages/Home/HomeContent.tsx | 3 +- client/src/pages/Home/HomeLayout.tsx | 1 + 34 files changed, 459 insertions(+), 362 deletions(-) delete mode 100644 client/src/components/Modal/Modal.tsx create mode 100644 client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.ts delete mode 100644 client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.tsx create mode 100644 client/src/components/Modal/SetActionModalContent/SetPurchase.style.ts create mode 100644 client/src/components/Modal/SetActionModalContent/UpdateParticipants.style.ts delete mode 100644 client/src/components/Switch/Switch.style.tsx delete mode 100644 client/src/components/Switch/Switch.tsx delete mode 100644 client/src/components/Switch/index.tsx create mode 100644 client/src/hooks/useDynamicAdditionalInput.tsx create mode 100644 client/src/hooks/useDynamicInputPairs.tsx diff --git a/client/eslint.config.mjs b/client/eslint.config.mjs index 46d23de19..106f6ccde 100644 --- a/client/eslint.config.mjs +++ b/client/eslint.config.mjs @@ -32,6 +32,9 @@ export default [ 'react/react-in-jsx-scope': 'off', 'react/prop-types': 'off', 'react/jsx-uses-vars': 'error', + // '@typescript-eslint/no-use-before-define': ['error'], + // '@typescript-eslint/explicit-module-boundary-types': 'error', + // "import/no-unresolved": "error", 'import/order': [ 'error', { diff --git a/client/package-lock.json b/client/package-lock.json index d66f61a8b..4ee33aaae 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.20", + "haengdong-design": "^0.1.28", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -6274,9 +6274,9 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.20", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.20.tgz", - "integrity": "sha512-MB4L5lP0eDKhm5hU/XROKNE/H0pj9Zaf/uiLUUhtvOzS6bzHd2guYlE/LI0G2bvA7v65APD1Bzp3KXGi/Z8nNw==", + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.28.tgz", + "integrity": "sha512-czidJMyGWLbdfrabj3SARWMS3fB26c1Fg43XxS7ognTc3mG37BqRe6coPKueU0onB4IoB+xhYZcmHJKIZwukLw==", "dependencies": { "@emotion/react": "^11.11.4", "@svgr/webpack": "^8.1.0", diff --git a/client/package.json b/client/package.json index 8155d4dc9..350a884ed 100644 --- a/client/package.json +++ b/client/package.json @@ -45,9 +45,9 @@ }, "dependencies": { "@emotion/react": "^11.11.4", - "haengdong-design": "^0.1.20", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", + "haengdong-design": "^0.1.28", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 31c097276..2e364b944 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -1,8 +1,9 @@ +import {Bill} from 'types/stepList'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestPost} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -import {Bill} from 'types/stepList'; type RequestAddBillList = { BillList: Bill[]; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index c941f31d4..f6ff6d56b 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -1,7 +1,8 @@ +import {StepList} from 'types/stepList'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet} from '@apis/fetcher'; -import {StepList} from 'types/stepList'; type RequestCreateNewEvent = { name: string; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index af8b6c689..252c85e11 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -1,8 +1,9 @@ +import {Member} from 'types/stepList'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestPost} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -import {Member} from 'types/stepList'; type RequestUpdateMemberList = { MemberList: Member[]; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts index cc9b0ad66..9b714752a 100644 --- a/client/src/apis/request/report.ts +++ b/client/src/apis/request/report.ts @@ -1,8 +1,9 @@ +import {MemberReport} from 'types/stepList'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -import {MemberReport} from 'types/stepList'; type ResponseMemberReportList = { reports: MemberReport[]; diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts index d696c69aa..60ad385e4 100644 --- a/client/src/apis/request/stepList.ts +++ b/client/src/apis/request/stepList.ts @@ -1,8 +1,9 @@ +import {Bill, Member, StepList} from 'types/stepList'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet, requestPost} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -import {Bill, Member, StepList} from 'types/stepList'; // TODO: (@weadie) 현재 토큰을 어떻게 관리할지.. 계속 사용되는데 export const requestStepList = async ({eventId}: WithEventId) => { diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx index 17a26f9ca..ebf1cf72e 100644 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -1,7 +1,8 @@ -import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; import {ExpenseList, Flex, Input} from 'haengdong-design'; import React, {useState} from 'react'; +import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; + const MemberReportList = () => { const [name, setName] = useState(''); const {memberReportSearchList} = useSearchMemberReportList({name, eventId: '므와아아아'}); diff --git a/client/src/components/Modal/Modal.tsx b/client/src/components/Modal/Modal.tsx deleted file mode 100644 index aaf0b8b6a..000000000 --- a/client/src/components/Modal/Modal.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import {css} from '@emotion/react'; - -import {modalBodyStyle, modalBackdropStyle} from './Modal.style'; - -interface ModalProps { - children: React.ReactNode; - onClose: () => void; -} - -const Modal = ({children, onClose}: ModalProps) => { - return ( - <> - <div css={modalBackdropStyle} onClick={onClose} /> - <div css={modalBodyStyle}>{children}</div> - </> - ); -}; - -export default Modal; diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.ts b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.ts new file mode 100644 index 000000000..560f672d5 --- /dev/null +++ b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.ts @@ -0,0 +1,16 @@ +import {css} from '@emotion/react'; + +export const setActionModalContentStyle = css({ + display: 'flex', + flexDirection: 'column', + width: '100%', + height: '100%', + padding: '0 1.5rem', + gap: '1.5rem', +}); + +export const setActionModalContentSwitchContainerStyle = css({ + display: 'flex', + width: '100%', + justifyContent: 'space-between', +}); diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.tsx b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.tsx deleted file mode 100644 index 48e975e9c..000000000 --- a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import {css} from '@emotion/react'; - -export const buttonStyle = (isActive: boolean) => css` - font-weight: ${isActive ? 'bold' : 'normal'}; - color: ${isActive ? '#333' : '#ccc'}; - padding: 10px; - cursor: pointer; -`; - -export const dividerStyle = css` - margin: 0 10px; - color: #ccc; -`; - -export const switchStyle = css` - display: flex; - align-items: center; -`; - -export const switchContainerStyle = css` - display: flex; - width: 100%; - justify-content: space-between; -`; diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx index 2c293abc8..93a917652 100644 --- a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx +++ b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx @@ -1,58 +1,60 @@ import {useState} from 'react'; +import {BottomSheet, Switch} from 'haengdong-design'; -import {Switch} from '@components/Switch'; +import {InOutType, ParticipantType, PurchaseInformation} from '@pages/Event/Event'; import SetPurchase from './SetPurchase'; import UpdateParticipants from './UpdateParticipants'; -import {switchContainerStyle} from './SetActionModalContent.style'; +import {setActionModalContentStyle, setActionModalContentSwitchContainerStyle} from './SetActionModalContent.style'; -// type ActionType = '지출' | '인원'; +export type ActionType = '지출' | '인원'; interface SetActionModalContentProps { - setOpen: React.Dispatch<React.SetStateAction<boolean>>; participants: string[]; - setParticipants: React.Dispatch<React.SetStateAction<string[]>>; - purchaseInformation: any; - setPurchaseInformation: any; + openBottomSheet: boolean; + + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setOrder: React.Dispatch<React.SetStateAction<number>>; } const SetActionModalContent = ({ - setOpen, participants, - setParticipants, - purchaseInformation, - setPurchaseInformation, + openBottomSheet, + + setOpenBottomSheet, + setOrder, }: SetActionModalContentProps) => { - const [actionType, setActionType] = useState('지출'); - const [participantType, setParticipantType] = useState('늦참'); + const [action, setAction] = useState<ActionType>('지출'); + const [participantAction, setParticipantAction] = useState<InOutType>('탈주'); + + const handleActionTypeChange = (value: string) => { + setAction(value as ActionType); + }; + + const handleParticipantTypeChange = (value: string) => { + setParticipantAction(value as InOutType); + }; return ( - <> - <div css={switchContainerStyle}> - <Switch buttonList={['지출', '인원']} curSwitch={actionType} setSwitch={setActionType} /> - {actionType === '인원' && ( - <Switch buttonList={['늦참', '탈주']} curSwitch={participantType} setSwitch={setParticipantType} /> + <BottomSheet isOpened={openBottomSheet} onChangeClose={() => setOpenBottomSheet(false)}> + <div css={setActionModalContentStyle}> + <div css={setActionModalContentSwitchContainerStyle}> + <Switch value={action} onChange={handleActionTypeChange} values={['지출', '인원']} /> + {action === '인원' && ( + <Switch values={['늦참', '탈주']} value={participantAction} onChange={handleParticipantTypeChange} /> + )} + </div> + + {action === '지출' && <SetPurchase setOpenBottomSheet={setOpenBottomSheet} setOrder={setOrder} />} + {action === '인원' && ( + <UpdateParticipants + participantAction={participantAction} + participants={participants} + setOpenBottomSheet={setOpenBottomSheet} + /> )} </div> - - {actionType === '지출' && ( - <SetPurchase - setOpen={setOpen} - setPurchaseInformation={setPurchaseInformation} - purchaseInformation={purchaseInformation} - /> - )} - {actionType === '인원' && ( - <UpdateParticipants - setOpen={setOpen} - participantType={participantType} - participants={participants} - setParticipants={setParticipants} - setPurchaseInformation={setPurchaseInformation} - purchaseInformation={purchaseInformation} - /> - )} - </> + </BottomSheet> ); }; diff --git a/client/src/components/Modal/SetActionModalContent/SetPurchase.style.ts b/client/src/components/Modal/SetActionModalContent/SetPurchase.style.ts new file mode 100644 index 000000000..cc852da28 --- /dev/null +++ b/client/src/components/Modal/SetActionModalContent/SetPurchase.style.ts @@ -0,0 +1,23 @@ +import {css} from '@emotion/react'; + +export const setPurchaseStyle = () => + css({ + height: '100%', + }); + +export const setPurchaseInputContainerStyle = () => + css({ + display: 'flex', + height: '100%', + flexDirection: 'column', + gap: '1.5rem', + overflow: 'auto', + paddingBottom: '14rem', + }); + +export const setPurchaseInputStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + }); diff --git a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx index 3112f2d41..515c048dd 100644 --- a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx +++ b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx @@ -1,42 +1,53 @@ -import {useState} from 'react'; +import {Input, FixedButton} from 'haengdong-design'; -import {PurchaseInformation} from '@pages/Event/Event'; +import useDynamicInputPairs from '@hooks/useDynamicInputPairs'; + +import {setPurchaseInputStyle, setPurchaseStyle, setPurchaseInputContainerStyle} from './SetPurchase.style'; interface SetPurchaseProps { - setOpen: React.Dispatch<React.SetStateAction<boolean>>; - setPurchaseInformation: any; - purchaseInformation: any; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setOrder: React.Dispatch<React.SetStateAction<number>>; } -const SetPurchase = ({setOpen, setPurchaseInformation}: SetPurchaseProps) => { - const [newPurchaseInformation, setNewPurchaseInformation] = useState<PurchaseInformation>({ - name: '', - price: 0, - }); - - const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => { - setNewPurchaseInformation({...newPurchaseInformation, name: e.target.value}); - }; - - const handlePriceChange = (e: React.ChangeEvent<HTMLInputElement>) => { - setNewPurchaseInformation({...newPurchaseInformation, price: parseFloat(e.target.value)}); - }; +const SetPurchase = ({setOpenBottomSheet, setOrder}: SetPurchaseProps) => { + const {inputPairs, inputRefs, handleInputChange, handleInputBlur} = useDynamicInputPairs(); - const addPurchaseInformation = () => { - setPurchaseInformation((prev: PurchaseInformation[]) => [...prev, newPurchaseInformation]); - setOpen(false); + const handleSetPurchaseSubmit = () => { + setOrder(prev => prev + 1); + // TODO: (@soha) api 요청시 inputPairs를 보내면 됨 + setOpenBottomSheet(false); }; return ( - <> - <div style={{display: 'flex', flexDirection: 'column'}}> - <input type="text" value={newPurchaseInformation.name} onChange={handleNameChange} placeholder="지출 내역" /> - <input type="number" value={newPurchaseInformation.price} onChange={handlePriceChange} placeholder="금액" /> + <div css={setPurchaseStyle}> + <div css={setPurchaseInputContainerStyle}> + {inputPairs.map((pair, index) => ( + <div key={index} css={setPurchaseInputStyle}> + <Input + type="text" + value={pair.name} + onChange={e => handleInputChange(index, 'name', e.target.value)} + onBlur={() => handleInputBlur(index)} + placeholder="지출 내역" + ref={el => (inputRefs.current[index * 2] = el)} + /> + <Input + type="number" + value={pair.price} + onChange={e => handleInputChange(index, 'price', e.target.value)} + onBlur={() => handleInputBlur(index)} + placeholder="금액" + ref={el => (inputRefs.current[index * 2 + 1] = el)} + /> + </div> + ))} </div> - <button style={{backgroundColor: 'lightGreen'}} onClick={addPurchaseInformation}> - 지출 내역 작성 완료 - </button> - </> + <FixedButton + variants={inputPairs.length - 1 ? 'primary' : 'tertiary'} + children={'추가하기'} + onClick={handleSetPurchaseSubmit} + /> + </div> ); }; diff --git a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.style.ts b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.style.ts new file mode 100644 index 000000000..087e25a85 --- /dev/null +++ b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.style.ts @@ -0,0 +1,18 @@ +import {css} from '@emotion/react'; + +export const updateParticipantsStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + height: '100%', + }); + +export const updateParticipantsInputStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '14rem', + }); diff --git a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx index e64ceff53..72b86faa7 100644 --- a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx +++ b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx @@ -1,51 +1,55 @@ +import {Input, FixedButton} from 'haengdong-design'; import {useState} from 'react'; +import {InOutType} from '@pages/Event/Event'; + +import useDynamicInput from '@hooks/useDynamicAdditionalInput'; + +import {updateParticipantsInputStyle, updateParticipantsStyle} from './UpdateParticipants.style'; + interface UpdateParticipantsProps { - setOpen: React.Dispatch<React.SetStateAction<boolean>>; - participantType: string; participants: string[]; - setParticipants: React.Dispatch<React.SetStateAction<string[]>>; - setPurchaseInformation: any; - purchaseInformation: any; + participantAction: InOutType; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; } -const UpdateParticipants = ({ - setPurchaseInformation, - purchaseInformation, - setOpen, - participantType, - participants, - setParticipants, -}: UpdateParticipantsProps) => { - const [name, setName] = useState(''); - - const updateParticipant = () => { - if (participantType === '늦참') { - if (participants.includes(name)) { - alert('이미 있는 사용자입니다.'); - return; - } +const UpdateParticipants = ({participantAction, participants, setOpenBottomSheet}: UpdateParticipantsProps) => { + const {inputs, inputRefs, handleInputChange, handleInputBlur, getNonEmptyInputs} = useDynamicInput(); - setParticipants([...participants, name]); - setPurchaseInformation([...purchaseInformation, {name, type: '늦참'}]); - } else if (participantType === '탈주') { - if (!participants.includes(name)) { - alert('그런 사용자는 없습니다. 올바른 이름을 입력해주세요.'); - return; + const handleUpdateParticipantsSubmit = () => { + const newParticipants = () => { + if (participantAction === '탈주') { + return participants.filter(participant => !getNonEmptyInputs().includes(participant)); + } else { + return [...participants, ...getNonEmptyInputs()]; } + }; - setParticipants(prev => prev.filter(participant => participant !== name)); - setPurchaseInformation([...purchaseInformation, {name, type: '탈주'}]); - } - - setName(''); - setOpen(false); + // TODO: (@soha) api 요청시 newParticipants()를 보내면 됨 + setOpenBottomSheet(false); }; return ( - <div style={{display: 'flex', flexDirection: 'column'}}> - <input onChange={event => setName(event.target.value)} value={name} /> - <button onClick={updateParticipant}>{participantType} 인원 확정</button> + <div css={updateParticipantsStyle}> + <div css={updateParticipantsInputStyle}> + {/* TODO: (@soha) Search로 변경하기 */} + {inputs.map((name, index) => ( + <Input + key={index} + placeholder="이름" + value={name} + type="text" + ref={el => (inputRefs.current[index] = el)} + onChange={e => handleInputChange(index, e.target.value)} + onBlur={() => handleInputBlur(index)} + /> + ))} + </div> + <FixedButton + variants={inputs.length - 1 ? 'primary' : 'tertiary'} + children={`${inputs.length - 1}명 ${participantAction}`} + onClick={handleUpdateParticipantsSubmit} + /> </div> ); }; diff --git a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts index 7f666c8d1..f0f5bf996 100644 --- a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts +++ b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts @@ -1,35 +1,20 @@ import {css} from '@emotion/react'; -export const inputStyle = css` - width: 100%; - padding: 10px; - border: 1px solid #ccc; - border-radius: 10px; - margin-bottom: 10px; -`; +export const setInitialParticipantsStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1.5rem', + }); -export const buttonStyle = (isActive: boolean) => css` - display: block; - width: 100%; - padding: 10px; - background-color: ${isActive ? '#B575FF' : '#e0e0e0'}; - border: none; - border-radius: 10px; - text-align: center; - color: ${isActive ? 'white' : '#999'}; - margin-top: 10px; -`; - -export const plusButtonStyle = css` - display: flex; - justify-content: center; - align-items: center; - width: 40px; - height: 40px; - background-color: #f5f5ff; - border: none; - border-radius: 50%; - color: #9e77ed; - font-size: 24px; - margin: 20px auto; -`; +export const setInitialParticipantsInputGroupStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '11rem', + }); diff --git a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx index 3a9f11a69..15a0b0460 100644 --- a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx +++ b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx @@ -1,47 +1,52 @@ -import {useState} from 'react'; +import {Text, Input, BottomSheet, FixedButton} from 'haengdong-design'; -import {buttonStyle, inputStyle, plusButtonStyle} from './SetInitialParticipants.style'; +import useDynamicInput from '@hooks/useDynamicAdditionalInput'; + +import {setInitialParticipantsInputGroupStyle, setInitialParticipantsStyle} from './SetInitialParticipants.style'; interface SetInitialParticipantsProps { - setParticipantsAndModalClose: (participants: string[]) => void; + openBottomSheet: boolean; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setParticipants: React.Dispatch<React.SetStateAction<string[]>>; } -const SetInitialParticipants = ({setParticipantsAndModalClose}: SetInitialParticipantsProps) => { - const [value, setValue] = useState(''); - const [participants, setParticipants] = useState<string[]>([]); - - const addParticipants = (event: React.FormEvent<HTMLFormElement>) => { - if (value === '') return; +const SetInitialParticipants = ({ + openBottomSheet, + setOpenBottomSheet, + setParticipants, +}: SetInitialParticipantsProps) => { + const {inputs, inputRefs, handleInputChange, handleInputBlur, getNonEmptyInputs} = useDynamicInput(); - event.preventDefault(); - setParticipants(prev => [...prev, value]); - setValue(''); + const handleSubmit = () => { + setParticipants(getNonEmptyInputs()); + // TODO: (@soha) api 요청시 getNonEmptyInputs() 보낼 형태 생성 + setOpenBottomSheet(false); }; return ( - <> - <h2>초기 인원 설정하기</h2> - {participants.map((participant, index) => ( - <input key={`${participant}-${index}`} type="text" value={participant} disabled /> - ))} - <form onSubmit={addParticipants}> - <input - type="text" - placeholder="이름" - css={inputStyle} - value={value} - onChange={event => setValue(event.target.value)} - /> - <button css={plusButtonStyle}>+</button> - </form> - <button - css={buttonStyle(participants.length !== 0)} - disabled={participants.length === 0} - onClick={() => setParticipantsAndModalClose(participants)} - > - 인원 설정 완료 - </button> - </> + <BottomSheet isOpened={openBottomSheet} onChangeClose={() => setOpenBottomSheet(false)}> + <div css={setInitialParticipantsStyle}> + <Text size="bodyBold">초기 인원 설정하기</Text> + <div css={setInitialParticipantsInputGroupStyle}> + {inputs.map((participant, index) => ( + <Input + key={index} + placeholder="이름" + type="text" + value={participant} + ref={el => (inputRefs.current[index] = el)} + onChange={e => handleInputChange(index, e.target.value)} + onBlur={() => handleInputBlur(index)} + /> + ))} + </div> + </div> + <FixedButton + variants={inputs.length - 1 ? 'primary' : 'tertiary'} + onClick={handleSubmit} + children={'인원 설정 완료'} + /> + </BottomSheet> ); }; diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts index 1693a3eef..e5d5264cd 100644 --- a/client/src/components/Modal/index.ts +++ b/client/src/components/Modal/index.ts @@ -1 +1,2 @@ -export {default as Modal} from './Modal'; +export {default as SetInitialParticipants} from './SetInitialParticipants/SetInitialParticipants'; +export {default as SetActionModalContent} from './SetActionModalContent/SetActionModalContent'; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 2ea9c0bc5..76dedc41b 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,5 +1,6 @@ -import {useStepList} from '@hooks/useStepList/useStepList'; import {Flex, InOutItem, StepItem} from 'haengdong-design'; + +import {useStepList} from '@hooks/useStepList/useStepList'; import {MemberType} from 'types/stepList'; const StepList = () => { diff --git a/client/src/components/Switch/Switch.style.tsx b/client/src/components/Switch/Switch.style.tsx deleted file mode 100644 index 0e1b81b50..000000000 --- a/client/src/components/Switch/Switch.style.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import {css} from '@emotion/react'; - -export const buttonStyle = (isActive: boolean) => css` - font-weight: ${isActive ? 'bold' : 'normal'}; - color: ${isActive ? '#333' : '#ccc'}; - padding: 10px; - cursor: pointer; -`; - -export const dividerStyle = css` - color: #ccc; -`; - -export const switchStyle = css` - display: flex; - align-items: center; -`; diff --git a/client/src/components/Switch/Switch.tsx b/client/src/components/Switch/Switch.tsx deleted file mode 100644 index ba30ea320..000000000 --- a/client/src/components/Switch/Switch.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; - -import {buttonStyle, switchStyle} from './Switch.style'; - -interface SwitchProps { - buttonList: string[]; - initialButton?: string; - curSwitch: string; - setSwitch: React.Dispatch<React.SetStateAction<string>>; -} - -const Switch = ({buttonList, initialButton = buttonList[0], setSwitch, curSwitch}: SwitchProps) => { - const handleButtonClick = (type: string) => { - setSwitch(type); - }; - - return ( - <div css={switchStyle}> - {buttonList.map(buttonName => ( - <button css={buttonStyle(curSwitch === buttonName)} onClick={() => handleButtonClick(buttonName)}> - {buttonName} - </button> - ))} - </div> - ); -}; - -export default Switch; diff --git a/client/src/components/Switch/index.tsx b/client/src/components/Switch/index.tsx deleted file mode 100644 index 6c9915003..000000000 --- a/client/src/components/Switch/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export {default as Switch} from './Switch'; diff --git a/client/src/hooks/useDynamicAdditionalInput.tsx b/client/src/hooks/useDynamicAdditionalInput.tsx new file mode 100644 index 000000000..6bd592254 --- /dev/null +++ b/client/src/hooks/useDynamicAdditionalInput.tsx @@ -0,0 +1,52 @@ +import {useEffect, useRef, useState} from 'react'; + +const useDynamicInput = () => { + const [inputs, setInputs] = useState<string[]>(['']); + const inputRefs = useRef<(HTMLInputElement | null)[]>([]); + + // TODO: (@soha) 입력이 완료되고 중간에 값을 모두 지웠을 경우 Input이 없애지도록 수정하기 + const handleInputChange = (index: number, value: string) => { + const newInputs = [...inputs]; + newInputs[index] = value; + setInputs(newInputs); + }; + + const handleInputBlur = (index: number) => { + if (inputs[index].trim() === '') { + setInputs(prev => { + const newInputs = [...prev]; + newInputs[index] = ''; + return newInputs; + }); + } else if (inputs[index].trim() !== '' && index === inputs.length - 1) { + setInputs(prev => { + const newInputs = [...prev, '']; + newInputs[index] = inputs[index].trim(); + return newInputs; + }); + } + }; + + const getNonEmptyInputs = () => { + return inputs.filter(input => input.trim() !== ''); + }; + + useEffect(() => { + if (inputRefs.current.length > 0) { + const lastInput = inputRefs.current[inputRefs.current.length - 1]; + if (lastInput) { + lastInput.scrollIntoView({behavior: 'smooth', block: 'center'}); + } + } + }, [inputs]); + + return { + inputs, + inputRefs, + handleInputChange, + handleInputBlur, + getNonEmptyInputs, + }; +}; + +export default useDynamicInput; diff --git a/client/src/hooks/useDynamicInputPairs.tsx b/client/src/hooks/useDynamicInputPairs.tsx new file mode 100644 index 000000000..db5347dd8 --- /dev/null +++ b/client/src/hooks/useDynamicInputPairs.tsx @@ -0,0 +1,42 @@ +import {useEffect, useRef, useState} from 'react'; + +import {PurchaseInformation} from '@pages/Event/Event'; + +const useDynamicInputPairs = () => { + const [inputPairs, setInputPairs] = useState<PurchaseInformation[]>([{name: '', price: 0}]); + const inputRefs = useRef<(HTMLInputElement | null)[]>([]); + + const handleInputChange = (index: number, field: 'name' | 'price', value: string) => { + const newInputPairs = [...inputPairs]; + newInputPairs[index] = { + ...newInputPairs[index], + [field]: field === 'price' ? parseFloat(value) : value, + }; + setInputPairs(newInputPairs); + }; + + const handleInputBlur = (index: number) => { + const currentPair = inputPairs[index]; + if (currentPair.name.trim() === '' && currentPair.price === 0) { + setInputPairs(prev => prev.filter((_, i) => i !== index)); + } else if (currentPair.name.trim() !== '' && currentPair.price !== 0 && index === inputPairs.length - 1) { + setInputPairs(prev => [...prev, {name: '', price: 0}]); + } + }; + + useEffect(() => { + if (inputRefs.current.length > 0) { + const lastInputPair = inputRefs.current.slice(-2); + lastInputPair.forEach(ref => ref?.scrollIntoView({behavior: 'smooth', block: 'center'})); + } + }, [inputPairs]); + + return { + inputPairs, + inputRefs, + handleInputChange, + handleInputBlur, + }; +}; + +export default useDynamicInputPairs; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx index bdd1e3cf2..589317f7d 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -1,9 +1,12 @@ import {useEffect, useState} from 'react'; + import {MemberReport} from 'types/stepList'; -import memberReportSearchJsonList from '@mocks/memberReportSearchList.json'; import {requestMemberReportList} from '@apis/request/report'; + import {WithEventId} from '@apis/withEventId.type'; +import memberReportSearchJsonList from '@mocks/memberReportSearchList.json'; + const memberReportSearchMockList = memberReportSearchJsonList as MemberReport[]; type UseSearchMemberReportListParams = { diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx index 842794f0f..9adb2d684 100644 --- a/client/src/hooks/useStepList/useStepList.tsx +++ b/client/src/hooks/useStepList/useStepList.tsx @@ -1,5 +1,7 @@ import {PropsWithChildren, createContext, useEffect, useState} from 'react'; + import {BillAction, MemberType, StepList} from 'types/stepList'; + import stepListJsonData from '@mocks/stepList.json'; const stepListMockData = stepListJsonData as StepList; diff --git a/client/src/index.css b/client/src/index.css index 936bdd319..8ebdb5ba8 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -7,3 +7,9 @@ body { section { width: 100%; } + +#root { + display: flex; + flex-direction: column; + height: 100%; +} diff --git a/client/src/pages/CreateEvent/CreateEvent.tsx b/client/src/pages/CreateEvent/CreateEvent.tsx index eb25c1faf..9697200e0 100644 --- a/client/src/pages/CreateEvent/CreateEvent.tsx +++ b/client/src/pages/CreateEvent/CreateEvent.tsx @@ -1,5 +1,6 @@ import {useState} from 'react'; import {useNavigate} from 'react-router-dom'; + import {ROUTER_URLS} from '@constants/routerUrls'; const CreateEvent = () => { diff --git a/client/src/pages/Event/Event.style.ts b/client/src/pages/Event/Event.style.ts index 517466c92..15e2443b4 100644 --- a/client/src/pages/Event/Event.style.ts +++ b/client/src/pages/Event/Event.style.ts @@ -1,17 +1,9 @@ import {css} from '@emotion/react'; -export const orderHeaderStyle = css` - display: flex; - justify-content: space-between; - align-items: center; - - width: 100%; -`; - -export const orderFooterStyle = css` - display: flex; - justify-content: space-between; - align-items: center; - - width: 100%; -`; +export const ReceiptStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '8px', + padding: '0 8px', + }); diff --git a/client/src/pages/Event/Event.tsx b/client/src/pages/Event/Event.tsx index bded81860..edc95d5b4 100644 --- a/client/src/pages/Event/Event.tsx +++ b/client/src/pages/Event/Event.tsx @@ -1,93 +1,105 @@ import {useState} from 'react'; -import {useParams} from 'react-router-dom'; +import {TopNav, Title, FixedButton, StepItem, InOutItem, MainLayout} from 'haengdong-design'; -import {SetInitialParticipants} from '@components/Modal/SetInitialParticipants'; -import {SetActionModalContent} from '@components/Modal/SetActionModalContent'; +import {SetActionModalContent, SetInitialParticipants} from '@components/Modal'; -import {Modal} from '@components/Modal'; - -import {orderHeaderStyle} from './Event.style'; +import {ReceiptStyle} from './Event.style'; export type PurchaseInformation = { name: string; price: number; }; -type ParticipantType = { +export type InOutType = '늦참' | '탈주'; + +export type ParticipantType = { name: string; - type: '늦참' | '탈주'; + type: InOutType; }; -const Event = () => { - const {eventId} = useParams(); - const [open, setOpen] = useState(false); - const [participants, setParticipants] = useState<string[]>([]); - const [order, setOrder] = useState(0); +interface ModalRenderingProps { + participants: string[]; + openBottomSheet: boolean; + + setOrder: React.Dispatch<React.SetStateAction<number>>; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setParticipants: React.Dispatch<React.SetStateAction<string[]>>; +} - const [purchaseInformation, setPurchaseInformation] = useState<(PurchaseInformation | ParticipantType)[]>([ - { - name: '', - price: 0, - } as PurchaseInformation, - ]); +const ModalRendering = ({ + participants, + setOrder, + setOpenBottomSheet, + setParticipants, + openBottomSheet, +}: ModalRenderingProps) => { + switch (participants.length) { + case 0: + return ( + <SetInitialParticipants + setParticipants={setParticipants} + setOpenBottomSheet={setOpenBottomSheet} + openBottomSheet={openBottomSheet} + /> + ); - const setParticipantsAndModalClose = (participants: string[]) => { - setParticipants(participants); - setOrder(1); - setOpen(false); - }; + default: + return ( + <SetActionModalContent + setOrder={setOrder} + participants={participants} + setOpenBottomSheet={setOpenBottomSheet} + openBottomSheet={openBottomSheet} + /> + ); + } +}; + +const Event = () => { + const [openBottomSheet, setOpenBottomSheet] = useState(false); + const [participants, setParticipants] = useState<string[]>([]); + const [order, setOrder] = useState<number>(0); return ( - <section> - <h1>{eventId}</h1> - <h3>“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요.</h3> - {order > 0 && ( - <article> - <header css={orderHeaderStyle}> - <h4>{`${order}차`}</h4> - <p>{`${participants.length}명`}</p> - </header> - {purchaseInformation.map((information, index) => ( - <section key={index} style={{padding: '10px'}}> - {'type' in information ? ( - <> - <h5> - {information.name} {information.type}입니다. - </h5> - </> - ) : ( - <> - <h5>{information.name}</h5> - <p>{information.price.toLocaleString()}원</p> - </> - )} - </section> - ))} - {/* <footer css={orderFooterStyle}> - <h6>총액</h6> - <p>{purchaseInformation.reduce((total, info) => 'price' in info ? total + info.price : total, 0).toLocaleString()}원</p> - </footer> */} - </article> - )} - <button onClick={() => setOpen(prev => !prev)}> - {participants.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} - </button> - {open && ( - <Modal onClose={() => setOpen(false)}> - {participants.length === 0 ? ( - <SetInitialParticipants setParticipantsAndModalClose={setParticipantsAndModalClose} /> - ) : ( - <SetActionModalContent - setOpen={setOpen} - participants={participants} - setParticipants={setParticipants} - purchaseInformation={purchaseInformation} - setPurchaseInformation={setPurchaseInformation} + <MainLayout backgroundColor="gray"> + <TopNav navType={'home'} /> + <Title + title="행동대장 야유회" + description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." + // TODO: (@soha) price 생성시 총 가격 생기기 + price={20000} + /> + <section css={ReceiptStyle}> + {order > 0 && ( + // TODO: (@soha) StepList로 변경하기 + // TODO: (@soha) order가 0일때 기본 Step 뜨기 + <> + <StepItem + name={`${order}차`} + personCount={participants.length} + bills={[ + {name: 'QWER', price: 12000, hasDragHandle: true}, + {name: '배고파요', price: 12000, hasDragHandle: true}, + ]} /> - )} - </Modal> - )} - </section> + <InOutItem names={['감자', '고구마']} inOutType={'OUT'} hasDragHandle={true} /> + </> + )} + {/* TODO: (@soha) 추후 버튼 width 화면에 맞게 수정 */} + <FixedButton + children={participants.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} + onClick={() => setOpenBottomSheet(prev => !prev)} + /> + {openBottomSheet && + ModalRendering({ + participants, + setOrder, + setParticipants, + setOpenBottomSheet, + openBottomSheet, + })} + </section> + </MainLayout> ); }; diff --git a/client/src/pages/Home/HomeContent.tsx b/client/src/pages/Home/HomeContent.tsx index c13829222..171729636 100644 --- a/client/src/pages/Home/HomeContent.tsx +++ b/client/src/pages/Home/HomeContent.tsx @@ -1,7 +1,8 @@ +import {Tab, Tabs, Title} from 'haengdong-design'; + import MemberReportList from '@components/MemberReportList/MemberReportList'; import StepList from '@components/StepList/StepList'; import {useStepList} from '@hooks/useStepList/useStepList'; -import {Tab, Tabs, Title} from 'haengdong-design'; const HomeContent = () => { const {getTotalPrice} = useStepList(); diff --git a/client/src/pages/Home/HomeLayout.tsx b/client/src/pages/Home/HomeLayout.tsx index c204f3da1..8cae579d6 100644 --- a/client/src/pages/Home/HomeLayout.tsx +++ b/client/src/pages/Home/HomeLayout.tsx @@ -1,4 +1,5 @@ import {Flex, MainLayout, TopNav} from 'haengdong-design'; + import {StepListProvider} from '@hooks/useStepList/useStepList'; import HomeContent from './HomeContent'; From c85f71eb60c1e0791d44935cf53901656c957dab Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:10:58 +0900 Subject: [PATCH 085/273] =?UTF-8?q?fix:=20=EC=98=88=EC=99=B8=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A0=95=EC=9D=98=ED=95=9C=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=EB=A5=BC=20=EA=BA=BC=EB=82=B4=EC=A7=80=20=EB=AA=BB?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?(#111)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/server/haengdong/exception/ErrorResponse.java | 4 ++-- .../haengdong/exception/GlobalExceptionHandler.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java index 5d1e33c9b..c797b811a 100644 --- a/server/src/main/java/server/haengdong/exception/ErrorResponse.java +++ b/server/src/main/java/server/haengdong/exception/ErrorResponse.java @@ -4,7 +4,7 @@ public record ErrorResponse( String message ) { - public static ErrorResponse of(HaengdongErrorCode errorCode) { - return new ErrorResponse(errorCode.getMessage()); + public static ErrorResponse of(String message) { + return new ErrorResponse(message); } } diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java index 7985721cd..bb3138cc7 100644 --- a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java +++ b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java @@ -15,7 +15,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public ResponseEntity<ErrorResponse> haengdongException() { return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.BAD_REQUEST)); + .body(ErrorResponse.of(HaengdongErrorCode.BAD_REQUEST.getMessage())); } @ExceptionHandler(MethodArgumentNotValidException.class) @@ -25,19 +25,19 @@ public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(Metho .collect(Collectors.joining(", ")); return ResponseEntity.badRequest() - .body(new ErrorResponse(errorMessage)); + .body(ErrorResponse.of(errorMessage)); } @ExceptionHandler(HaengdongException.class) public ResponseEntity<ErrorResponse> haengdongException(HaengdongException e) { return ResponseEntity.status(e.getStatusCode()) - .body(ErrorResponse.of(e.getErrorCode())); + .body(ErrorResponse.of(e.getMessage())); } @ExceptionHandler(Exception.class) public ResponseEntity<ErrorResponse> handleException(Exception e) { log.error(e.getMessage(), e); return ResponseEntity.internalServerError() - .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR)); + .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR.getMessage())); } } From 97bd3e6a59aaccc861663864e2dca6209dbe8916 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:23:56 +0900 Subject: [PATCH 086/273] =?UTF-8?q?feat:=20=ED=8D=BC=EB=B8=94=EB=A6=AC?= =?UTF-8?q?=EC=8B=B1=EB=90=9C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A7=A4?= =?UTF-8?q?=EB=81=84=EB=9F=BD=EA=B2=8C=20=EC=97=B0=EA=B2=B0=20(#114)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 --- client/package-lock.json | 8 ++++---- client/package.json | 2 +- client/src/constants/routerUrls.ts | 2 +- client/src/pages/Create/Complete.tsx | 2 +- client/src/pages/Create/Name.tsx | 2 +- client/src/pages/Event/Event.tsx | 24 ++++++++++-------------- 6 files changed, 18 insertions(+), 22 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 4ee33aaae..8bc10061f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.28", + "haengdong-design": "^0.1.29", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -6274,9 +6274,9 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.28", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.28.tgz", - "integrity": "sha512-czidJMyGWLbdfrabj3SARWMS3fB26c1Fg43XxS7ognTc3mG37BqRe6coPKueU0onB4IoB+xhYZcmHJKIZwukLw==", + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.29.tgz", + "integrity": "sha512-yBxmS8PBYOMG6scumzeey2LQMSvlB5kqyd/pIP/ID4WRkvwVo8ScFYO6iV8odFINt4I1Dx2aC/itdk74Pyvv4A==", "dependencies": { "@emotion/react": "^11.11.4", "@svgr/webpack": "^8.1.0", diff --git a/client/package.json b/client/package.json index 350a884ed..fed2f5249 100644 --- a/client/package.json +++ b/client/package.json @@ -47,7 +47,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.28", + "haengdong-design": "^0.1.29", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index f0a910d5b..228e25c7c 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -3,6 +3,6 @@ export const ROUTER_URLS = { eventCreateName: '/event/create/name', eventCreateComplete: '/event/create/complete', event: '/event', - eventManage: '/event/:eventId', + eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', }; diff --git a/client/src/pages/Create/Complete.tsx b/client/src/pages/Create/Complete.tsx index c2f499cb6..b4496d0cd 100644 --- a/client/src/pages/Create/Complete.tsx +++ b/client/src/pages/Create/Complete.tsx @@ -29,7 +29,7 @@ const CompleteCreateEvent = () => { description="행사가 성공적으로 개시됐어요 :) 행사 링크를 통해서 참여자 관리가 가능해요. 관리를 위해서 행사 관리 링크를 보관해 주세요." /> - <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${url}`)}>관리 페이지로 이동</FixedButton> + <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${url}/admin`)}>관리 페이지로 이동</FixedButton> </MainLayout> ); }; diff --git a/client/src/pages/Create/Name.tsx b/client/src/pages/Create/Name.tsx index ee847e258..8a1261662 100644 --- a/client/src/pages/Create/Name.tsx +++ b/client/src/pages/Create/Name.tsx @@ -27,7 +27,7 @@ const CreateEvent = () => { onChange={event => setEventTitle(event.target.value)} placeholder="ex) 행동대장 야유회" /> - <FixedButton>행동 개시!</FixedButton> + <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateComplete)}>행동 개시!</FixedButton> </form> </MainLayout> ); diff --git a/client/src/pages/Event/Event.tsx b/client/src/pages/Event/Event.tsx index edc95d5b4..79c1f9950 100644 --- a/client/src/pages/Event/Event.tsx +++ b/client/src/pages/Event/Event.tsx @@ -1,6 +1,10 @@ import {useState} from 'react'; import {TopNav, Title, FixedButton, StepItem, InOutItem, MainLayout} from 'haengdong-design'; +import StepList from '@components/StepList/StepList'; +import {useStepList} from '@hooks/useStepList/useStepList'; +import {StepListProvider} from '@hooks/useStepList/useStepList'; + import {SetActionModalContent, SetInitialParticipants} from '@components/Modal'; import {ReceiptStyle} from './Event.style'; @@ -60,30 +64,22 @@ const Event = () => { const [participants, setParticipants] = useState<string[]>([]); const [order, setOrder] = useState<number>(0); + const {getTotalPrice} = useStepList(); + return ( <MainLayout backgroundColor="gray"> <TopNav navType={'home'} /> <Title title="행동대장 야유회" description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." - // TODO: (@soha) price 생성시 총 가격 생기기 - price={20000} + price={getTotalPrice()} /> <section css={ReceiptStyle}> {order > 0 && ( - // TODO: (@soha) StepList로 변경하기 // TODO: (@soha) order가 0일때 기본 Step 뜨기 - <> - <StepItem - name={`${order}차`} - personCount={participants.length} - bills={[ - {name: 'QWER', price: 12000, hasDragHandle: true}, - {name: '배고파요', price: 12000, hasDragHandle: true}, - ]} - /> - <InOutItem names={['감자', '고구마']} inOutType={'OUT'} hasDragHandle={true} /> - </> + <StepListProvider> + <StepList /> + </StepListProvider> )} {/* TODO: (@soha) 추후 버튼 width 화면에 맞게 수정 */} <FixedButton From 3cb6872a88a39a1915c81488329729d8fc51c6a5 Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:17:29 +0900 Subject: [PATCH 087/273] =?UTF-8?q?refactor:=20=EC=9D=B8=EC=9B=90=20?= =?UTF-8?q?=EB=B3=80=EB=8F=99=20=EC=9A=94=EC=B2=AD=20=ED=98=95=ED=83=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#117)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/MemberActionSaveRequest.java | 10 ---------- .../request/MemberActionsSaveRequest.java | 12 +++++++++--- .../presentation/MemberActionControllerTest.java | 11 ++++------- 3 files changed, 13 insertions(+), 20 deletions(-) delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionSaveRequest.java diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionSaveRequest.java deleted file mode 100644 index a69c51d41..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberActionSaveRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.request; - -import server.haengdong.application.request.MemberActionSaveAppRequest; - -public record MemberActionSaveRequest(String name, String status) { - - public MemberActionSaveAppRequest toAppRequest() { - return new MemberActionSaveAppRequest(name, status); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java index bfe80f0ee..0b3fcebae 100644 --- a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java +++ b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java @@ -1,14 +1,20 @@ package server.haengdong.presentation.request; +import jakarta.validation.constraints.NotBlank; import java.util.List; import server.haengdong.application.request.MemberActionSaveAppRequest; import server.haengdong.application.request.MemberActionsSaveAppRequest; -public record MemberActionsSaveRequest(List<MemberActionSaveRequest> actions) { +public record MemberActionsSaveRequest( + List<String> members, + + @NotBlank + String status +) { public MemberActionsSaveAppRequest toAppRequest() { - List<MemberActionSaveAppRequest> appRequests = actions.stream() - .map(MemberActionSaveRequest::toAppRequest) + List<MemberActionSaveAppRequest> appRequests = members.stream() + .map(name -> new MemberActionSaveAppRequest(name, status)) .toList(); return new MemberActionsSaveAppRequest(appRequests); diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java index be8b89182..ad8787cc6 100644 --- a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java +++ b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java @@ -20,7 +20,6 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import server.haengdong.application.MemberActionService; import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionSaveRequest; import server.haengdong.presentation.request.MemberActionsSaveRequest; @WebMvcTest(MemberActionController.class) @@ -38,11 +37,8 @@ class MemberActionControllerTest { @DisplayName("참여자 행동을 추가한다.") @Test void saveMemberActionTest() throws Exception { - MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest(List.of( - new MemberActionSaveRequest("웨디", "IN"), - new MemberActionSaveRequest("소하", "IN"), - new MemberActionSaveRequest("토다리", "IN"), - new MemberActionSaveRequest("쿠키", "IN"))); + MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( + List.of("웨디", "소하", "토다리", "쿠키"), "IN"); String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); @@ -56,7 +52,8 @@ void saveMemberActionTest() throws Exception { @DisplayName("현재 참여 인원을 조회합니다.") @Test void getCurrentMembers() throws Exception { - List<CurrentMemberAppResponse> currentMemberAppResponses = List.of(new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); + List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( + new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); From d943520138de321bfd74211348a5fd2599fe74b5 Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Thu, 25 Jul 2024 18:05:13 +0900 Subject: [PATCH 088/273] =?UTF-8?q?=08feat:=20=EC=95=A1=EC=85=98=20?= =?UTF-8?q?=EC=9D=B4=EB=A0=A5=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#76)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> --- .../haengdong/application/EventService.java | 52 +++++++++++++++ .../response/ActionAppResponse.java | 54 ++++++++++++++++ .../presentation/EventController.java | 8 +++ .../presentation/response/ActionResponse.java | 20 ++++++ .../response/ActionsResponse.java | 28 +++++++++ .../presentation/response/StepResponse.java | 63 +++++++++++++++++++ .../application/EventServiceTest.java | 51 +++++++++++++++ .../response/StepResponseTest.java | 57 +++++++++++++++++ 8 files changed, 333 insertions(+) create mode 100644 server/src/main/java/server/haengdong/application/response/ActionAppResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/StepResponse.java create mode 100644 server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index dee023fbc..94c9dbda1 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -1,10 +1,18 @@ package server.haengdong.application; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.ActionAppResponse; import server.haengdong.application.response.EventAppResponse; import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; import server.haengdong.domain.event.EventTokenProvider; @@ -17,6 +25,8 @@ public class EventService { private final EventRepository eventRepository; private final EventTokenProvider eventTokenProvider; + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; public EventAppResponse saveEvent(EventAppRequest request) { String token = eventTokenProvider.createToken(); @@ -32,4 +42,46 @@ public EventDetailAppResponse findEvent(String token) { return EventDetailAppResponse.of(event); } + + public List<ActionAppResponse> findActions(String token) { + Event event = eventRepository.findByToken(token).orElseThrow(() -> new IllegalArgumentException("")); + + List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() + .sorted(Comparator.comparing(BillAction::getSequence)).toList(); + List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event).stream() + .sorted(Comparator.comparing(MemberAction::getSequence)).toList(); + + return getActionAppResponses(billActions, memberActions); + } + + private List<ActionAppResponse> getActionAppResponses( + List<BillAction> billActions, + List<MemberAction> memberActions + ) { + int billActionIndex = 0; + int memberActionIndex = 0; + List<ActionAppResponse> actionAppResponses = new ArrayList<>(); + + while (billActionIndex < billActions.size() && memberActionIndex < memberActions.size()) { + BillAction billAction = billActions.get(billActionIndex); + MemberAction memberAction = memberActions.get(memberActionIndex); + if (billAction.getSequence() < memberAction.getSequence()) { + actionAppResponses.add(ActionAppResponse.of(billAction)); + billActionIndex++; + } else { + actionAppResponses.add(ActionAppResponse.of(memberAction)); + memberActionIndex++; + } + } + while (billActionIndex < billActions.size()) { + BillAction billAction = billActions.get(billActionIndex++); + actionAppResponses.add(ActionAppResponse.of(billAction)); + } + while (memberActionIndex < memberActions.size()) { + MemberAction memberAction = memberActions.get(memberActionIndex++); + actionAppResponses.add(ActionAppResponse.of(memberAction)); + } + + return actionAppResponses; + } } diff --git a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java new file mode 100644 index 000000000..a1abcc35b --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java @@ -0,0 +1,54 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; + +public record ActionAppResponse( + Long actionId, + String name, + Long price, + Long sequence, + ActionType actionType +) { + + public static ActionAppResponse of(BillAction billAction) { + return new ActionAppResponse( + billAction.getAction().getId(), + billAction.getTitle(), + billAction.getPrice(), + billAction.getSequence(), + ActionType.BILL + ); + } + + public static ActionAppResponse of(MemberAction memberAction) { + MemberActionStatus status = memberAction.getStatus(); + + return new ActionAppResponse( + memberAction.getAction().getId(), + memberAction.getMemberName(), + null, + memberAction.getSequence(), + ActionType.of(status) + ); + } + + public String actionTypeName() { + return actionType.name(); + } + + public enum ActionType { + BILL, + IN, + OUT, + ; + + private static ActionType of(MemberActionStatus memberActionStatus) { + if (MemberActionStatus.IN == memberActionStatus) { + return IN; + } + return OUT; + } + } +} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java index 260253e8b..9fbe098ce 100644 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -12,6 +12,7 @@ import server.haengdong.presentation.request.EventSaveRequest; import server.haengdong.presentation.response.EventDetailResponse; import server.haengdong.presentation.response.EventResponse; +import server.haengdong.presentation.response.StepResponse; @RequiredArgsConstructor @RestController @@ -32,4 +33,11 @@ public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") St return ResponseEntity.ok(eventDetailResponse); } + + @GetMapping("/api/events/{eventId}/actions") + public ResponseEntity<StepResponse> findActions(@PathVariable("eventId") String token) { + StepResponse stepResponse = StepResponse.of(eventService.findActions(token)); + + return ResponseEntity.ok(stepResponse); + } } diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java new file mode 100644 index 000000000..a58e60186 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java @@ -0,0 +1,20 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.ActionAppResponse; + +public record ActionResponse( + Long actionId, + String name, + Long price, + Long sequence +) { + + public static ActionResponse of(ActionAppResponse actionAppResponse) { + return new ActionResponse( + actionAppResponse.actionId(), + actionAppResponse.name(), + actionAppResponse.price(), + actionAppResponse.sequence() + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java new file mode 100644 index 000000000..188c48dc9 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java @@ -0,0 +1,28 @@ +package server.haengdong.presentation.response; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import server.haengdong.application.response.ActionAppResponse; + +public record ActionsResponse( + String type, + String stepName, + Set<String> members, + List<ActionResponse> actions +) { + + public static ActionsResponse of(List<ActionAppResponse> actions, Set<String> members) { + List<ActionResponse> actionResponses = actions.stream() + .map(ActionResponse::of) + .toList(); + + String actionType = actions.get(0).actionTypeName(); + return new ActionsResponse( + actionType, + null, + new HashSet<>(members), + actionResponses + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java new file mode 100644 index 000000000..76f92ad53 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java @@ -0,0 +1,63 @@ +package server.haengdong.presentation.response; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import server.haengdong.application.response.ActionAppResponse; + +public record StepResponse( + List<ActionsResponse> steps +) { + + public static StepResponse of(List<ActionAppResponse> actions) { + List<ActionsResponse> actionsResponse = new ArrayList<>(); + Set<String> members = new HashSet<>(); + ActionAppResponse firstAction = getFirstAction(actions); + List<ActionAppResponse> group = new ArrayList<>(); + group.add(firstAction); + String currentActionType = firstAction.actionTypeName(); + members.add(firstAction.name()); + + for (int i = 1; i < actions.size(); i++) { + ActionAppResponse action = actions.get(i); + String typeName = action.actionTypeName(); + if (currentActionType.equals(typeName)) { + if (typeName.equals("IN")) { + members.add(action.name()); + } + if (typeName.equals("OUT")) { + members.remove(action.name()); + } + group.add(action); + continue; + } + if (currentActionType.equals("BILL")) { + actionsResponse.add(ActionsResponse.of(group, members)); + } else { + actionsResponse.add(ActionsResponse.of(group, Set.of())); + } + currentActionType = typeName; + group.clear(); + if (typeName.equals("IN")) { + members.add(action.name()); + } + if (typeName.equals("OUT")) { + members.remove(action.name()); + } + group.add(action); + } + + if (currentActionType.equals("BILL")) { + actionsResponse.add(ActionsResponse.of(group, members)); + } else { + actionsResponse.add(ActionsResponse.of(group, null)); + } + + return new StepResponse(actionsResponse); + } + + private static ActionAppResponse getFirstAction(List<ActionAppResponse> actions) { + return actions.get(0); + } +} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java index 31b1c650e..5a3e8bce3 100644 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -2,8 +2,10 @@ import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; import static org.mockito.BDDMockito.given; +import java.util.List; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,8 +13,16 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.ActionAppResponse; import server.haengdong.application.response.EventAppResponse; import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberActionStatus; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; import server.haengdong.domain.event.EventTokenProvider; @@ -29,8 +39,20 @@ class EventServiceTest { @Autowired private EventRepository eventRepository; + @Autowired + private ActionRepository actionRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + @AfterEach void tearDown() { + billActionRepository.deleteAllInBatch(); + memberActionRepository.deleteAllInBatch(); + actionRepository.deleteAllInBatch(); eventRepository.deleteAllInBatch(); } @@ -56,4 +78,33 @@ void findEventTest() { assertThat(eventDetailAppResponse.eventName()).isEqualTo("행동대장 회식"); } + + @DisplayName("행사에 속한 모든 액션을 조회한다.") + @Test + void findActionsTest() { + Event event = new Event("행동대장 회식", "웨디_토큰"); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + Action action1 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "쿠키", MemberActionStatus.IN, 1L); + Action action2 = new Action(event, 3L); + BillAction billAction = new BillAction(action2, "뽕나무쟁이족발", 30000L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction, memberAction1)); + billActionRepository.save(billAction); + + List<ActionAppResponse> actionAppResponses = eventService.findActions("웨디_토큰"); + + assertThat(actionAppResponses).hasSize(3) + .extracting(ActionAppResponse::actionId, + ActionAppResponse::name, + ActionAppResponse::price, + ActionAppResponse::sequence, + ActionAppResponse::actionTypeName) + .containsExactly( + tuple(1L, "토다리", null, 1L, "IN"), + tuple(2L, "쿠키", null, 2L, "IN"), + tuple(3L, "뽕나무쟁이족발", 30000L, 3L, "BILL") + ); + } } diff --git a/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java b/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java new file mode 100644 index 000000000..aac78691c --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java @@ -0,0 +1,57 @@ +package server.haengdong.presentation.response; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.ActionAppResponse.ActionType; + +@SpringBootTest +class StepResponseTest { + + @Autowired + private ObjectMapper objectMapper; + + @DisplayName("") + @Test + void test() throws JsonProcessingException { + List<ActionAppResponse> actionAppResponse = new ArrayList<>(); + + // IN actions + ActionAppResponse actionAppResponse1 = new ActionAppResponse(3L, "망쵸", null, 3L, ActionType.IN); + actionAppResponse.add(actionAppResponse1); + ActionAppResponse actionAppResponse2 = new ActionAppResponse(4L, "백호", null, 4L, ActionType.IN); + actionAppResponse.add(actionAppResponse2); + + // BILL step 1 + ActionAppResponse actionAppResponse3 = new ActionAppResponse(1L, "감자탕", 10000L, 1L, ActionType.BILL); + actionAppResponse.add(actionAppResponse3); + ActionAppResponse actionAppResponse4 = new ActionAppResponse(2L, "인생네컷", 10000L, 2L, ActionType.BILL); + actionAppResponse.add(actionAppResponse4); + + // IN actions + ActionAppResponse actionAppResponse5 = new ActionAppResponse(5L, "소하", null, 5L, ActionType.IN); + actionAppResponse.add(actionAppResponse5); + ActionAppResponse actionAppResponse6 = new ActionAppResponse(6L, "웨디", null, 6L, ActionType.IN); + actionAppResponse.add(actionAppResponse6); + + // OUT actions + ActionAppResponse actionAppResponse7 = new ActionAppResponse(7L, "망쵸", null, 7L, ActionType.OUT); + actionAppResponse.add(actionAppResponse7); + ActionAppResponse actionAppResponse8 = new ActionAppResponse(8L, "백호", null, 8L, ActionType.OUT); + actionAppResponse.add(actionAppResponse8); + + // BILL step 2 + ActionAppResponse actionAppResponse9 = new ActionAppResponse(9L, "노래방", 20000L, 10L, ActionType.BILL); + actionAppResponse.add(actionAppResponse9); + + // StepResponse creation + StepResponse stepResponse = StepResponse.of(actionAppResponse); + System.out.println("stepResponse = " + stepResponse); + } +} From 74de2a68ea29560f781a195eb1b2ebe4800071a9 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 25 Jul 2024 18:06:07 +0900 Subject: [PATCH 089/273] =?UTF-8?q?chore:=20frontend=20yml=20lint=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=95=20=EC=88=98=EC=A0=95=20(#120)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/bug-template.md | 8 ++++++++ ...frontend-pll-request.yml => frontend-pull-request.yml} | 0 client/package.json | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) rename .github/workflows/{frontend-pll-request.yml => frontend-pull-request.yml} (100%) diff --git a/.github/ISSUE_TEMPLATE/bug-template.md b/.github/ISSUE_TEMPLATE/bug-template.md index e14ce93b3..4fab11f91 100644 --- a/.github/ISSUE_TEMPLATE/bug-template.md +++ b/.github/ISSUE_TEMPLATE/bug-template.md @@ -12,6 +12,14 @@ assignees: '' ## 🚨 버그 발생 상황 최대한 상세하게 작성해주세요. +### as-is + +현재 상황에 대해서 알려주세요. + +### to-be + +구현이 된 후 상황을 예상해 주세요. + ## 예상 결과 예상했던 정상적인 결과가 어떤 것인지 설명해주세요. diff --git a/.github/workflows/frontend-pll-request.yml b/.github/workflows/frontend-pull-request.yml similarity index 100% rename from .github/workflows/frontend-pll-request.yml rename to .github/workflows/frontend-pull-request.yml diff --git a/client/package.json b/client/package.json index fed2f5249..3c66313b4 100644 --- a/client/package.json +++ b/client/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "webpack serve ", "build": "webpack --mode production", - "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}' --fix", + "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" }, "keywords": [], @@ -56,4 +56,4 @@ "npm": ">=10.7.0", "node": ">=20.15.1" } -} +} \ No newline at end of file From b9870edba09577c9d880c6ac32d04a92f90a84fb Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Thu, 25 Jul 2024 18:24:30 +0900 Subject: [PATCH 090/273] =?UTF-8?q?fix:=20=EC=95=A1=EC=85=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A0=A5=EC=9D=B4=20=EC=97=86=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EB=B9=88=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?(#122)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/haengdong/presentation/response/StepResponse.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java index 76f92ad53..354f019df 100644 --- a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java +++ b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java @@ -11,6 +11,9 @@ public record StepResponse( ) { public static StepResponse of(List<ActionAppResponse> actions) { + if (actions.isEmpty()) { + return new StepResponse(List.of()); + } List<ActionsResponse> actionsResponse = new ArrayList<>(); Set<String> members = new HashSet<>(); ActionAppResponse firstAction = getFirstAction(actions); From ff2632dccbfa63a980cc3cdb1bb98854e055278d Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Thu, 25 Jul 2024 19:08:42 +0900 Subject: [PATCH 091/273] =?UTF-8?q?=08fix:=20=EC=95=A1=EC=85=98=20?= =?UTF-8?q?=EC=9D=B4=EB=A0=A5=20=EC=A1=B0=ED=9A=8C=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#124)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 --- .../java/server/haengdong/application/EventService.java | 6 +++++- .../server/haengdong/domain/action/MemberActionStatus.java | 5 ++++- .../haengdong/presentation/response/StepResponse.java | 4 ---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index 94c9dbda1..9ad502606 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -5,6 +5,7 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import server.haengdong.application.request.EventAppRequest; import server.haengdong.application.response.ActionAppResponse; import server.haengdong.application.response.EventAppResponse; @@ -20,6 +21,7 @@ import server.haengdong.exception.HaengdongException; @RequiredArgsConstructor +@Transactional(readOnly = true) @Service public class EventService { @@ -28,6 +30,7 @@ public class EventService { private final BillActionRepository billActionRepository; private final MemberActionRepository memberActionRepository; + @Transactional public EventAppResponse saveEvent(EventAppRequest request) { String token = eventTokenProvider.createToken(); Event event = request.toEvent(token); @@ -44,7 +47,8 @@ public EventDetailAppResponse findEvent(String token) { } public List<ActionAppResponse> findActions(String token) { - Event event = eventRepository.findByToken(token).orElseThrow(() -> new IllegalArgumentException("")); + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() .sorted(Comparator.comparing(BillAction::getSequence)).toList(); diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java index afcb31337..0a20817fd 100644 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java @@ -1,6 +1,8 @@ package server.haengdong.domain.action; import java.util.Arrays; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; public enum MemberActionStatus { IN, @@ -11,6 +13,7 @@ public static MemberActionStatus of(String status) { return Arrays.stream(MemberActionStatus.values()) .filter(s -> s.name().equals(status)) .findFirst() - .orElseThrow(() -> new IllegalArgumentException("Invalid status: " + status)); + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + "존재하지 않는 인원 변동 액션입니다.")); } } diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java index 354f019df..54b2b06b9 100644 --- a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java +++ b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java @@ -37,8 +37,6 @@ public static StepResponse of(List<ActionAppResponse> actions) { } if (currentActionType.equals("BILL")) { actionsResponse.add(ActionsResponse.of(group, members)); - } else { - actionsResponse.add(ActionsResponse.of(group, Set.of())); } currentActionType = typeName; group.clear(); @@ -53,8 +51,6 @@ public static StepResponse of(List<ActionAppResponse> actions) { if (currentActionType.equals("BILL")) { actionsResponse.add(ActionsResponse.of(group, members)); - } else { - actionsResponse.add(ActionsResponse.of(group, null)); } return new StepResponse(actionsResponse); From 6be91dae0550909ff3eac2c6a625f402cae20a32 Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Thu, 25 Jul 2024 19:24:48 +0900 Subject: [PATCH 092/273] =?UTF-8?q?fix:=20StepResponse=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95=20(#126)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../haengdong/presentation/response/StepResponse.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java index 54b2b06b9..a8f3877ef 100644 --- a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java +++ b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java @@ -35,9 +35,7 @@ public static StepResponse of(List<ActionAppResponse> actions) { group.add(action); continue; } - if (currentActionType.equals("BILL")) { - actionsResponse.add(ActionsResponse.of(group, members)); - } + actionsResponse.add(ActionsResponse.of(group, members)); currentActionType = typeName; group.clear(); if (typeName.equals("IN")) { @@ -48,10 +46,7 @@ public static StepResponse of(List<ActionAppResponse> actions) { } group.add(action); } - - if (currentActionType.equals("BILL")) { - actionsResponse.add(ActionsResponse.of(group, members)); - } + actionsResponse.add(ActionsResponse.of(group, members)); return new StepResponse(actionsResponse); } From 38a28f71be90d376d7b3c818067fbc80a0053b0f Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:58:09 +0900 Subject: [PATCH 093/273] =?UTF-8?q?test:=20Gradle,=20Docker=20=EC=BA=90?= =?UTF-8?q?=EC=8B=B1=EC=9D=84=20=EC=9C=84=ED=95=9C=20Feature/#121=20test?= =?UTF-8?q?=20(#128)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 --- .github/workflows/backend-pull-request.yml | 14 +++++++++++-- .github/workflows/backend-push.yml | 21 ++++++++++++++----- .../haengdong/HaengdongApplication.java | 2 ++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml index 113972929..ba6870a61 100644 --- a/.github/workflows/backend-pull-request.yml +++ b/.github/workflows/backend-pull-request.yml @@ -2,7 +2,7 @@ name: backend-pull-request on: pull_request: - branches: [ "main", "develop" ] + branches: [ "main", "develop", "feature/#121" ] paths: - 'server/**' @@ -18,6 +18,16 @@ jobs: - name: CheckOut uses: actions/checkout@v4 + - name: Gradle Caching + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Set up JDK 17 uses: actions/setup-java@v4 with: @@ -25,7 +35,7 @@ jobs: distribution: 'temurin' - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + uses: gradle/gradle-build-action@v2 - name: Test with Gradle Wrapper run: ./gradlew clean build diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml index a35eaea7b..0a3b3e43f 100644 --- a/.github/workflows/backend-push.yml +++ b/.github/workflows/backend-push.yml @@ -2,7 +2,7 @@ name: backend-push on: push: - branches: [ "main", "develop" ] + branches: [ "main", "develop", "feature/#121" ] paths: - 'server/**' @@ -25,6 +25,16 @@ jobs: token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} submodules: true + - name: Gradle Caching + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Set up JDK 17 uses: actions/setup-java@v4 with: @@ -32,7 +42,7 @@ jobs: distribution: 'temurin' - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + uses: gradle/gradle-build-action@v2 - name: Test with Gradle Wrapper run: ./gradlew test @@ -48,8 +58,9 @@ jobs: - name: Build and push run: | - docker buildx build --platform linux/arm64 -t \ - ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev --push . + docker buildx build --platform linux/arm64 --cache-from=type=registry,ref=${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev:cache \ + --cache-to=type=registry,ref=${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev:cache,mode=max \ + -t ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev --push . deploy: needs: build @@ -68,4 +79,4 @@ jobs: run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev - name: Docker run - run: sudo docker run -d -p 80:8080 --name haengdong-backend-dev haengdong/haengdong-backend-dev + run: sudo docker run -d -p 8080:8080 --name haengdong-backend-dev haengdong/haengdong-backend-dev diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java index 31b6e46e7..7549a9784 100644 --- a/server/src/main/java/server/haengdong/HaengdongApplication.java +++ b/server/src/main/java/server/haengdong/HaengdongApplication.java @@ -8,6 +8,8 @@ public class HaengdongApplication { public static void main(String[] args) { SpringApplication.run(HaengdongApplication.class, args); + + } } From 1d2e71a716674d15e9b0a3e19235ee0f1d1d0dc4 Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:12:21 +0900 Subject: [PATCH 094/273] =?UTF-8?q?test:=20Gardle,=20Docker=20=EC=BA=90?= =?UTF-8?q?=EC=8B=B1=EC=9D=84=20=EC=9C=84=ED=95=9C=20Feature/#121=20test2?= =?UTF-8?q?=20(#130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache --- server/src/main/java/server/haengdong/HaengdongApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java index 7549a9784..be22f61d0 100644 --- a/server/src/main/java/server/haengdong/HaengdongApplication.java +++ b/server/src/main/java/server/haengdong/HaengdongApplication.java @@ -11,5 +11,5 @@ public static void main(String[] args) { } - + } From 883884427ff87f4325acd2c5cf7e84be57adf291 Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Fri, 26 Jul 2024 13:44:42 +0900 Subject: [PATCH 095/273] revert: gradle cache, docker cache (#133) --- .github/workflows/backend-pull-request.yml | 14 ++----------- .github/workflows/backend-push.yml | 21 +++++-------------- .../haengdong/HaengdongApplication.java | 4 +--- 3 files changed, 8 insertions(+), 31 deletions(-) diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml index ba6870a61..113972929 100644 --- a/.github/workflows/backend-pull-request.yml +++ b/.github/workflows/backend-pull-request.yml @@ -2,7 +2,7 @@ name: backend-pull-request on: pull_request: - branches: [ "main", "develop", "feature/#121" ] + branches: [ "main", "develop" ] paths: - 'server/**' @@ -18,16 +18,6 @@ jobs: - name: CheckOut uses: actions/checkout@v4 - - name: Gradle Caching - uses: actions/cache@v3 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Set up JDK 17 uses: actions/setup-java@v4 with: @@ -35,7 +25,7 @@ jobs: distribution: 'temurin' - name: Setup Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - name: Test with Gradle Wrapper run: ./gradlew clean build diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml index 0a3b3e43f..a35eaea7b 100644 --- a/.github/workflows/backend-push.yml +++ b/.github/workflows/backend-push.yml @@ -2,7 +2,7 @@ name: backend-push on: push: - branches: [ "main", "develop", "feature/#121" ] + branches: [ "main", "develop" ] paths: - 'server/**' @@ -25,16 +25,6 @@ jobs: token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} submodules: true - - name: Gradle Caching - uses: actions/cache@v3 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Set up JDK 17 uses: actions/setup-java@v4 with: @@ -42,7 +32,7 @@ jobs: distribution: 'temurin' - name: Setup Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - name: Test with Gradle Wrapper run: ./gradlew test @@ -58,9 +48,8 @@ jobs: - name: Build and push run: | - docker buildx build --platform linux/arm64 --cache-from=type=registry,ref=${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev:cache \ - --cache-to=type=registry,ref=${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev:cache,mode=max \ - -t ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev --push . + docker buildx build --platform linux/arm64 -t \ + ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev --push . deploy: needs: build @@ -79,4 +68,4 @@ jobs: run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev - name: Docker run - run: sudo docker run -d -p 8080:8080 --name haengdong-backend-dev haengdong/haengdong-backend-dev + run: sudo docker run -d -p 80:8080 --name haengdong-backend-dev haengdong/haengdong-backend-dev diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java index be22f61d0..31b6e46e7 100644 --- a/server/src/main/java/server/haengdong/HaengdongApplication.java +++ b/server/src/main/java/server/haengdong/HaengdongApplication.java @@ -8,8 +8,6 @@ public class HaengdongApplication { public static void main(String[] args) { SpringApplication.run(HaengdongApplication.class, args); - - } - + } From b0f0ffa14edda42c7f846b5ff59ba267226f3384 Mon Sep 17 00:00:00 2001 From: Juhwan Kim <13selfesteem91@naver.com> Date: Fri, 26 Jul 2024 13:51:32 +0900 Subject: [PATCH 096/273] =?UTF-8?q?refactor:=20=EC=95=A0=ED=94=8C=EB=A6=AC?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=85=98=20=EB=8F=84=EC=BB=A4=20=ED=8F=AC?= =?UTF-8?q?=ED=8A=B8=20=EB=B2=88=ED=98=B8=20=EC=88=98=EC=A0=95=20(#134)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml index a35eaea7b..b22b20aa7 100644 --- a/.github/workflows/backend-push.yml +++ b/.github/workflows/backend-push.yml @@ -68,4 +68,4 @@ jobs: run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev - name: Docker run - run: sudo docker run -d -p 80:8080 --name haengdong-backend-dev haengdong/haengdong-backend-dev + run: sudo docker run -d -p 8080:8080 --name haengdong-backend-dev haengdong/haengdong-backend-dev From d056d28b0e8e2d4c19466f51088c897ccdf66d6f Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:59:06 +0900 Subject: [PATCH 097/273] =?UTF-8?q?refactor:=20Docker=20=EB=B9=8C=EB=93=9C?= =?UTF-8?q?=20=EC=84=B1=EB=8A=A5=20=EA=B0=9C=EC=84=A0=20(#138)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-push.yml | 2 +- server/Dockerfile | 10 +--------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml index b22b20aa7..be973a6a9 100644 --- a/.github/workflows/backend-push.yml +++ b/.github/workflows/backend-push.yml @@ -35,7 +35,7 @@ jobs: uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - name: Test with Gradle Wrapper - run: ./gradlew test + run: ./gradlew clean build - name: Login to Docker Hub uses: docker/login-action@v3 diff --git a/server/Dockerfile b/server/Dockerfile index 66a2d0ab3..37e37d237 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,16 +1,8 @@ -FROM gradle:7.6.1-jdk17 AS build - -WORKDIR /app - -COPY . /app - -RUN gradle clean build -x test - FROM openjdk:17-jdk-slim WORKDIR /app -COPY --from=build /app/build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar +COPY /build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar EXPOSE 8080 ENTRYPOINT ["java"] From 14be9b3d8ec17289ecf78bd1dbb63485334e9b4a Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Fri, 26 Jul 2024 14:58:45 +0900 Subject: [PATCH 098/273] =?UTF-8?q?refactor:=20=EC=B0=B8=EC=97=AC=EC=9E=90?= =?UTF-8?q?=20=EC=A0=95=EC=82=B0=20=ED=98=84=ED=99=A9=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=20=EB=A6=AC=ED=8E=99=ED=86=A0=EB=A7=81=20(#110)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 --- .../haengdong/application/ActionService.java | 13 +++---- .../domain/action/CurrentMembers.java | 39 ++++++++++++++++--- .../haengdong/domain/action/MemberAction.java | 4 ++ ...BillReports.java => MemberBillReport.java} | 36 +++++++---------- .../domain/action/CurrentMembersTest.java | 28 +++++++++++++ ...rtsTest.java => MemberBillReportTest.java} | 6 +-- 6 files changed, 88 insertions(+), 38 deletions(-) rename server/src/main/java/server/haengdong/domain/action/{MemberBillReports.java => MemberBillReport.java} (66%) rename server/src/test/java/server/haengdong/domain/action/{MemberBillReportsTest.java => MemberBillReportTest.java} (89%) diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java index b28374bb9..bda638756 100644 --- a/server/src/main/java/server/haengdong/application/ActionService.java +++ b/server/src/main/java/server/haengdong/application/ActionService.java @@ -1,6 +1,5 @@ package server.haengdong.application; -import java.util.ArrayList; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -9,7 +8,7 @@ import server.haengdong.domain.action.BillActionRepository; import server.haengdong.domain.action.MemberAction; import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberBillReports; +import server.haengdong.domain.action.MemberBillReport; import server.haengdong.domain.event.Event; import server.haengdong.domain.event.EventRepository; import server.haengdong.exception.HaengdongErrorCode; @@ -29,12 +28,10 @@ public List<MemberBillReportAppResponse> getMemberBillReports(String token) { List<BillAction> billActions = billActionRepository.findByAction_Event(event); List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); - MemberBillReports memberBillReports = MemberBillReports.createByActions(billActions, memberActions); + MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - List<MemberBillReportAppResponse> memberBillReportResponses = new ArrayList<>(); - memberBillReports.getReports().forEach( - (member, price) -> memberBillReportResponses.add(new MemberBillReportAppResponse(member, price)) - ); - return memberBillReportResponses; + return memberBillReport.getReports().entrySet().stream() + .map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue())) + .toList(); } } diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java index e6843a404..298a8a965 100644 --- a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java +++ b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java @@ -1,19 +1,23 @@ package server.haengdong.domain.action; +import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -@Getter -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) public class CurrentMembers { private final Set<String> members; + public CurrentMembers() { + this(new HashSet<>()); + } + + private CurrentMembers(Set<String> members) { + this.members = members; + } + public static CurrentMembers of(List<MemberAction> memberActions) { List<MemberAction> sortedMemberActions = getSortedMemberActions(memberActions); Set<String> members = new HashSet<>(); @@ -34,4 +38,29 @@ private static List<MemberAction> getSortedMemberActions(List<MemberAction> memb .sorted(Comparator.comparing(MemberAction::getSequence)) .toList(); } + + public CurrentMembers addMemberAction(MemberAction memberAction) { + String memberName = memberAction.getMemberName(); + + Set<String> currentMembers = new HashSet<>(members); + + if (memberAction.isIn()) { + currentMembers.add(memberName); + } else { + currentMembers.remove(memberName); + } + return new CurrentMembers(currentMembers); + } + + public boolean isEmpty() { + return members.isEmpty(); + } + + public int size() { + return members.size(); + } + + public Set<String> getMembers() { + return Collections.unmodifiableSet(members); + } } diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java index af340de3f..67387cbde 100644 --- a/server/src/main/java/server/haengdong/domain/action/MemberAction.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberAction.java @@ -43,6 +43,10 @@ public boolean isSameName(String name) { return memberName.equals(name); } + public boolean isIn() { + return status == MemberActionStatus.IN; + } + public boolean isSameStatus(MemberActionStatus memberActionStatus) { return status == memberActionStatus; } diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReports.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java similarity index 66% rename from server/src/main/java/server/haengdong/domain/action/MemberBillReports.java rename to server/src/main/java/server/haengdong/domain/action/MemberBillReport.java index aa928d2e4..dbf2b49ac 100644 --- a/server/src/main/java/server/haengdong/domain/action/MemberBillReports.java +++ b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java @@ -2,33 +2,31 @@ import static java.util.stream.Collectors.toMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.PriorityQueue; -import java.util.Set; import java.util.function.Function; import lombok.Getter; @Getter -public class MemberBillReports { +public class MemberBillReport { private final Map<String, Long> reports; - private MemberBillReports(Map<String, Long> reports) { + private MemberBillReport(Map<String, Long> reports) { this.reports = reports; } - public static MemberBillReports createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { + public static MemberBillReport createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); Map<String, Long> memberBillReports = initReports(memberActions); - Set<String> currentMembers = new HashSet<>(); - + CurrentMembers currentMembers = new CurrentMembers(); while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { - addMemberAction(sortedMemberActions, currentMembers); + MemberAction memberAction = sortedMemberActions.poll(); + currentMembers = currentMembers.addMemberAction(memberAction); continue; } addBillAction(sortedBillActions, currentMembers, memberBillReports); @@ -38,7 +36,7 @@ public static MemberBillReports createByActions(List<BillAction> billActions, Li addBillAction(sortedBillActions, currentMembers, memberBillReports); } - return new MemberBillReports(memberBillReports); + return new MemberBillReport(memberBillReports); } private static Map<String, Long> initReports(List<MemberAction> memberActions) { @@ -58,25 +56,19 @@ private static boolean isMemberActionTurn( return memberAction.getSequence() < billAction.getSequence(); } - private static void addMemberAction(PriorityQueue<MemberAction> sortedMemberActions, Set<String> currentMembers) { - MemberAction memberAction = sortedMemberActions.poll(); - String memberName = memberAction.getMemberName(); - if (memberAction.isSameStatus(MemberActionStatus.IN)) { - currentMembers.add(memberName); - return; - } - currentMembers.remove(memberAction.getMemberName()); - } - private static void addBillAction( PriorityQueue<BillAction> sortedBillActions, - Set<String> currentMembers, + CurrentMembers currentMembers, Map<String, Long> memberBillReports ) { BillAction billAction = sortedBillActions.poll(); + if (currentMembers.isEmpty()) { + return; + } + Long pricePerMember = billAction.getPrice() / currentMembers.size(); - for (String currentMember : currentMembers) { - Long price = memberBillReports.getOrDefault(currentMember, 0L) + pricePerMember; + for (String currentMember : currentMembers.getMembers()) { + Long price = memberBillReports.get(currentMember) + pricePerMember; memberBillReports.put(currentMember, price); } } diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java index 37ddca432..389ca70c1 100644 --- a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java +++ b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java @@ -5,6 +5,7 @@ import static server.haengdong.domain.action.MemberActionStatus.OUT; import java.util.List; +import java.util.Set; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import server.haengdong.domain.event.Event; @@ -27,4 +28,31 @@ void of() { assertThat(currentMembers.getMembers()) .containsExactlyInAnyOrder("망쵸", "웨디"); } + + @DisplayName("인원 변동 액션의 상태가 IN이면 현재 인원에 추가한다.") + @Test + void addMemberAction1() { + CurrentMembers currentMembers = new CurrentMembers(); + Event event = new Event("이벤트", "token"); + MemberAction memberAction = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); + + CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction); + Set<String> members = addedCurrentMembers.getMembers(); + + assertThat(members).hasSize(1) + .containsExactly("웨디"); + } + + @DisplayName("인원 변동 액션의 상태가 OUT이면 현재 인원에서 제외한다.") + @Test + void addMemberAction2() { + Event event = new Event("이벤트", "token"); + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); + CurrentMembers currentMembers = new CurrentMembers().addMemberAction(memberAction1); + MemberAction memberAction2 = new MemberAction(new Action(event, 1L), "웨디", OUT, 1L); + + CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction2); + + assertThat(addedCurrentMembers.getMembers()).hasSize(0); + } } diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportsTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java similarity index 89% rename from server/src/test/java/server/haengdong/domain/action/MemberBillReportsTest.java rename to server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java index db0e2ff37..9ad27d5bc 100644 --- a/server/src/test/java/server/haengdong/domain/action/MemberBillReportsTest.java +++ b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; import server.haengdong.domain.event.Event; -class MemberBillReportsTest { +class MemberBillReportTest { @DisplayName("액션 목록으로 참가자 정산 리포트를 생성한다.") @Test @@ -29,9 +29,9 @@ void createByActions() { new MemberAction(new Action(event, 5L), "감자", OUT, 2L) ); - MemberBillReports memberBillReports = MemberBillReports.createByActions(billActions, memberActions); + MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - assertThat(memberBillReports.getReports()) + assertThat(memberBillReport.getReports()) .containsAllEntriesOf( Map.of( "감자", 20_000L, From 897746625bdaca74850137c765041ff4c7da4858 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Sat, 27 Jul 2024 22:03:58 +0900 Subject: [PATCH 099/273] =?UTF-8?q?chore:=20storybook=20chromatic=20?= =?UTF-8?q?=EB=B0=B0=ED=8F=AC=20(#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 --- .github/workflows/design-pull-request.yml | 61 +++ HDesign/eslint.config.mjs | 49 ++- HDesign/package-lock.json | 355 ++++++++---------- HDesign/package.json | 4 +- .../src/components/BillItem/BillItem.style.ts | 3 +- HDesign/src/components/BillItem/BillItem.tsx | 10 +- .../DragHandleItem/DragHandleItem.style.ts | 3 +- .../DragHandleItem/DragHandleItem.tsx | 12 +- .../ExpenseList/ExpenseList.style.ts | 3 +- .../components/ExpenseList/ExpenseList.tsx | 12 +- HDesign/src/components/Flex/Flex.tsx | 8 +- .../src/components/IconButton/IconButton.tsx | 1 - .../components/InOutItem/InOutItem.style.ts | 3 +- .../src/components/InOutItem/InOutItem.tsx | 8 +- HDesign/src/components/Input/Input.style.ts | 1 + .../src/components/Search/Search.stories.tsx | 5 +- HDesign/src/components/Search/Search.style.ts | 3 +- HDesign/src/components/Search/Search.tsx | 10 +- .../src/components/StepItem/StepItem.style.ts | 3 +- HDesign/src/components/StepItem/StepItem.tsx | 6 +- HDesign/src/components/Switch/Switch.tsx | 5 +- HDesign/src/components/Tab/Tab.stories.tsx | 3 +- HDesign/src/components/Tab/Tab.style.ts | 3 +- HDesign/src/components/Tab/Tab.tsx | 3 +- .../components/TextButton/TextButton.style.ts | 4 +- .../src/components/TextButton/TextButton.tsx | 7 +- .../src/components/TopNav/TopNav.stories.ts | 1 + HDesign/src/components/TopNav/TopNav.tsx | 10 +- HDesign/src/layouts/MainLayout.tsx | 5 +- 29 files changed, 339 insertions(+), 262 deletions(-) create mode 100644 .github/workflows/design-pull-request.yml diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml new file mode 100644 index 000000000..4d54e8b39 --- /dev/null +++ b/.github/workflows/design-pull-request.yml @@ -0,0 +1,61 @@ +name: Storybook Deployment +run-name: ${{ github.actor }}의 스토리북 배포 +on: + pull_request: + branches: + - develop + paths: + - 'HDesign/**' + +jobs: + storybook: + runs-on: ubuntu-latest + outputs: + status: ${{ job.status }} + + defaults: + run: + shell: bash + working-directory: ./HDesign + + steps: + - name: checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: cache dependencies + id: cache + uses: actions/cache@v3 + with: + path: "**/node_modules" + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-storybook + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '20.15.1' + + - name: depedency install + if: steps.cache.outputs.cache-hit != 'true' + run: npm ci + + - name: run lint + working-directory: ./HDesign + run: npm run lint + + - name: publish to chromatic + working-directory: ./HDesign + id: chromatic + uses: chromaui/action@v1 + with: + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} + + - name: comment PR + uses: thollander/actions-comment-pull-request@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + message: "🚀storybook: ${{ steps.chromatic.outputs.storybookUrl }}" + \ No newline at end of file diff --git a/HDesign/eslint.config.mjs b/HDesign/eslint.config.mjs index b6040f04e..96b3da00a 100644 --- a/HDesign/eslint.config.mjs +++ b/HDesign/eslint.config.mjs @@ -21,8 +21,6 @@ const compat = new FlatCompat({ export default [ ...fixupConfigRules( compat.extends( - 'airbnb', - 'airbnb/hooks', 'eslint:recommended', 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended', @@ -64,12 +62,38 @@ export default [ }, rules: { + 'no-use-before-define': 0, 'prettier/prettier': 'error', 'react/react-in-jsx-scope': 'off', 'react/prop-types': 'off', - 'react/jsx-uses-vars': 'error', - '@typescript-eslint/no-use-before-define': ['error'], - '@typescript-eslint/explicit-module-boundary-types': 'error', + 'import/prefer-default-export': 0, + 'import/no-named-as-default': 0, + 'import/namespace': 0, + 'import/extensions': 0, + 'import/no-cycle': 0, + 'react/no-unknown-property': 0, + 'react/jsx-filename-extension': [1, {extensions: ['.ts', '.tsx']}], + 'react/function-component-definition': 0, + 'react/jsx-props-no-spreading': 0, + 'react/jsx-key': 0, + 'react/button-has-type': 'off', + 'no-shadow': 0, + 'no-console': 0, + 'no-alert': 0, + 'react/no-children-prop': 'off', + 'react/no-array-index-key': 'off', + 'react-hooks/exhaustive-deps': 'off', + 'react-hooks/rules-of-hooks': 'off', + 'react/jsx-no-useless-fragment': 'off', + 'react/jsx-no-constructed-context-values': 'off', + 'jsx-a11y/click-events-have-key-events': 'off', + 'jsx-a11y/no-static-element-interactions': 'off', + + '@typescript-eslint/no-unused-vars': 0, + + // 'react/jsx-uses-vars': 'error', + // '@typescript-eslint/no-use-before-define': ['error'], + // '@typescript-eslint/explicit-module-boundary-types': 'error', 'import/order': [ 'error', @@ -89,6 +113,11 @@ export default [ group: 'internal', position: 'after', }, + { + pattern: '@layouts/*', + group: 'internal', + position: 'after', + }, { pattern: '@assets/*', group: 'internal', @@ -104,6 +133,16 @@ export default [ group: 'internal', position: 'after', }, + { + pattern: '@types/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@utils/*', + group: 'internal', + position: 'after', + }, ], }, ], diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 9a18cd5ff..d6b1de8f4 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -32,8 +32,8 @@ "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", - "eslint": "^8.57.0", - "eslint-config-airbnb": "^19.0.4", + "eslint": "^9.7.0", + "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.9.0", @@ -2723,30 +2723,21 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "node_modules/@eslint/config-array/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", @@ -2756,7 +2747,7 @@ "concat-map": "0.0.1" } }, - "node_modules/@eslint/eslintrc/node_modules/debug": { + "node_modules/@eslint/config-array/node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", @@ -2773,22 +2764,7 @@ } } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "node_modules/@eslint/config-array/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", @@ -2800,49 +2776,36 @@ "node": "*" } }, - "node_modules/@eslint/eslintrc/node_modules/ms": { + "node_modules/@eslint/config-array/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.7.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", - "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", - "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" }, - "engines": { - "node": ">=10.10.0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", @@ -2852,7 +2815,7 @@ "concat-map": "0.0.1" } }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "node_modules/@eslint/eslintrc/node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", @@ -2869,7 +2832,19 @@ } } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", @@ -2881,12 +2856,30 @@ "node": "*" } }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "node_modules/@eslint/eslintrc/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/@eslint/js": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", + "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2900,12 +2893,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@jest/schemas": { "version": "29.6.3", @@ -6684,12 +6683,6 @@ "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", "dev": true }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, "node_modules/consola": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", @@ -7691,41 +7684,37 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.7.0.tgz", + "integrity": "sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.7.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -7739,59 +7728,22 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-airbnb": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", - "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", - "dev": true, - "dependencies": { - "eslint-config-airbnb-base": "^15.0.0", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5" - }, - "engines": { - "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0" + "url": "https://eslint.org/donate" } }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "bin": { + "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" - } - }, - "node_modules/eslint-config-airbnb-base/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "eslint": ">=7.0.0" } }, "node_modules/eslint-import-resolver-node": { @@ -8237,15 +8189,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -8273,18 +8216,6 @@ } } }, - "node_modules/eslint/node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/eslint/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -8298,16 +8229,28 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -8350,21 +8293,6 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -8428,30 +8356,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -8692,15 +8620,28 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" + } + }, + "node_modules/file-entry-cache/node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" } }, "node_modules/file-loader": { diff --git a/HDesign/package.json b/HDesign/package.json index 42f857a3e..b077aa3ba 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -36,8 +36,8 @@ "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", - "eslint": "^8.57.0", - "eslint-config-airbnb": "^19.0.4", + "eslint": "^9.7.0", + "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.9.0", diff --git a/HDesign/src/components/BillItem/BillItem.style.ts b/HDesign/src/components/BillItem/BillItem.style.ts index dceb9af92..54531e095 100644 --- a/HDesign/src/components/BillItem/BillItem.style.ts +++ b/HDesign/src/components/BillItem/BillItem.style.ts @@ -1,6 +1,7 @@ -import {Theme} from '@/theme/theme.type'; import {css} from '@emotion/react'; +import {Theme} from '@/theme/theme.type'; + export const textStyle = (theme: Theme) => css({ color: theme.colors.black, diff --git a/HDesign/src/components/BillItem/BillItem.tsx b/HDesign/src/components/BillItem/BillItem.tsx index 0823d8add..bf5d916cd 100644 --- a/HDesign/src/components/BillItem/BillItem.tsx +++ b/HDesign/src/components/BillItem/BillItem.tsx @@ -1,12 +1,16 @@ /** @jsxImportSource @emotion/react */ import React from 'react'; -import {useTheme} from '@theme/HDesignProvider'; -import {BillItemProps} from './BillItem.type'; -import {textStyle} from './BillItem.style'; + import Text from '@components/Text/Text'; + +import {useTheme} from '@theme/HDesignProvider'; + import DragHandleItem from '../DragHandleItem/DragHandleItem'; import Flex from '../Flex/Flex'; +import {BillItemProps} from './BillItem.type'; +import {textStyle} from './BillItem.style'; + export const BillItem: React.FC<BillItemProps> = ({ name = '', price = 0, diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts index a08dfc574..972050619 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts @@ -1,6 +1,7 @@ +import {css} from '@emotion/react'; + import {Theme} from '@/theme/theme.type'; import {ColorKeys} from '@/token/colors'; -import {css} from '@emotion/react'; export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgroundColor: ColorKeys) => css({ diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx index 8ae6aeb8c..9c92a6c8f 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx @@ -1,12 +1,14 @@ /** @jsxImportSource @emotion/react */ import React from 'react'; +import {StrictPropsWithChildren} from '@/types/strictPropsWithChildren'; +import {COLORS, ColorKeys} from '@/token/colors'; + import {useTheme} from '@theme/HDesignProvider'; import IconButton from '../IconButton/IconButton'; -import {StrictPropsWithChildren} from '@/types/strictPropsWithChildren'; + import {dragHandleItemStyle, prefixStyle} from './DragHandleItem.style'; -import {COLORS, ColorKeys} from '@/token/colors'; interface DragHandleItemCustomProps { hasDragHandle?: boolean; @@ -15,12 +17,12 @@ interface DragHandleItemCustomProps { export type DragHandleItemProps = React.ComponentProps<'div'> & DragHandleItemCustomProps; -export const DragHandleItem = ({ +export function DragHandleItem({ hasDragHandle = false, backgroundColor = 'white', children, ...htmlProps -}: StrictPropsWithChildren<DragHandleItemProps>) => { +}: StrictPropsWithChildren<DragHandleItemProps>) { const {theme} = useTheme(); // TODO: (@toari) : 사람 수 많을 때 UX writing 처리 @@ -32,5 +34,5 @@ export const DragHandleItem = ({ </div> </div> ); -}; +} export default DragHandleItem; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.style.ts b/HDesign/src/components/ExpenseList/ExpenseList.style.ts index 30d71de79..58c8ba7f5 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.style.ts +++ b/HDesign/src/components/ExpenseList/ExpenseList.style.ts @@ -1,6 +1,7 @@ -import {Theme} from '@/theme/theme.type'; import {css} from '@emotion/react'; +import {Theme} from '@/theme/theme.type'; + export const expenseItemStyle = () => css({ display: 'flex', diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx index 0c1b8a771..8dbc71858 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.tsx +++ b/HDesign/src/components/ExpenseList/ExpenseList.tsx @@ -1,14 +1,16 @@ /** @jsxImportSource @emotion/react */ -import {useTheme} from '@theme/HDesignProvider'; import Text from '@components/Text/Text'; + import {Arrow} from '@assets/index'; +import {useTheme} from '@theme/HDesignProvider'; + import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle, TextStyle} from './ExpenseList.style'; // TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 -const ExpenseItem = ({name, price}: ExpenseItemProps) => { +function ExpenseItem({name, price}: ExpenseItemProps) { const {theme} = useTheme(); return ( <button css={expenseItemStyle}> @@ -21,9 +23,9 @@ const ExpenseItem = ({name, price}: ExpenseItemProps) => { </div> </button> ); -}; +} -const ExpenseList = ({expenseList = []}: ExpenseListProps) => { +function ExpenseList({expenseList = []}: ExpenseListProps) { const {theme} = useTheme(); return ( <div css={expenseListStyle(theme)}> @@ -32,6 +34,6 @@ const ExpenseList = ({expenseList = []}: ExpenseListProps) => { ))} </div> ); -}; +} export default ExpenseList; diff --git a/HDesign/src/components/Flex/Flex.tsx b/HDesign/src/components/Flex/Flex.tsx index eb2530b31..0210669cc 100644 --- a/HDesign/src/components/Flex/Flex.tsx +++ b/HDesign/src/components/Flex/Flex.tsx @@ -1,7 +1,9 @@ /** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + import {StrictPropsWithChildren} from '@/types/strictPropsWithChildren'; import {changeCamelCaseToKebabCase} from '@/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase'; -import {css} from '@emotion/react'; + import {FlexDirectionStrictType, FlexProps} from './Flex.type'; const flexStyle = ({ @@ -32,8 +34,8 @@ const flexStyle = ({ }); // TODO: (@weadie) 지정된 프롭 말고 다른 프롭도 가져올 수 있게 하자. -const Flex = ({children, ...props}: StrictPropsWithChildren<FlexProps>) => { +function Flex({children, ...props}: StrictPropsWithChildren<FlexProps>) { return <div css={flexStyle(props)}>{children}</div>; -}; +} export default Flex; diff --git a/HDesign/src/components/IconButton/IconButton.tsx b/HDesign/src/components/IconButton/IconButton.tsx index 9e19ddf21..66d4c34b8 100644 --- a/HDesign/src/components/IconButton/IconButton.tsx +++ b/HDesign/src/components/IconButton/IconButton.tsx @@ -2,7 +2,6 @@ import {forwardRef} from 'react'; import {IconButtonProps} from '@components/IconButton/IconButton.type'; - import {InputDelete, Plus, Buljusa} from '@/assets'; const ICON = { diff --git a/HDesign/src/components/InOutItem/InOutItem.style.ts b/HDesign/src/components/InOutItem/InOutItem.style.ts index b14dedae8..3137d1908 100644 --- a/HDesign/src/components/InOutItem/InOutItem.style.ts +++ b/HDesign/src/components/InOutItem/InOutItem.style.ts @@ -1,6 +1,7 @@ -import {Theme} from '@/theme/theme.type'; import {css} from '@emotion/react'; +import {Theme} from '@/theme/theme.type'; + export const inOutItemStyle = (theme: Theme) => css({ display: 'flex', diff --git a/HDesign/src/components/InOutItem/InOutItem.tsx b/HDesign/src/components/InOutItem/InOutItem.tsx index 37fd8bbd5..7cc99622f 100644 --- a/HDesign/src/components/InOutItem/InOutItem.tsx +++ b/HDesign/src/components/InOutItem/InOutItem.tsx @@ -1,14 +1,16 @@ /** @jsxImportSource @emotion/react */ import React from 'react'; +import Text from '@components/Text/Text'; + import {useTheme} from '@theme/HDesignProvider'; -import {InOutItemProps} from './InOutItem.type'; -import {prefixStyle, textStyle} from './InOutItem.style'; -import Text from '@components/Text/Text'; import IconButton from '../IconButton/IconButton'; import DragHandleItem from '../DragHandleItem/DragHandleItem'; +import {InOutItemProps} from './InOutItem.type'; +import {prefixStyle, textStyle} from './InOutItem.style'; + export const InOutItem: React.FC<InOutItemProps> = ({ names = [], inOutType = 'out', diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts index be05abb5b..aeedfeb50 100644 --- a/HDesign/src/components/Input/Input.style.ts +++ b/HDesign/src/components/Input/Input.style.ts @@ -1,6 +1,7 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; + import {InputType} from './Input.type'; const inputBoxBackgroundColorByInputType = (theme: Theme, inputType: InputType = 'input') => { diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx index 40f7df4b1..d52f74053 100644 --- a/HDesign/src/components/Search/Search.stories.tsx +++ b/HDesign/src/components/Search/Search.stories.tsx @@ -1,6 +1,7 @@ -import React from 'react'; import type {Meta, StoryObj} from '@storybook/react'; +import React from 'react'; + import Search from '@components/Search/Search'; const meta = { @@ -23,7 +24,7 @@ const meta = { disabled: false, placeholder: 'placeholder', searchTerms: ['todari', 'cookie'], - setKeyword: keyword => console.log(keyword), + setKeyword: (keyword: string) => console.log(keyword), }, } satisfies Meta<typeof Search>; diff --git a/HDesign/src/components/Search/Search.style.ts b/HDesign/src/components/Search/Search.style.ts index 413655bd5..230cf3e8e 100644 --- a/HDesign/src/components/Search/Search.style.ts +++ b/HDesign/src/components/Search/Search.style.ts @@ -1,6 +1,7 @@ -import {Theme} from '@/theme/theme.type'; import {css} from '@emotion/react'; +import {Theme} from '@/theme/theme.type'; + export const searchStyle = css({ position: 'relative', diff --git a/HDesign/src/components/Search/Search.tsx b/HDesign/src/components/Search/Search.tsx index 68fc02209..cecdffa52 100644 --- a/HDesign/src/components/Search/Search.tsx +++ b/HDesign/src/components/Search/Search.tsx @@ -1,11 +1,13 @@ /** @jsxImportSource @emotion/react */ +import Flex from '@components/Flex/Flex'; + +import {useTheme} from '@theme/HDesignProvider'; + import Input from '../Input/Input'; import {InputProps} from '../Input/Input.type'; -import {searchStyle, searchTermsStyle} from './Search.style'; + +import {searchStyle, searchTermsStyle, searchTermStyle} from './Search.style'; import useSearch from './useSearch'; -import {searchTermStyle} from './Search.style'; -import {useTheme} from '@theme/HDesignProvider'; -import Flex from '@components/Flex/Flex'; export interface SearchProps extends InputProps { searchTerms: string[]; diff --git a/HDesign/src/components/StepItem/StepItem.style.ts b/HDesign/src/components/StepItem/StepItem.style.ts index 0cf47c7bb..0258b47a4 100644 --- a/HDesign/src/components/StepItem/StepItem.style.ts +++ b/HDesign/src/components/StepItem/StepItem.style.ts @@ -1,6 +1,7 @@ -import {Theme} from '@/theme/theme.type'; import {css} from '@emotion/react'; +import {Theme} from '@/theme/theme.type'; + export const stepItemStyle = (theme: Theme) => css({ display: 'flex', diff --git a/HDesign/src/components/StepItem/StepItem.tsx b/HDesign/src/components/StepItem/StepItem.tsx index c85fe61bc..6f096db12 100644 --- a/HDesign/src/components/StepItem/StepItem.tsx +++ b/HDesign/src/components/StepItem/StepItem.tsx @@ -1,12 +1,14 @@ /** @jsxImportSource @emotion/react */ import {useTheme} from '@/theme/HDesignProvider'; -import {StepItemCustomProps} from './StepItem.type'; -import {nameStyle, personCountStyle, stepItemStyle, totalAmountStyle, totalTitleStyle} from './StepItem.style'; + import Text from '../Text/Text'; import BillItem from '../BillItem/BillItem'; import {BillItemCustomProps} from '../BillItem/BillItem.type'; import Flex from '../Flex/Flex'; +import {nameStyle, personCountStyle, stepItemStyle, totalAmountStyle, totalTitleStyle} from './StepItem.style'; +import {StepItemCustomProps} from './StepItem.type'; + export const StepItem: React.FC<StepItemCustomProps> = ({ name = '', personCount = 0, diff --git a/HDesign/src/components/Switch/Switch.tsx b/HDesign/src/components/Switch/Switch.tsx index 3ac505ff6..17118a6fa 100644 --- a/HDesign/src/components/Switch/Switch.tsx +++ b/HDesign/src/components/Switch/Switch.tsx @@ -1,10 +1,11 @@ /** @jsxImportSource @emotion/react */ import TextButton from '../TextButton/TextButton'; + import {switchContainerStyle} from './Switch.style'; import {SwitchProps} from './Switch.type'; import {useSwitch} from './useSwitch'; -const Switch = ({value = '', initialValue, values, onChange}: SwitchProps) => { +function Switch({value = '', initialValue, values, onChange}: SwitchProps) { const {selectedValue, handleClick} = useSwitch({value, initialValue, values, onChange}); return ( @@ -21,6 +22,6 @@ const Switch = ({value = '', initialValue, values, onChange}: SwitchProps) => { ))} </div> ); -}; +} export default Switch; diff --git a/HDesign/src/components/Tab/Tab.stories.tsx b/HDesign/src/components/Tab/Tab.stories.tsx index 06986fec2..e92495e1a 100644 --- a/HDesign/src/components/Tab/Tab.stories.tsx +++ b/HDesign/src/components/Tab/Tab.stories.tsx @@ -1,6 +1,7 @@ -import React from 'react'; import type {Meta, StoryObj} from '@storybook/react'; +import React from 'react'; + import Tab from '@components/Tab/Tab'; const meta = { diff --git a/HDesign/src/components/Tab/Tab.style.ts b/HDesign/src/components/Tab/Tab.style.ts index 2242261b5..b038fadd1 100644 --- a/HDesign/src/components/Tab/Tab.style.ts +++ b/HDesign/src/components/Tab/Tab.style.ts @@ -1,6 +1,7 @@ -import {Theme} from '@/theme/theme.type'; import {css} from '@emotion/react'; +import {Theme} from '@/theme/theme.type'; + export const tabStyle = css({ display: 'flex', flexDirection: 'column', diff --git a/HDesign/src/components/Tab/Tab.tsx b/HDesign/src/components/Tab/Tab.tsx index 313f62086..4981b9e92 100644 --- a/HDesign/src/components/Tab/Tab.tsx +++ b/HDesign/src/components/Tab/Tab.tsx @@ -2,11 +2,12 @@ import {css} from '@emotion/react'; import React, {useState} from 'react'; +import Text from '@components/Text/Text'; + import {useTheme} from '@theme/HDesignProvider'; import {tabListStyle, tabTextStyle, tabStyle, tabItemStyle, indicatorStyle} from './Tab.style'; import {TabsProps} from './Tab.type'; -import Text from '@components/Text/Text'; const Tab: React.FC<TabsProps> = ({tabs}) => { const {theme} = useTheme(); diff --git a/HDesign/src/components/TextButton/TextButton.style.ts b/HDesign/src/components/TextButton/TextButton.style.ts index e2b602c62..6777b1eed 100644 --- a/HDesign/src/components/TextButton/TextButton.style.ts +++ b/HDesign/src/components/TextButton/TextButton.style.ts @@ -1,6 +1,8 @@ +import {css} from '@emotion/react'; + import {Theme} from '@/theme/theme.type'; + import {TextColor} from './TextButton.type'; -import {css} from '@emotion/react'; interface TextButtonStyleProps { textColor: TextColor; diff --git a/HDesign/src/components/TextButton/TextButton.tsx b/HDesign/src/components/TextButton/TextButton.tsx index c44b7a5c7..9d857c38d 100644 --- a/HDesign/src/components/TextButton/TextButton.tsx +++ b/HDesign/src/components/TextButton/TextButton.tsx @@ -1,8 +1,11 @@ /** @jsxImportSource @emotion/react */ import {forwardRef} from 'react'; -import {TextButtonProps} from './TextButton.type'; -import Text from '../Text/Text'; + import {useTheme} from '@/theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {TextButtonProps} from './TextButton.type'; import {textButtonStyle} from './TextButton.style'; export const TextButton: React.FC<TextButtonProps> = forwardRef<HTMLButtonElement, TextButtonProps>(function Button( diff --git a/HDesign/src/components/TopNav/TopNav.stories.ts b/HDesign/src/components/TopNav/TopNav.stories.ts index f37845346..f231e8bd7 100644 --- a/HDesign/src/components/TopNav/TopNav.stories.ts +++ b/HDesign/src/components/TopNav/TopNav.stories.ts @@ -1,6 +1,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import TopNav from '@components/TopNav/TopNav'; + import Switch from '../Switch/Switch'; const meta = { diff --git a/HDesign/src/components/TopNav/TopNav.tsx b/HDesign/src/components/TopNav/TopNav.tsx index 75ce368ff..bcfa72260 100644 --- a/HDesign/src/components/TopNav/TopNav.tsx +++ b/HDesign/src/components/TopNav/TopNav.tsx @@ -1,12 +1,14 @@ import {useNavigate} from 'react-router-dom'; + import TextButton from '../TextButton/TextButton'; +import Switch from '../Switch/Switch'; + import {topNavStyle} from './TopNav.style'; import {TopNavProps} from './TopNav.type'; -import Switch from '../Switch/Switch'; // TODO: (@todari) navigation으로 인해 storybook 동작하지 않는 오류 해결해야함 // + 페이지 정하는 것에 따라, navigate 경로 수정해 줘야 함 -const TopNav = ({navType}: TopNavProps) => { +function TopNav({navType}: TopNavProps) { const navigate = useNavigate(); return ( <div css={topNavStyle}> @@ -15,10 +17,10 @@ const TopNav = ({navType}: TopNavProps) => { 뒤로가기 </TextButton> ) : ( - <Switch values={['홈', '관리']} onChange={() => navigate('./')}></Switch> + <Switch values={['홈', '관리']} onChange={() => navigate('./')} /> )} </div> ); -}; +} export default TopNav; diff --git a/HDesign/src/layouts/MainLayout.tsx b/HDesign/src/layouts/MainLayout.tsx index 825aca175..10032b4d8 100644 --- a/HDesign/src/layouts/MainLayout.tsx +++ b/HDesign/src/layouts/MainLayout.tsx @@ -1,12 +1,13 @@ import {PropsWithChildren} from 'react'; + import {Flex} from '..'; interface MainLayoutInterface extends PropsWithChildren {} -export const MainLayout = ({children}: MainLayoutInterface) => { +export function MainLayout({children}: MainLayoutInterface) { return ( <Flex justifyContent="flexStart" flexDirection="column" margin="1rem 0 0 0" gap="1rem" width="100%" height="100%"> {children} </Flex> ); -}; +} From e443f3b54dc7635785492b69cf8d93143a94e661 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Sat, 27 Jul 2024 23:08:49 +0900 Subject: [PATCH 100/273] =?UTF-8?q?feat:=202=EC=B0=A8=20=EC=8A=A4=ED=94=84?= =?UTF-8?q?=EB=A6=B0=ED=8A=B8=20API=20=EC=97=B0=EA=B2=B0=20(#137)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> --- client/index.html | 3 +- client/package-lock.json | 8 +- client/package.json | 2 +- client/src/apis/fetcher.ts | 16 ++- client/src/apis/request/bill.ts | 8 +- client/src/apis/request/event.ts | 29 +++-- client/src/apis/request/member.ts | 14 ++- client/src/apis/request/report.ts | 4 +- client/src/apis/request/stepList.ts | 8 +- client/src/apis/requestPostEvent.ts | 2 +- .../MemberReportList/MemberReportList.tsx | 6 +- .../SetActionModalContent.tsx | 21 +--- .../SetActionModalContent/SetPurchase.tsx | 16 ++- .../UpdateParticipants.tsx | 24 ++--- .../SetInitialParticipants.tsx | 16 ++- client/src/components/StepList/StepList.tsx | 11 +- client/src/constants/routerUrls.ts | 2 +- client/src/hooks/useDynamicInputPairs.tsx | 17 +-- client/src/hooks/useEventId/useEventId.tsx | 25 +++++ client/src/hooks/useNavSwitch.tsx | 37 +++++++ .../useSearchMemberReportList.tsx | 22 ++-- .../stepList.ts => hooks/useStepList/type.ts} | 16 +-- client/src/hooks/useStepList/useStepList.tsx | 91 ++++++++++++---- client/src/index.css | 5 + client/src/pages/Create/Complete.tsx | 13 +-- client/src/pages/Create/Name.tsx | 32 ++++-- client/src/pages/CreateEvent/CreateEvent.tsx | 27 ----- .../{Event.style.ts => Admin/Admin.style.ts} | 1 + client/src/pages/Event/Admin/Admin.tsx | 97 +++++++++++++++++ client/src/pages/Event/Admin/index.ts | 1 + client/src/pages/Event/Event.tsx | 102 ------------------ client/src/pages/Event/EventLayout.tsx | 23 ++++ client/src/pages/Event/Home/Home.tsx | 40 +++++++ client/src/pages/Event/Home/index.ts | 1 + client/src/pages/Event/index.ts | 2 +- client/src/pages/Home/HomeContent.tsx | 21 ---- client/src/pages/Home/HomeLayout.tsx | 20 ---- client/src/pages/Home/index.ts | 1 - client/src/pages/Main/Main.tsx | 4 +- client/src/router.tsx | 14 +-- client/src/type.d.ts | 18 ++++ 41 files changed, 479 insertions(+), 341 deletions(-) create mode 100644 client/src/hooks/useEventId/useEventId.tsx create mode 100644 client/src/hooks/useNavSwitch.tsx rename client/src/{types/stepList.ts => hooks/useStepList/type.ts} (64%) delete mode 100644 client/src/pages/CreateEvent/CreateEvent.tsx rename client/src/pages/Event/{Event.style.ts => Admin/Admin.style.ts} (85%) create mode 100644 client/src/pages/Event/Admin/Admin.tsx create mode 100644 client/src/pages/Event/Admin/index.ts delete mode 100644 client/src/pages/Event/Event.tsx create mode 100644 client/src/pages/Event/EventLayout.tsx create mode 100644 client/src/pages/Event/Home/Home.tsx create mode 100644 client/src/pages/Event/Home/index.ts delete mode 100644 client/src/pages/Home/HomeContent.tsx delete mode 100644 client/src/pages/Home/HomeLayout.tsx delete mode 100644 client/src/pages/Home/index.ts create mode 100644 client/src/type.d.ts diff --git a/client/index.html b/client/index.html index 05702360a..97edcf3ca 100644 --- a/client/index.html +++ b/client/index.html @@ -2,7 +2,8 @@ <html lang="ko"> <head> <meta charset="UTF-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" /> + <meta content="upgrade-insecure-requests" /> <title>행동대장 diff --git a/client/package-lock.json b/client/package-lock.json index 8bc10061f..91269318a 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.29", + "haengdong-design": "^0.1.35", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -6274,9 +6274,9 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.29", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.29.tgz", - "integrity": "sha512-yBxmS8PBYOMG6scumzeey2LQMSvlB5kqyd/pIP/ID4WRkvwVo8ScFYO6iV8odFINt4I1Dx2aC/itdk74Pyvv4A==", + "version": "0.1.35", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.35.tgz", + "integrity": "sha512-JhlZgZXzYfCMV57glEOiI+YKGstGAAOhBOKGad6Mugio/vNVUmInf3/eJPEy/10SM9reizYsSCt7eoyj71ZaSA==", "dependencies": { "@emotion/react": "^11.11.4", "@svgr/webpack": "^8.1.0", diff --git a/client/package.json b/client/package.json index 3c66313b4..cb8e9a714 100644 --- a/client/package.json +++ b/client/package.json @@ -47,7 +47,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.29", + "haengdong-design": "^0.1.35", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 8df81a2c2..f0bdb9887 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -39,7 +39,7 @@ export const requestGet = async ({headers = {}, ...args}: RequestProps): Prom headers, }); - const data: T = await response.json(); + const data: T = await response!.json(); return data; }; @@ -51,8 +51,16 @@ export const requestPut = ({headers = {}, ...args}: RequestProps) => { return fetcher({method: 'PUT', headers, ...args}); }; -export const requestPost = ({headers = {}, ...args}: RequestProps) => { - return fetcher({method: 'POST', headers, ...args}); +export const requestPost = async ({headers = {}, ...args}: RequestProps): Promise => { + const response = await fetcher({method: 'POST', headers, ...args}); + + const contentType = response!.headers.get('Content-Type'); + if (contentType && contentType.includes('application/json')) { + const data: T = await response!.json(); + return data; + } + + return; }; export const requestDelete = ({headers = {}, ...args}: RequestProps) => { @@ -98,8 +106,8 @@ const errorHandler = async (url: string, options: Options) => { return response; } catch (error) { console.error(error); - throw new Error('아 에러났다;; 인생이 행복해질거에요 에러덕분에요ㅎㅎ'); // throw new ErrorWithHeader(errorMessageHeader, getErrorMessage(error)); + return; } }; diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 2e364b944..c07fd758a 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -1,20 +1,18 @@ -import {Bill} from 'types/stepList'; - import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestPost} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; type RequestAddBillList = { - BillList: Bill[]; + billList: Bill[]; }; -export const requestAddBillList = async ({eventId, BillList}: WithEventId) => { +export const requestAddBillList = async ({eventId, billList}: WithEventId) => { await requestPost({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/actions/bills`, body: { - actions: BillList, + actions: billList, }, }); }; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index f6ff6d56b..5822267b9 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -1,18 +1,29 @@ -import {StepList} from 'types/stepList'; - -import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestGet} from '@apis/fetcher'; +import {requestGet, requestPost} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; type RequestCreateNewEvent = { - name: string; + eventName: string; +}; + +type ResponseCreateNewEvent = { + eventId: string; }; -export const requestCreateNewEvent = async ({name}: RequestCreateNewEvent) => { +export const requestCreateNewEvent = async ({eventName}: RequestCreateNewEvent) => { // TODO: (@weadie) 뼈대만 둔 것. header값을 꺼내오는 로직이 필요하다. 또는 바디에 달라고 부탁할 수 있다. - return await requestGet({ - baseUrl: BASE_URL.HD, + return requestPost({ endpoint: TEMP_PREFIX, - body: {name}, + body: {eventName}, + }); +}; + +type ResponseGetEventName = { + eventName: string; +}; + +export const requestGetEventName = async ({eventId}: WithEventId) => { + return requestGet({ + endpoint: `${TEMP_PREFIX}/${eventId}`, }); }; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 252c85e11..d23563f34 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -1,20 +1,24 @@ -import {Member} from 'types/stepList'; - import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestPost} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; type RequestUpdateMemberList = { - MemberList: Member[]; + memberNameList: string[]; + type: MemberType; }; -export const requestUpdateMemberList = async ({eventId, MemberList}: WithEventId) => { +export const requestUpdateMemberList = async ({ + eventId, + type, + memberNameList, +}: WithEventId) => { await requestPost({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/actions/members`, body: { - actions: MemberList, + members: memberNameList, + status: type, }, }); }; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts index 9b714752a..faa6c9185 100644 --- a/client/src/apis/request/report.ts +++ b/client/src/apis/request/report.ts @@ -1,5 +1,3 @@ -import {MemberReport} from 'types/stepList'; - import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet} from '@apis/fetcher'; @@ -12,7 +10,7 @@ type ResponseMemberReportList = { export const requestMemberReportList = async ({eventId}: WithEventId) => { const {reports} = await requestGet({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/actions`, + endpoint: `${TEMP_PREFIX}/${eventId}/actions/reports`, }); return reports; diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts index 60ad385e4..e09cb67fd 100644 --- a/client/src/apis/request/stepList.ts +++ b/client/src/apis/request/stepList.ts @@ -1,15 +1,15 @@ -import {Bill, Member, StepList} from 'types/stepList'; - import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestGet, requestPost} from '@apis/fetcher'; +import {requestGet} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; // TODO: (@weadie) 현재 토큰을 어떻게 관리할지.. 계속 사용되는데 export const requestStepList = async ({eventId}: WithEventId) => { // TODO: (@weadie) response가 어떻게 오는지 안나와서 data로만 써뒀어요. - return await requestGet({ + const {steps} = await requestGet({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/actions`, }); + + return steps; }; diff --git a/client/src/apis/requestPostEvent.ts b/client/src/apis/requestPostEvent.ts index cf6b4716e..c03ae02af 100644 --- a/client/src/apis/requestPostEvent.ts +++ b/client/src/apis/requestPostEvent.ts @@ -5,7 +5,7 @@ interface RequestPostEventProps { } export const requestPostEvent = async ({name}: RequestPostEventProps) => { - requestPost({ + await requestPost({ headers: {'Content-Type': 'application/json'}, body: {name}, endpoint: '/api/events', diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx index ebf1cf72e..1004540fa 100644 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -5,15 +5,15 @@ import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearc const MemberReportList = () => { const [name, setName] = useState(''); - const {memberReportSearchList} = useSearchMemberReportList({name, eventId: '므와아아아'}); + const {memberReportSearchList} = useSearchMemberReportList({name}); const changeName = ({target}: React.ChangeEvent) => { setName(target.value); }; return ( - - + + ); diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx index 93a917652..b3ccd64c9 100644 --- a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx +++ b/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx @@ -1,8 +1,6 @@ import {useState} from 'react'; import {BottomSheet, Switch} from 'haengdong-design'; -import {InOutType, ParticipantType, PurchaseInformation} from '@pages/Event/Event'; - import SetPurchase from './SetPurchase'; import UpdateParticipants from './UpdateParticipants'; import {setActionModalContentStyle, setActionModalContentSwitchContainerStyle} from './SetActionModalContent.style'; @@ -10,29 +8,21 @@ import {setActionModalContentStyle, setActionModalContentSwitchContainerStyle} f export type ActionType = '지출' | '인원'; interface SetActionModalContentProps { - participants: string[]; openBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch>; setOrder: React.Dispatch>; } -const SetActionModalContent = ({ - participants, - openBottomSheet, - - setOpenBottomSheet, - setOrder, -}: SetActionModalContentProps) => { +const SetActionModalContent = ({openBottomSheet, setOpenBottomSheet, setOrder}: SetActionModalContentProps) => { const [action, setAction] = useState('지출'); - const [participantAction, setParticipantAction] = useState('탈주'); + const [inOutAction, setInOutAction] = useState('탈주'); const handleActionTypeChange = (value: string) => { setAction(value as ActionType); }; const handleParticipantTypeChange = (value: string) => { - setParticipantAction(value as InOutType); + setInOutAction(value as InOutType); }; return ( @@ -41,15 +31,14 @@ const SetActionModalContent = ({
{action === '인원' && ( - + )}
{action === '지출' && } {action === '인원' && ( )} diff --git a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx index 515c048dd..a83a697a7 100644 --- a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx +++ b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx @@ -1,5 +1,7 @@ import {Input, FixedButton} from 'haengdong-design'; +import {useStepList} from '@hooks/useStepList/useStepList'; + import useDynamicInputPairs from '@hooks/useDynamicInputPairs'; import {setPurchaseInputStyle, setPurchaseStyle, setPurchaseInputContainerStyle} from './SetPurchase.style'; @@ -10,11 +12,14 @@ interface SetPurchaseProps { } const SetPurchase = ({setOpenBottomSheet, setOrder}: SetPurchaseProps) => { - const {inputPairs, inputRefs, handleInputChange, handleInputBlur} = useDynamicInputPairs(); + const {inputPairs, inputRefs, handleInputChange, handleInputBlur, getNonEmptyInputPairs} = useDynamicInputPairs(); + const {addBill} = useStepList(); const handleSetPurchaseSubmit = () => { setOrder(prev => prev + 1); - // TODO: (@soha) api 요청시 inputPairs를 보내면 됨 + + // TODO: (@weadie) 요청 실패시 오류 핸들 필요 + addBill(getNonEmptyInputPairs()); setOpenBottomSheet(false); }; @@ -25,8 +30,8 @@ const SetPurchase = ({setOpenBottomSheet, setOrder}: SetPurchaseProps) => {
handleInputChange(index, 'name', e.target.value)} + value={pair.title} + onChange={e => handleInputChange(index, 'title', e.target.value)} onBlur={() => handleInputBlur(index)} placeholder="지출 내역" ref={el => (inputRefs.current[index * 2] = el)} @@ -43,7 +48,8 @@ const SetPurchase = ({setOpenBottomSheet, setOrder}: SetPurchaseProps) => { ))}
diff --git a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx index 72b86faa7..5adc3cd43 100644 --- a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx +++ b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx @@ -1,31 +1,22 @@ import {Input, FixedButton} from 'haengdong-design'; -import {useState} from 'react'; -import {InOutType} from '@pages/Event/Event'; +import {useStepList} from '@hooks/useStepList/useStepList'; import useDynamicInput from '@hooks/useDynamicAdditionalInput'; import {updateParticipantsInputStyle, updateParticipantsStyle} from './UpdateParticipants.style'; interface UpdateParticipantsProps { - participants: string[]; - participantAction: InOutType; + inOutAction: MemberType; setOpenBottomSheet: React.Dispatch>; } -const UpdateParticipants = ({participantAction, participants, setOpenBottomSheet}: UpdateParticipantsProps) => { +const UpdateParticipants = ({inOutAction, setOpenBottomSheet}: UpdateParticipantsProps) => { const {inputs, inputRefs, handleInputChange, handleInputBlur, getNonEmptyInputs} = useDynamicInput(); + const {updateMemberList} = useStepList(); const handleUpdateParticipantsSubmit = () => { - const newParticipants = () => { - if (participantAction === '탈주') { - return participants.filter(participant => !getNonEmptyInputs().includes(participant)); - } else { - return [...participants, ...getNonEmptyInputs()]; - } - }; - - // TODO: (@soha) api 요청시 newParticipants()를 보내면 됨 + updateMemberList({memberNameList: getNonEmptyInputs(), type: inOutAction}); setOpenBottomSheet(false); }; @@ -46,8 +37,9 @@ const UpdateParticipants = ({participantAction, participants, setOpenBottomSheet ))}
diff --git a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx index 15a0b0460..e5dda7c96 100644 --- a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx +++ b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx @@ -1,5 +1,7 @@ import {Text, Input, BottomSheet, FixedButton} from 'haengdong-design'; +import {useStepList} from '@hooks/useStepList/useStepList'; + import useDynamicInput from '@hooks/useDynamicAdditionalInput'; import {setInitialParticipantsInputGroupStyle, setInitialParticipantsStyle} from './SetInitialParticipants.style'; @@ -7,19 +9,14 @@ import {setInitialParticipantsInputGroupStyle, setInitialParticipantsStyle} from interface SetInitialParticipantsProps { openBottomSheet: boolean; setOpenBottomSheet: React.Dispatch>; - setParticipants: React.Dispatch>; } -const SetInitialParticipants = ({ - openBottomSheet, - setOpenBottomSheet, - setParticipants, -}: SetInitialParticipantsProps) => { +const SetInitialParticipants = ({openBottomSheet, setOpenBottomSheet}: SetInitialParticipantsProps) => { const {inputs, inputRefs, handleInputChange, handleInputBlur, getNonEmptyInputs} = useDynamicInput(); + const {updateMemberList} = useStepList(); const handleSubmit = () => { - setParticipants(getNonEmptyInputs()); - // TODO: (@soha) api 요청시 getNonEmptyInputs() 보낼 형태 생성 + updateMemberList({memberNameList: getNonEmptyInputs(), type: 'IN'}); setOpenBottomSheet(false); }; @@ -42,7 +39,8 @@ const SetInitialParticipants = ({ diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 76dedc41b..6e9961f99 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,17 +1,22 @@ import {Flex, InOutItem, StepItem} from 'haengdong-design'; import {useStepList} from '@hooks/useStepList/useStepList'; -import {MemberType} from 'types/stepList'; const StepList = () => { const {stepList} = useStepList(); // TODO: (@weadie) if else 구문이 지저분하므로 리펙터링이 필요합니다. return ( - + {stepList.map(step => { if (step.type === 'BILL') { - return ; + return ( + + ); } else if (step.type === 'IN' || step.type === 'OUT') { return name)} />; } else { diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index 228e25c7c..c57ab181e 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -2,7 +2,7 @@ export const ROUTER_URLS = { main: '', eventCreateName: '/event/create/name', eventCreateComplete: '/event/create/complete', - event: '/event', + event: '/event', // TODO: (@weadie) baseurl을 어떻게 관리할 것인가? eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', }; diff --git a/client/src/hooks/useDynamicInputPairs.tsx b/client/src/hooks/useDynamicInputPairs.tsx index db5347dd8..b6f86b000 100644 --- a/client/src/hooks/useDynamicInputPairs.tsx +++ b/client/src/hooks/useDynamicInputPairs.tsx @@ -1,12 +1,10 @@ import {useEffect, useRef, useState} from 'react'; -import {PurchaseInformation} from '@pages/Event/Event'; - const useDynamicInputPairs = () => { - const [inputPairs, setInputPairs] = useState([{name: '', price: 0}]); + const [inputPairs, setInputPairs] = useState([{title: '', price: 0}]); const inputRefs = useRef<(HTMLInputElement | null)[]>([]); - const handleInputChange = (index: number, field: 'name' | 'price', value: string) => { + const handleInputChange = (index: number, field: 'title' | 'price', value: string) => { const newInputPairs = [...inputPairs]; newInputPairs[index] = { ...newInputPairs[index], @@ -17,13 +15,17 @@ const useDynamicInputPairs = () => { const handleInputBlur = (index: number) => { const currentPair = inputPairs[index]; - if (currentPair.name.trim() === '' && currentPair.price === 0) { + if (currentPair.title.trim() === '' && currentPair.price === 0) { setInputPairs(prev => prev.filter((_, i) => i !== index)); - } else if (currentPair.name.trim() !== '' && currentPair.price !== 0 && index === inputPairs.length - 1) { - setInputPairs(prev => [...prev, {name: '', price: 0}]); + } else if (currentPair.title.trim() !== '' && currentPair.price !== 0 && index === inputPairs.length - 1) { + setInputPairs(prev => [...prev, {title: '', price: 0}]); } }; + const getNonEmptyInputPairs = () => { + return inputPairs.filter(currentPair => currentPair.title.trim() !== '' && currentPair.price !== 0); + }; + useEffect(() => { if (inputRefs.current.length > 0) { const lastInputPair = inputRefs.current.slice(-2); @@ -33,6 +35,7 @@ const useDynamicInputPairs = () => { return { inputPairs, + getNonEmptyInputPairs, inputRefs, handleInputChange, handleInputBlur, diff --git a/client/src/hooks/useEventId/useEventId.tsx b/client/src/hooks/useEventId/useEventId.tsx new file mode 100644 index 000000000..ca3775f8e --- /dev/null +++ b/client/src/hooks/useEventId/useEventId.tsx @@ -0,0 +1,25 @@ +import {useEffect, useState} from 'react'; +import {useLocation} from 'react-router-dom'; + +const useEventId = () => { + const [eventId, setEventId] = useState(''); + const location = useLocation(); + + const extractIdFromUrl = (url: string) => { + const regex = /\/event\/([a-zA-Z0-9-]+)\//; + const match = url.match(regex); + return match ? match[1] : null; + }; + + const curEventId = extractIdFromUrl(location.pathname) ?? ''; + + useEffect(() => { + setEventId(curEventId); + }, []); + + return { + eventId, + }; +}; + +export default useEventId; diff --git a/client/src/hooks/useNavSwitch.tsx b/client/src/hooks/useNavSwitch.tsx new file mode 100644 index 000000000..7ecd3def8 --- /dev/null +++ b/client/src/hooks/useNavSwitch.tsx @@ -0,0 +1,37 @@ +import {useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; + +const PATH_TABLE: Record = { + 홈: 'home', + 관리: 'admin', +}; + +const PATH_DISPLAY_TABLE: Record = { + home: '홈', + admin: '관리', +}; + +const useNavSwitch = () => { + const paths = ['홈', '관리']; + const location = useLocation(); + const navigate = useNavigate(); + + const pathArray = location.pathname.split('/'); + const basePath = pathArray.slice(0, -1).join('/'); + const lastPath = pathArray[pathArray.length - 1]; + + const [nav, setNav] = useState(PATH_DISPLAY_TABLE[lastPath]); + + const onChange = (displayName: string) => { + setNav(displayName); + navigate(`${basePath}/${PATH_TABLE[displayName]}`); + }; + + return { + nav, + paths, + onChange, + }; +}; + +export default useNavSwitch; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx index 589317f7d..02c07b80a 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -1,41 +1,37 @@ import {useEffect, useState} from 'react'; -import {MemberReport} from 'types/stepList'; import {requestMemberReportList} from '@apis/request/report'; - -import {WithEventId} from '@apis/withEventId.type'; - -import memberReportSearchJsonList from '@mocks/memberReportSearchList.json'; - -const memberReportSearchMockList = memberReportSearchJsonList as MemberReport[]; +import useEventId from '@hooks/useEventId/useEventId'; type UseSearchMemberReportListParams = { name: string; }; -const useSearchMemberReportList = ({name, eventId}: WithEventId) => { - const [memberReportList, setMemberReportList] = useState(memberReportSearchMockList); +const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { + const [memberReportList, setMemberReportList] = useState([]); const [memberReportSearchList, setMemberReportSearchList] = useState([]); + const {eventId} = useEventId(); useEffect(() => { const fetchMemberReportList = async () => { // TODO: (@weadie) cors 고쳐지면 주석 풀게요. - // const memberReportListData = await requestMemberReportList({eventId}); + // TODO: (@weadie) eventId에 의존하는 두 개의 훅에 대한 리펙토링 필요 + if (eventId === '') return; - const memberReportListData = memberReportSearchMockList; + const memberReportListData = await requestMemberReportList({eventId}); setMemberReportList(memberReportListData); }; fetchMemberReportList(); - }, []); + }, [eventId]); // TODO: (@weadie) 글자가 완성될 때마다 아래 로직이 실행되어야 합니다. useEffect(() => { if (name === '') setMemberReportSearchList(memberReportList); setMemberReportSearchList(memberReportList.filter(memberReport => memberReport.name.includes(name))); - }, [name]); + }, [name, memberReportList]); return { memberReportSearchList, diff --git a/client/src/types/stepList.ts b/client/src/hooks/useStepList/type.ts similarity index 64% rename from client/src/types/stepList.ts rename to client/src/hooks/useStepList/type.ts index f106306e9..6d9b78de1 100644 --- a/client/src/types/stepList.ts +++ b/client/src/hooks/useStepList/type.ts @@ -1,11 +1,7 @@ -export type MemberType = 'IN' | 'OUT'; - -// TODO: (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. -export type StepList = (MemberStep | BillStep)[]; - export type Step = { type: MemberType | 'BILL'; stepName: string | null; + members: string[]; actions: (BillAction | MemberAction)[]; }; @@ -40,13 +36,3 @@ export type Member = { name: string; status: MemberType; }; - -export type Bill = { - title: string; - price: number; -}; - -export type MemberReport = { - name: string; - price: number; -}; diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx index 9adb2d684..52d2a78d6 100644 --- a/client/src/hooks/useStepList/useStepList.tsx +++ b/client/src/hooks/useStepList/useStepList.tsx @@ -1,25 +1,65 @@ -import {PropsWithChildren, createContext, useEffect, useState} from 'react'; +import {PropsWithChildren, createContext, useContext, useEffect, useState} from 'react'; -import {BillAction, MemberType, StepList} from 'types/stepList'; +import useEventId from '@hooks/useEventId/useEventId'; +import {requestAddBillList} from '@apis/request/bill'; +import {requestUpdateMemberList} from '@apis/request/member'; +import {requestStepList} from '@apis/request/stepList'; -import stepListJsonData from '@mocks/stepList.json'; +import {BillAction, BillStep, MemberStep} from './type.ts'; -const stepListMockData = stepListJsonData as StepList; +interface StepListContextProps { + stepList: (BillStep | MemberStep)[]; + getTotalPrice: () => number; + addBill: (billList: Bill[]) => Promise; + updateMemberList: ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => Promise; + memberNameList: string[]; +} -const useStepList = () => { - const [stepList, setStepList] = useState(stepListMockData); +export const StepListContext = createContext(null); // TODO: (@weadie) 인자를 어떻게 줘야 하는지 고민하기. + +const StepListProvider = ({children}: PropsWithChildren) => { + const [stepList, setStepList] = useState<(BillStep | MemberStep)[]>([]); + const [memberNameList, setNameMemberList] = useState([]); + + const {eventId} = useEventId(); useEffect(() => { + if (eventId === '') return; + + refreshStepList(); + // TODO: (@weadie) useEffect를 꼭 써야하는가? - // 초기 리스트 불러서 setActionList - }, []); + }, [eventId]); + + const refreshStepList = async () => { + const stepList = await requestStepList({eventId}); + + if (stepList.length !== 0) { + setNameMemberList(stepList[stepList.length - 1].members); + } - const updateMemberList = (type: MemberType, memberList: string[]) => { - // api를 호출하고 set한다 + setStepList(stepList); }; - const addBill = (title: string, price: number) => { - // api를 호출하고 set한다. + const updateMemberList = async ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => { + try { + await requestUpdateMemberList({eventId, type, memberNameList}); + + // TODO: (@weadie) 클라이언트 단에서 멤버 목록을 관리하기 위한 로직. 개선이 필요하다. + if (type === 'IN') setNameMemberList(prev => [...prev, ...memberNameList]); + if (type === 'OUT') setNameMemberList(prev => prev.filter(name => !memberNameList.includes(name))); + + refreshStepList(); + } catch (error) { + alert(error); + } + }; + + const addBill = async (billList: Bill[]) => { + // TODO: (@weadie) 에러 처리 + await requestAddBillList({eventId, billList}); + + refreshStepList(); }; const calculateBillSum = (actions: BillAction[]) => { @@ -35,15 +75,28 @@ const useStepList = () => { }, 0); }; - return {stepList, getTotalPrice}; + return ( + + {children} + + ); }; -const StepListContext = createContext([]); // TODO: (@weadie) 인자를 어떻게 줘야 하는지 고민하기. - -const StepListProvider = ({children}: PropsWithChildren) => { - const {stepList} = useStepList(); +export const useStepList = () => { + const context = useContext(StepListContext); - return {children}; + if (!context) { + throw new Error('useStepList는 StepListProvider 내에서 사용되어야 합니다.'); + } + return context; }; -export {useStepList, StepListProvider}; +export default StepListProvider; diff --git a/client/src/index.css b/client/src/index.css index 8ebdb5ba8..2f63176f6 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -2,6 +2,11 @@ body { max-width: 768px; height: 100lvh; margin: 0 auto; + + overflow-y: scroll; + &::-webkit-scrollbar { + display: none; + } } section { diff --git a/client/src/pages/Create/Complete.tsx b/client/src/pages/Create/Complete.tsx index b4496d0cd..786979607 100644 --- a/client/src/pages/Create/Complete.tsx +++ b/client/src/pages/Create/Complete.tsx @@ -1,6 +1,6 @@ import {useEffect, useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, Title} from 'haengdong-design'; +import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -11,11 +11,12 @@ const CompleteCreateEvent = () => { useEffect(() => { const getUrl = async () => { - const eventTitle = location.search; - // console.log(eventTitle); + // TODO: (@weadie) eventId를 location에서 불러오는 로직 함수로 분리해서 재사용 + const params = new URLSearchParams(location.search); + const eventId = params.get('eventId'); - // const url = await fetch(); - setUrl('hangsapage'); + // TODO: (@weadie) eventId가 없는 경우에 대한 처리 필요 + setUrl(eventId ?? ''); }; getUrl(); @@ -23,7 +24,7 @@ const CompleteCreateEvent = () => { return ( - {/* */} + } /> + <TopNav> + <Back /> + </TopNav> <Title title="행사 이름 입력" description="시작할 행사 이름을 입력해 주세요." /> - <form onSubmit={submitEventTitle}> + <form onSubmit={submitEventName} style={{padding: '0 1rem'}}> <Input - value={eventTitle} - onChange={event => setEventTitle(event.target.value)} + value={eventName} + onChange={event => setEventName(event.target.value)} + onBlur={() => setEventName(eventName.trim())} placeholder="ex) 행동대장 야유회" /> - <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateComplete)}>행동 개시!</FixedButton> + <FixedButton disabled={!eventName.length}>행동 개시!</FixedButton> </form> </MainLayout> ); diff --git a/client/src/pages/CreateEvent/CreateEvent.tsx b/client/src/pages/CreateEvent/CreateEvent.tsx deleted file mode 100644 index 9697200e0..000000000 --- a/client/src/pages/CreateEvent/CreateEvent.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import {useState} from 'react'; -import {useNavigate} from 'react-router-dom'; - -import {ROUTER_URLS} from '@constants/routerUrls'; - -const CreateEvent = () => { - const [eventTitle, setEventTitle] = useState(''); - const navigate = useNavigate(); - - const submitEventTitle = (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - navigate(`${ROUTER_URLS.eventCreateName}?${new URLSearchParams({title: eventTitle})}`); - }; - - return ( - <section> - <h1>행사 생성하기</h1> - <h3>시작할 행사 이름을 입력해 주세요.</h3> - <form onSubmit={submitEventTitle}> - <input value={eventTitle} onChange={event => setEventTitle(event.target.value)} /> - <button>행동 개시!</button> - </form> - </section> - ); -}; - -export default CreateEvent; diff --git a/client/src/pages/Event/Event.style.ts b/client/src/pages/Event/Admin/Admin.style.ts similarity index 85% rename from client/src/pages/Event/Event.style.ts rename to client/src/pages/Event/Admin/Admin.style.ts index 15e2443b4..2025006d4 100644 --- a/client/src/pages/Event/Event.style.ts +++ b/client/src/pages/Event/Admin/Admin.style.ts @@ -6,4 +6,5 @@ export const ReceiptStyle = () => flexDirection: 'column', gap: '8px', padding: '0 8px', + paddingBottom: '8.75rem', }); diff --git a/client/src/pages/Event/Admin/Admin.tsx b/client/src/pages/Event/Admin/Admin.tsx new file mode 100644 index 000000000..bda03da55 --- /dev/null +++ b/client/src/pages/Event/Admin/Admin.tsx @@ -0,0 +1,97 @@ +import {useEffect, useState} from 'react'; +import {Title, FixedButton} from 'haengdong-design'; + +import StepList from '@components/StepList/StepList'; +import {useStepList} from '@hooks/useStepList/useStepList'; +import {requestGetEventName} from '@apis/request/event'; +import useEventId from '@hooks/useEventId/useEventId'; + +import {SetActionModalContent, SetInitialParticipants} from '@components/Modal'; + +import {ReceiptStyle} from './Admin.style'; + +export type PurchaseInformation = { + title: string; + price: number; +}; + +export type ParticipantType = { + name: string; + type: InOutType; +}; + +interface ModalRenderingProps { + memberNameList: string[]; + openBottomSheet: boolean; + setOrder: React.Dispatch<React.SetStateAction<number>>; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; +} + +const ModalRendering = ({memberNameList, openBottomSheet, setOrder, setOpenBottomSheet}: ModalRenderingProps) => { + switch (memberNameList.length) { + case 0: + return <SetInitialParticipants setOpenBottomSheet={setOpenBottomSheet} openBottomSheet={openBottomSheet} />; + + default: + return ( + <SetActionModalContent + setOrder={setOrder} + setOpenBottomSheet={setOpenBottomSheet} + openBottomSheet={openBottomSheet} + /> + ); + } +}; + +const Admin = () => { + const [openBottomSheet, setOpenBottomSheet] = useState(false); + const [order, setOrder] = useState<number>(1); + + // TODO: (@weadie) eventName이 새로고침시 공간이 없다가 생겨나 레이아웃이 움직이는 문제 + const [eventName, setEventName] = useState(' '); + + const {getTotalPrice, memberNameList} = useStepList(); + + const {eventId} = useEventId(); + + // TODO: (@weadie) 아래 로직을 훅으로 분리합니다. + useEffect(() => { + if (eventId === '') return; + + const getEventName = async () => { + const {eventName} = await requestGetEventName({eventId: eventId ?? ''}); + + setEventName(eventName); + }; + + getEventName(); + }, [eventId]); + + return ( + <> + <Title + title={eventName} + description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." + price={getTotalPrice()} + /> + <section css={ReceiptStyle}> + <StepList /> + {/* TODO: (@soha) 추후 버튼 width 화면에 맞게 수정 */} + <FixedButton + children={memberNameList.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} + onClick={() => setOpenBottomSheet(prev => !prev)} + /> + {openBottomSheet && ( + <ModalRendering + memberNameList={memberNameList} + setOrder={setOrder} + setOpenBottomSheet={setOpenBottomSheet} + openBottomSheet={openBottomSheet} + /> + )} + </section> + </> + ); +}; + +export default Admin; diff --git a/client/src/pages/Event/Admin/index.ts b/client/src/pages/Event/Admin/index.ts new file mode 100644 index 000000000..9799a7485 --- /dev/null +++ b/client/src/pages/Event/Admin/index.ts @@ -0,0 +1 @@ +export {default as AdminPage} from './Admin'; diff --git a/client/src/pages/Event/Event.tsx b/client/src/pages/Event/Event.tsx deleted file mode 100644 index 79c1f9950..000000000 --- a/client/src/pages/Event/Event.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import {useState} from 'react'; -import {TopNav, Title, FixedButton, StepItem, InOutItem, MainLayout} from 'haengdong-design'; - -import StepList from '@components/StepList/StepList'; -import {useStepList} from '@hooks/useStepList/useStepList'; -import {StepListProvider} from '@hooks/useStepList/useStepList'; - -import {SetActionModalContent, SetInitialParticipants} from '@components/Modal'; - -import {ReceiptStyle} from './Event.style'; - -export type PurchaseInformation = { - name: string; - price: number; -}; - -export type InOutType = '늦참' | '탈주'; - -export type ParticipantType = { - name: string; - type: InOutType; -}; - -interface ModalRenderingProps { - participants: string[]; - openBottomSheet: boolean; - - setOrder: React.Dispatch<React.SetStateAction<number>>; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; - setParticipants: React.Dispatch<React.SetStateAction<string[]>>; -} - -const ModalRendering = ({ - participants, - setOrder, - setOpenBottomSheet, - setParticipants, - openBottomSheet, -}: ModalRenderingProps) => { - switch (participants.length) { - case 0: - return ( - <SetInitialParticipants - setParticipants={setParticipants} - setOpenBottomSheet={setOpenBottomSheet} - openBottomSheet={openBottomSheet} - /> - ); - - default: - return ( - <SetActionModalContent - setOrder={setOrder} - participants={participants} - setOpenBottomSheet={setOpenBottomSheet} - openBottomSheet={openBottomSheet} - /> - ); - } -}; - -const Event = () => { - const [openBottomSheet, setOpenBottomSheet] = useState(false); - const [participants, setParticipants] = useState<string[]>([]); - const [order, setOrder] = useState<number>(0); - - const {getTotalPrice} = useStepList(); - - return ( - <MainLayout backgroundColor="gray"> - <TopNav navType={'home'} /> - <Title - title="행동대장 야유회" - description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." - price={getTotalPrice()} - /> - <section css={ReceiptStyle}> - {order > 0 && ( - // TODO: (@soha) order가 0일때 기본 Step 뜨기 - <StepListProvider> - <StepList /> - </StepListProvider> - )} - {/* TODO: (@soha) 추후 버튼 width 화면에 맞게 수정 */} - <FixedButton - children={participants.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} - onClick={() => setOpenBottomSheet(prev => !prev)} - /> - {openBottomSheet && - ModalRendering({ - participants, - setOrder, - setParticipants, - setOpenBottomSheet, - openBottomSheet, - })} - </section> - </MainLayout> - ); -}; - -export default Event; diff --git a/client/src/pages/Event/EventLayout.tsx b/client/src/pages/Event/EventLayout.tsx new file mode 100644 index 000000000..2b2b439de --- /dev/null +++ b/client/src/pages/Event/EventLayout.tsx @@ -0,0 +1,23 @@ +import {MainLayout, TopNav, Switch} from 'haengdong-design'; +import {Outlet} from 'react-router-dom'; + +import StepListProvider from '@hooks/useStepList/useStepList'; + +import useNavSwitch from '@hooks/useNavSwitch'; + +const EventLayout = () => { + const {nav, paths, onChange} = useNavSwitch(); + + return ( + <StepListProvider> + <MainLayout backgroundColor="gray"> + <TopNav> + <Switch value={nav} values={paths} onChange={onChange} /> + </TopNav> + <Outlet /> + </MainLayout> + </StepListProvider> + ); +}; + +export default EventLayout; diff --git a/client/src/pages/Event/Home/Home.tsx b/client/src/pages/Event/Home/Home.tsx new file mode 100644 index 000000000..8ff195cb8 --- /dev/null +++ b/client/src/pages/Event/Home/Home.tsx @@ -0,0 +1,40 @@ +import {Tab, Tabs, Title} from 'haengdong-design'; +import {useEffect, useState} from 'react'; + +import MemberReportList from '@components/MemberReportList/MemberReportList'; +import StepList from '@components/StepList/StepList'; +import {useStepList} from '@hooks/useStepList/useStepList'; +import useEventId from '@hooks/useEventId/useEventId'; +import {requestGetEventName} from '@apis/request/event'; + +const HomeContent = () => { + const {getTotalPrice} = useStepList(); + const {eventId} = useEventId(); + + // TODO: (@soha) 행사 이름 나중에 따로 분리해야 함 + const [eventName, setEventName] = useState(' '); + + useEffect(() => { + if (eventId === '') return; + + const getEventName = async () => { + const {eventName} = await requestGetEventName({eventId: eventId ?? ''}); + + setEventName(eventName); + }; + + getEventName(); + }, [eventId]); + + return ( + <div> + <Title title={eventName} price={getTotalPrice()} /> + <Tabs tabsContainerStyle={{gap: '1rem'}}> + <Tab label="전체 지출 내역" content={<StepList />} /> + <Tab label="참여자 별 내역" content={<MemberReportList />} /> + </Tabs> + </div> + ); +}; + +export default HomeContent; diff --git a/client/src/pages/Event/Home/index.ts b/client/src/pages/Event/Home/index.ts new file mode 100644 index 000000000..75e27b8a3 --- /dev/null +++ b/client/src/pages/Event/Home/index.ts @@ -0,0 +1 @@ +export {default as HomePage} from './Home'; diff --git a/client/src/pages/Event/index.ts b/client/src/pages/Event/index.ts index fa85db27a..af2aa805d 100644 --- a/client/src/pages/Event/index.ts +++ b/client/src/pages/Event/index.ts @@ -1 +1 @@ -export {default as EventPage} from './Event'; +export {default as EventPage} from './EventLayout'; diff --git a/client/src/pages/Home/HomeContent.tsx b/client/src/pages/Home/HomeContent.tsx deleted file mode 100644 index 171729636..000000000 --- a/client/src/pages/Home/HomeContent.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import {Tab, Tabs, Title} from 'haengdong-design'; - -import MemberReportList from '@components/MemberReportList/MemberReportList'; -import StepList from '@components/StepList/StepList'; -import {useStepList} from '@hooks/useStepList/useStepList'; - -const HomeContent = () => { - const {getTotalPrice} = useStepList(); - - return ( - <div> - <Title title="행동대장 야유회" price={getTotalPrice()} /> - <Tabs> - <Tab label="전체 지출 내역" content={<StepList />} /> - <Tab label="참여자 별 내역" content={<MemberReportList />} /> - </Tabs> - </div> - ); -}; - -export default HomeContent; diff --git a/client/src/pages/Home/HomeLayout.tsx b/client/src/pages/Home/HomeLayout.tsx deleted file mode 100644 index 8cae579d6..000000000 --- a/client/src/pages/Home/HomeLayout.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import {Flex, MainLayout, TopNav} from 'haengdong-design'; - -import {StepListProvider} from '@hooks/useStepList/useStepList'; - -import HomeContent from './HomeContent'; - -const HomeLayout = () => { - return ( - <StepListProvider> - <MainLayout backgroundColor="gray"> - <TopNav navType="home" /> - <Flex flexDirection="column" gap="1rem"> - <HomeContent /> - </Flex> - </MainLayout> - </StepListProvider> - ); -}; - -export default HomeLayout; diff --git a/client/src/pages/Home/index.ts b/client/src/pages/Home/index.ts deleted file mode 100644 index fde362f5c..000000000 --- a/client/src/pages/Home/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as HomePage} from './HomeLayout'; diff --git a/client/src/pages/Main/Main.tsx b/client/src/pages/Main/Main.tsx index 1cb9f6b26..dfd7c406e 100644 --- a/client/src/pages/Main/Main.tsx +++ b/client/src/pages/Main/Main.tsx @@ -1,5 +1,5 @@ import {useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, Title} from 'haengdong-design'; +import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -8,7 +8,7 @@ const Main = () => { return ( <MainLayout> - {/* <TopNav navType="back" /> */} + <TopNav children={<></>} /> <Title title="행동대장" description="랜딩페이지입니다." /> <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateName)}>행사 생성하기</FixedButton> </MainLayout> diff --git a/client/src/router.tsx b/client/src/router.tsx index a84ea18e5..70f7a1e71 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -1,9 +1,11 @@ import {createBrowserRouter} from 'react-router-dom'; +import {AdminPage} from '@pages/Event/Admin'; +import {HomePage} from '@pages/Event/Home'; + import {MainPage} from '@pages/Main'; import {CreateNamePage, CreateCompletePage} from '@pages/Create'; import {EventPage} from '@pages/Event'; -import {HomePage} from '@pages/Home'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -28,12 +30,12 @@ const router = createBrowserRouter([ element: <CreateCompletePage />, }, { - path: ROUTER_URLS.eventManage, + path: ROUTER_URLS.event, element: <EventPage />, - }, - { - path: ROUTER_URLS.home, - element: <HomePage />, + children: [ + {path: ROUTER_URLS.eventManage, element: <AdminPage />}, + {path: ROUTER_URLS.home, element: <HomePage />}, + ], }, ], }, diff --git a/client/src/type.d.ts b/client/src/type.d.ts new file mode 100644 index 000000000..a81318e4c --- /dev/null +++ b/client/src/type.d.ts @@ -0,0 +1,18 @@ +type MemberType = 'IN' | 'OUT'; + +type InOutType = '늦참' | '탈주'; + +type MemberReport = { + name: string; + price: number; +}; + +type Bill = { + title: string; + price: number; +}; + +// TODO: (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. +type StepList = { + steps: (MemberStep | BillStep)[]; +}; From 4d8697a1214debd729e92766ca8c642b59de6e29 Mon Sep 17 00:00:00 2001 From: JUHA <84626225+khabh@users.noreply.github.com> Date: Sun, 28 Jul 2024 16:44:04 +0900 Subject: [PATCH 101/273] =?UTF-8?q?refactor:=20=EB=8F=84=EC=BB=A4=20?= =?UTF-8?q?=EA=B3=84=EC=A0=95=20=EA=B4=80=EB=A0=A8=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?secrets=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20(#139)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml index be973a6a9..d385a69c8 100644 --- a/.github/workflows/backend-push.yml +++ b/.github/workflows/backend-push.yml @@ -68,4 +68,4 @@ jobs: run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev - name: Docker run - run: sudo docker run -d -p 8080:8080 --name haengdong-backend-dev haengdong/haengdong-backend-dev + run: sudo docker run -d -p 8080:8080 --name haengdong-backend-dev ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev From ee1030c6ca49d0e1a4baa472a519dd29675fdacd Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:07:51 +0900 Subject: [PATCH 102/273] =?UTF-8?q?feat:=202=EC=B0=A8=20=EC=8A=A4=ED=94=84?= =?UTF-8?q?=EB=A6=B0=ED=8A=B8=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=8B=9C?= =?UTF-8?q?=EC=8A=A4=ED=85=9C=20=EC=88=98=EC=A0=95=20(#83)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> --- HDesign/package-lock.json | 561 ++---------------- HDesign/package.json | 3 +- HDesign/src/components/BillItem/BillItem.tsx | 2 +- .../BottomSheet/BottomSheet.stories.tsx | 20 +- .../BottomSheet/BottomSheet.style.ts | 2 +- .../components/BottomSheet/BottomSheet.tsx | 10 +- .../BottomSheet/BottomSheet.type.ts | 5 +- .../components/BottomSheet/useBottomSheet.ts | 23 +- .../components/ExpenseList/ExpenseList.tsx | 12 +- .../ExpenseList/ExpenseList.type.ts | 4 +- .../FixedButton/FixedButton.style.ts | 5 +- HDesign/src/components/Flex/Flex.style.ts | 45 ++ HDesign/src/components/Flex/Flex.tsx | 35 +- HDesign/src/components/Flex/Flex.type.ts | 9 +- .../InOutItem/InOutItem.stories.tsx | 4 +- .../components/InOutItem/InOutItem.style.ts | 4 +- .../src/components/InOutItem/InOutItem.tsx | 18 +- .../components/InOutItem/InOutItem.type.ts | 2 +- HDesign/src/components/Input/Input.style.ts | 2 +- .../src/components/Search/Search.stories.tsx | 4 +- HDesign/src/components/StepItem/StepItem.tsx | 2 +- .../src/components/Switch/Switch.stories.tsx | 4 - HDesign/src/components/Switch/Switch.tsx | 15 +- HDesign/src/components/Switch/Switch.type.ts | 3 +- HDesign/src/components/Switch/useSwitch.ts | 24 - HDesign/src/components/Tab/Tab.stories.tsx | 26 - HDesign/src/components/Tab/Tab.tsx | 55 -- HDesign/src/components/Tab/Tab.type.ts | 8 - HDesign/src/components/Tabs/Tab.tsx | 8 + HDesign/src/components/Tabs/Tab.type.ts | 16 + HDesign/src/components/Tabs/Tabs.stories.tsx | 31 + .../{Tab/Tab.style.ts => Tabs/Tabs.style.ts} | 12 - HDesign/src/components/Tabs/Tabs.tsx | 53 ++ HDesign/src/components/Title/Title.tsx | 4 +- HDesign/src/components/TopNav/Back.tsx | 17 + .../src/components/TopNav/TopNav.stories.ts | 29 - .../src/components/TopNav/TopNav.stories.tsx | 50 ++ HDesign/src/components/TopNav/TopNav.style.ts | 7 + HDesign/src/components/TopNav/TopNav.tsx | 34 +- HDesign/src/components/TopNav/TopNav.type.ts | 5 - HDesign/src/index.tsx | 10 +- HDesign/src/layouts/ContentLayout.tsx | 25 + HDesign/src/layouts/MainLayout.tsx | 18 +- HDesign/src/theme/GlobalStyle.ts | 4 + client/src/pages/Main/Main.tsx | 2 + server/.gitignore | 244 -------- server/Dockerfile | 9 - server/build.gradle | 40 -- server/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - server/gradlew | 249 -------- server/gradlew.bat | 92 --- server/settings.gradle | 1 - .../haengdong/HaengdongApplication.java | 13 - .../haengdong/application/ActionService.java | 37 -- .../application/BillActionService.java | 44 -- .../haengdong/application/EventService.java | 91 --- .../application/MemberActionFactory.java | 82 --- .../application/MemberActionService.java | 60 -- .../request/BillActionAppRequest.java | 14 - .../application/request/EventAppRequest.java | 10 - .../request/MemberActionSaveAppRequest.java | 12 - .../request/MemberActionsSaveAppRequest.java | 6 - .../response/ActionAppResponse.java | 54 -- .../response/CurrentMemberAppResponse.java | 10 - .../response/EventAppResponse.java | 10 - .../response/EventDetailAppResponse.java | 10 - .../response/MemberBillReportAppResponse.java | 4 - .../server/haengdong/config/WebConfig.java | 27 - .../haengdong/domain/action/Action.java | 42 -- .../domain/action/ActionRepository.java | 21 - .../haengdong/domain/action/BillAction.java | 70 --- .../domain/action/BillActionRepository.java | 14 - .../domain/action/CurrentMembers.java | 66 --- .../haengdong/domain/action/MemberAction.java | 62 -- .../domain/action/MemberActionRepository.java | 15 - .../domain/action/MemberActionStatus.java | 19 - .../domain/action/MemberBillReport.java | 75 --- .../domain/action/MemberGroupIdProvider.java | 11 - .../server/haengdong/domain/event/Event.java | 54 -- .../domain/event/EventRepository.java | 11 - .../haengdong/domain/event/EventStep.java | 28 - .../domain/event/EventTokenProvider.java | 12 - .../haengdong/exception/ErrorResponse.java | 10 - .../exception/GlobalExceptionHandler.java | 43 -- .../exception/HaengdongErrorCode.java | 24 - .../exception/HaengdongException.java | 32 - .../presentation/ActionController.java | 26 - .../presentation/BillActionController.java | 29 - .../presentation/EventController.java | 43 -- .../presentation/MemberActionController.java | 39 -- .../request/BillActionSaveRequest.java | 19 - .../request/BillActionsSaveRequest.java | 14 - .../request/EventSaveRequest.java | 15 - .../request/MemberActionsSaveRequest.java | 22 - .../presentation/response/ActionResponse.java | 20 - .../response/ActionsResponse.java | 28 - .../response/CurrentMemberResponse.java | 10 - .../response/CurrentMembersResponse.java | 15 - .../response/EventDetailResponse.java | 10 - .../presentation/response/EventResponse.java | 10 - .../response/MemberBillReportResponse.java | 10 - .../response/MemberBillReportsResponse.java | 15 - .../presentation/response/StepResponse.java | 57 -- server/src/main/resources/application.yml | 31 - server/src/main/resources/config | 1 - .../application/ActionServiceTest.java | 79 --- .../application/BillActionServiceTest.java | 65 -- .../application/EventServiceTest.java | 110 ---- .../application/MemberActionFactoryTest.java | 217 ------- .../application/MemberActionServiceTest.java | 92 --- .../haengdong/domain/action/ActionTest.java | 30 - .../domain/action/BillActionTest.java | 58 -- .../domain/action/CurrentMembersTest.java | 58 -- .../domain/action/MemberBillReportTest.java | 43 -- .../haengdong/domain/event/EventTest.java | 37 -- .../presentation/ActionControllerTest.java | 49 -- .../BillActionControllerTest.java | 69 --- .../presentation/EventControllerTest.java | 66 --- .../MemberActionControllerTest.java | 67 --- .../response/StepResponseTest.java | 57 -- server/src/test/resources/application.yml | 18 - 122 files changed, 439 insertions(+), 4057 deletions(-) create mode 100644 HDesign/src/components/Flex/Flex.style.ts delete mode 100644 HDesign/src/components/Switch/useSwitch.ts delete mode 100644 HDesign/src/components/Tab/Tab.stories.tsx delete mode 100644 HDesign/src/components/Tab/Tab.tsx delete mode 100644 HDesign/src/components/Tab/Tab.type.ts create mode 100644 HDesign/src/components/Tabs/Tab.tsx create mode 100644 HDesign/src/components/Tabs/Tab.type.ts create mode 100644 HDesign/src/components/Tabs/Tabs.stories.tsx rename HDesign/src/components/{Tab/Tab.style.ts => Tabs/Tabs.style.ts} (82%) create mode 100644 HDesign/src/components/Tabs/Tabs.tsx create mode 100644 HDesign/src/components/TopNav/Back.tsx delete mode 100644 HDesign/src/components/TopNav/TopNav.stories.ts create mode 100644 HDesign/src/components/TopNav/TopNav.stories.tsx delete mode 100644 HDesign/src/components/TopNav/TopNav.type.ts create mode 100644 HDesign/src/layouts/ContentLayout.tsx delete mode 100644 server/.gitignore delete mode 100644 server/Dockerfile delete mode 100644 server/build.gradle delete mode 100644 server/gradle/wrapper/gradle-wrapper.jar delete mode 100644 server/gradle/wrapper/gradle-wrapper.properties delete mode 100755 server/gradlew delete mode 100644 server/gradlew.bat delete mode 100644 server/settings.gradle delete mode 100644 server/src/main/java/server/haengdong/HaengdongApplication.java delete mode 100644 server/src/main/java/server/haengdong/application/ActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/BillActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/EventService.java delete mode 100644 server/src/main/java/server/haengdong/application/MemberActionFactory.java delete mode 100644 server/src/main/java/server/haengdong/application/MemberActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/EventAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/response/ActionAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/EventAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/config/WebConfig.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/Action.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/ActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillAction.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/CurrentMembers.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberAction.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberBillReport.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/Event.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventStep.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java delete mode 100644 server/src/main/java/server/haengdong/exception/ErrorResponse.java delete mode 100644 server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java delete mode 100644 server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java delete mode 100644 server/src/main/java/server/haengdong/exception/HaengdongException.java delete mode 100644 server/src/main/java/server/haengdong/presentation/ActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/BillActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/EventController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/MemberActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/EventResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/StepResponse.java delete mode 100644 server/src/main/resources/application.yml delete mode 160000 server/src/main/resources/config delete mode 100644 server/src/test/java/server/haengdong/application/ActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/BillActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/EventServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java delete mode 100644 server/src/test/java/server/haengdong/application/MemberActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/ActionTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/BillActionTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/event/EventTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/ActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/EventControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java delete mode 100644 server/src/test/resources/application.yml diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index d6b1de8f4..3747523df 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.3", + "version": "0.1.35", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.3", + "version": "0.1.35", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", @@ -45,6 +45,7 @@ "globals": "^15.8.0", "prettier": "3.3.2", "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", "ts-loader": "^9.5.1", "tsc-alias": "^1.8.10", "typescript": "^5.5.3", @@ -2322,358 +2323,6 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/win32-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", @@ -4438,150 +4087,6 @@ } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.7.tgz", - "integrity": "sha512-bZLVHPTpH3h6yhwVl395k0Mtx8v6CGhq5r4KQdAoPbADU974Mauz1b6ViHAJ74O0IVE5vyy7tD3OpkQxL/vMDQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.7.tgz", - "integrity": "sha512-RpUyu2GsviwTc2qVajPL0l8nf2vKj5wzO3WkLSHAHEJbiUZk83NJrZd1RVbEknIMO7+Uyjh54hEh8R26jSByaw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.7.tgz", - "integrity": "sha512-cTZWTnCXLABOuvWiv6nQQM0hP6ZWEkzdgDvztgHI/+u/MvtzJBN5lBQ2lue/9sSFYLMqzqff5EHKlFtrJCA9dQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.7.tgz", - "integrity": "sha512-hoeTJFBiE/IJP30Be7djWF8Q5KVgkbDtjySmvYLg9P94bHg9TJPSQoC72tXx/oXOgXvElDe/GMybru0UxhKx4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.7.tgz", - "integrity": "sha512-+NDhK+IFTiVK1/o7EXdCeF2hEzCiaRSrb9zD7X2Z7inwWlxAntcSuzZW7Y6BRqGQH89KA91qYgwbnjgTQ22PiQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.7.tgz", - "integrity": "sha512-25GXpJmeFxKB+7pbY7YQLhWWjkYlR+kHz5I3j9WRl3Lp4v4UD67OGXwPe+DIcHqcouA1fhLhsgHJWtsaNOMBNg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.7.tgz", - "integrity": "sha512-0VN9Y5EAPBESmSPPsCJzplZHV26akC0sIgd3Hc/7S/1GkSMoeuVL+V9vt+F/cCuzr4VidzSkqftdP3qEIsXSpg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.7.tgz", - "integrity": "sha512-RtoNnstBwy5VloNCvmvYNApkTmuCe4sNcoYWpmY7C1+bPR+6SOo8im1G6/FpNem8AR5fcZCmXHWQ+EUmRWJyuA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.7.tgz", - "integrity": "sha512-Xm0TfvcmmspvQg1s4+USL3x8D+YPAfX2JHygvxAnCJ0EHun8cm2zvfNBcsTlnwYb0ybFWXXY129aq1wgFC9TpQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/core-win32-x64-msvc": { "version": "1.5.7", "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.7.tgz", @@ -6671,6 +6176,12 @@ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -8895,20 +8406,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -11786,6 +11283,15 @@ "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", "dev": true }, + "node_modules/react-inspector": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz", + "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==", + "dev": true, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -12518,6 +12024,37 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/storybook-addon-react-router-v6": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/storybook-addon-react-router-v6/-/storybook-addon-react-router-v6-2.0.15.tgz", + "integrity": "sha512-4vOYIQwehlQLyXaCT9K0Iu0po2Z+pANGsqkfm/BQuAEjE9MoN7vrsrQLHINhKbmQVtNMmuS/oBR3GGNbqQ1gew==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "compare-versions": "^6.0.0", + "react-inspector": "6.0.2" + }, + "peerDependencies": { + "@storybook/blocks": "^7.0.0", + "@storybook/channels": "^7.0.0", + "@storybook/components": "^7.0.0", + "@storybook/core-events": "^7.0.0", + "@storybook/manager-api": "^7.0.0", + "@storybook/preview-api": "^7.0.0", + "@storybook/theming": "^7.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-router-dom": "^6.4.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/storybook/node_modules/commander": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", diff --git a/HDesign/package.json b/HDesign/package.json index b077aa3ba..b587d3be8 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.3", + "version": "0.1.35", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", @@ -49,6 +49,7 @@ "globals": "^15.8.0", "prettier": "3.3.2", "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", "ts-loader": "^9.5.1", "tsc-alias": "^1.8.10", "typescript": "^5.5.3", diff --git a/HDesign/src/components/BillItem/BillItem.tsx b/HDesign/src/components/BillItem/BillItem.tsx index bf5d916cd..f73c5d32d 100644 --- a/HDesign/src/components/BillItem/BillItem.tsx +++ b/HDesign/src/components/BillItem/BillItem.tsx @@ -25,7 +25,7 @@ export const BillItem: React.FC<BillItemProps> = ({ {name} </Text> <Text css={textStyle(theme)} size="body"> - {price.toLocaleString('ko-kr')} 원 + {price.toLocaleString('ko-kr')}원 </Text> </Flex> </DragHandleItem> diff --git a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx b/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx index 943dfa46b..48288fb6c 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx +++ b/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx @@ -14,19 +14,15 @@ const meta = { // layout: 'centered', }, argTypes: { - fixedButtonVariants: { + fixedButtonProps: { description: '', - control: {type: 'select'}, - options: ['', 'primary', 'secondary', 'tertiary'], - }, - fixedButtonText: { - description: '', - control: {type: 'text'}, + control: {type: 'object'}, }, }, args: { - fixedButtonVariants: 'primary', - fixedButtonText: '하단 고정 버튼이에요', + fixedButtonProps: { + variants: 'primary', + }, }, } satisfies Meta<typeof BottomSheet>; @@ -36,8 +32,10 @@ type Story = StoryObj<typeof meta>; export const Playground: Story = { args: { - fixedButtonVariants: 'primary', - fixedButtonText: '하단 고정 버튼이에요', + fixedButtonProps: { + variants: 'primary', + children: '하단 고정 버튼', + }, }, render: ({...args}) => { const [isOpened, setIsOpened] = useState(false); diff --git a/HDesign/src/components/BottomSheet/BottomSheet.style.ts b/HDesign/src/components/BottomSheet/BottomSheet.style.ts index c2dd93fb3..4968206f1 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.style.ts +++ b/HDesign/src/components/BottomSheet/BottomSheet.style.ts @@ -16,7 +16,7 @@ export const dimmedLayerStyle = (theme: Theme) => export const bottomSheetContainerStyle = (theme: Theme) => css({ - position: 'absolute', + position: 'fixed', display: 'flex', flexDirection: 'column', alignItems: 'center', diff --git a/HDesign/src/components/BottomSheet/BottomSheet.tsx b/HDesign/src/components/BottomSheet/BottomSheet.tsx index 510b428be..d0f286cc8 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.tsx +++ b/HDesign/src/components/BottomSheet/BottomSheet.tsx @@ -2,23 +2,23 @@ import {createPortal} from 'react-dom'; import {BottomSheetProps} from '@components/BottomSheet/BottomSheet.type'; -import {useBottomSheet} from '@components/BottomSheet/useBottomSheet'; import FixedButton from '@components/FixedButton/FixedButton'; import {useTheme} from '@theme/HDesignProvider'; +import {useBottomSheet} from './useBottomSheet'; import {bottomSheetContainerStyle, dimmedLayerStyle, indicatorStyle} from './BottomSheet.style'; const BottomSheet: React.FC<BottomSheetProps> = ({ - fixedButtonVariants = 'primary', isOpened = false, children, - fixedButtonText, + fixedButtonProps, ...props }: BottomSheetProps) => { const {theme} = useTheme(); const {opened, handleClose} = useBottomSheet({isOpened, ...props}); + // TODO: (@todari) : children 길이 길 때 overflow button에 안가리는 영역 처리 return createPortal( <> {opened && ( @@ -27,9 +27,7 @@ const BottomSheet: React.FC<BottomSheetProps> = ({ <div css={bottomSheetContainerStyle(theme)}> <div css={indicatorStyle(theme)} /> {children} - {(fixedButtonVariants || fixedButtonText) && ( - <FixedButton variants={fixedButtonVariants} children={fixedButtonText} /> - )} + {fixedButtonProps && <FixedButton {...fixedButtonProps} />} </div> </> )} diff --git a/HDesign/src/components/BottomSheet/BottomSheet.type.ts b/HDesign/src/components/BottomSheet/BottomSheet.type.ts index 365f9f498..312fe3c29 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.type.ts +++ b/HDesign/src/components/BottomSheet/BottomSheet.type.ts @@ -4,6 +4,8 @@ import {ButtonVariants} from '@components/Button/Button.type'; import {Theme} from '@theme/theme.type'; +import {FixedButtonProps} from '../FixedButton/FixedButton.type'; + export interface BottomSheetStyleProps { theme?: Theme; } @@ -12,8 +14,7 @@ export interface BottomSheetCustomProps { isOpened?: boolean; onChangeOpen?: () => void; onChangeClose?: () => void; - fixedButtonVariants?: ButtonVariants; - fixedButtonText?: string; + fixedButtonProps?: FixedButtonProps; } export type BottomSheetOptionProps = BottomSheetStyleProps & BottomSheetCustomProps; diff --git a/HDesign/src/components/BottomSheet/useBottomSheet.ts b/HDesign/src/components/BottomSheet/useBottomSheet.ts index f67796979..ca2274e19 100644 --- a/HDesign/src/components/BottomSheet/useBottomSheet.ts +++ b/HDesign/src/components/BottomSheet/useBottomSheet.ts @@ -1,23 +1,36 @@ -import {useEffect, useState} from 'react'; +import {useCallback, useEffect, useState} from 'react'; interface UseBottomSheetProps { isOpened: boolean; onChangeClose?: () => void; + onChangeOpen?: () => void; } -export const useBottomSheet = ({isOpened, onChangeClose}: UseBottomSheetProps) => { - const [opened, setOpened] = useState(isOpened); +export const useBottomSheet = ({isOpened, onChangeClose, onChangeOpen}: UseBottomSheetProps) => { + const [opened, setOpened] = useState(false); useEffect(() => { setOpened(isOpened); + if (!isOpened) { + handleClose(); + } else { + handleOpen(); + } }, [isOpened]); - const handleClose = () => { + const handleClose = useCallback(() => { setOpened(false); if (onChangeClose) { onChangeClose(); } - }; + }, []); + + const handleOpen = useCallback(() => { + setOpened(true); + if (onChangeOpen) { + onChangeOpen(); + } + }, []); useEffect(() => { document.body.style.overflow = 'hidden'; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx index 8dbc71858..2990458bb 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.tsx +++ b/HDesign/src/components/ExpenseList/ExpenseList.tsx @@ -2,29 +2,34 @@ import Text from '@components/Text/Text'; + import {Arrow} from '@assets/index'; import {useTheme} from '@theme/HDesignProvider'; +import {useTheme} from '@theme/HDesignProvider'; + import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle, TextStyle} from './ExpenseList.style'; // TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 -function ExpenseItem({name, price}: ExpenseItemProps) { +function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { const {theme} = useTheme(); return ( - <button css={expenseItemStyle}> + <button css={expenseItemStyle} {...buttonProps}> <Text size="bodyBold" css={TextStyle(theme)}> {name} </Text> <div css={expenseItemLeftStyle}> - <Text css={TextStyle(theme)}>{price.toLocaleString('ko-kr')} 원</Text> + <Text css={TextStyle(theme)}>{price.toLocaleString('ko-kr')}원</Text> <Arrow /> </div> </button> ); } +} +function ExpenseList({expenseList = []}: ExpenseListProps) { function ExpenseList({expenseList = []}: ExpenseListProps) { const {theme} = useTheme(); return ( @@ -35,5 +40,6 @@ function ExpenseList({expenseList = []}: ExpenseListProps) { </div> ); } +} export default ExpenseList; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.type.ts b/HDesign/src/components/ExpenseList/ExpenseList.type.ts index 9ab2aa8bb..939cd2f68 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.type.ts +++ b/HDesign/src/components/ExpenseList/ExpenseList.type.ts @@ -1,8 +1,10 @@ -export interface ExpenseItemProps { +export interface ExpenseItemCustomProps { name: string; price: number; } +export type ExpenseItemProps = React.ComponentProps<'button'> & ExpenseItemCustomProps; + export type ExpenseListProps = { expenseList: ExpenseItemProps[]; }; diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/HDesign/src/components/FixedButton/FixedButton.style.ts index dc9f96eab..19e011893 100644 --- a/HDesign/src/components/FixedButton/FixedButton.style.ts +++ b/HDesign/src/components/FixedButton/FixedButton.style.ts @@ -8,9 +8,10 @@ import {Theme} from '@theme/theme.type'; export const fixedButtonContainerStyle = (theme: Theme) => css({ display: 'flex', - position: 'absolute', - + position: 'fixed', + maxWidth: '768px', inset: 'auto 0 0', + margin: '0 auto', backgroundColor: theme.colors.white, boxSizing: 'border-box', }); diff --git a/HDesign/src/components/Flex/Flex.style.ts b/HDesign/src/components/Flex/Flex.style.ts new file mode 100644 index 000000000..c86f1b64d --- /dev/null +++ b/HDesign/src/components/Flex/Flex.style.ts @@ -0,0 +1,45 @@ +import {css} from '@emotion/react'; + +import {changeCamelCaseToKebabCase} from '@/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase'; + +import {FlexDirectionStrictType, FlexProps} from './Flex.type'; + +export const flexStyle = ({ + justifyContent = 'flexStart', + alignItems = 'stretch', + flexDirection = 'row', + gap = '0', + padding = '0', + paddingInline = '0', + margin = '0', + width = 'auto', + height = 'auto', + backgroundColor, + theme, + ...rest +}: FlexProps) => + css({ + display: 'flex', + justifyContent: changeCamelCaseToKebabCase(justifyContent), + alignItems: changeCamelCaseToKebabCase(alignItems), + // TODO: (@weadie) as를 사용하지 않으면 방법이 없음. css의 flexDirection속성은 string을 받지 않고 명확한 속성명(ex row-reverse)를 받고 싶어함. 다만 as를 사용해도 된다고 생각한 근거는 케밥함수가 FlexDirectionType에 명시된 모든 타입을 정확하게 변환하며, 받는 문자열이 FlexDirectionType에 제한되기 때문. + flexDirection: changeCamelCaseToKebabCase(flexDirection) as FlexDirectionStrictType, + gap, + padding, + paddingInline, + margin, + width, + height, + ...rest, + + backgroundColor: (() => { + switch (backgroundColor) { + case 'white': + return theme?.colors.white; + case 'gray': + return theme?.colors.grayContainer; + default: + return 'none'; + } + })(), + }); diff --git a/HDesign/src/components/Flex/Flex.tsx b/HDesign/src/components/Flex/Flex.tsx index 0210669cc..57a5e7332 100644 --- a/HDesign/src/components/Flex/Flex.tsx +++ b/HDesign/src/components/Flex/Flex.tsx @@ -2,40 +2,15 @@ import {css} from '@emotion/react'; import {StrictPropsWithChildren} from '@/types/strictPropsWithChildren'; -import {changeCamelCaseToKebabCase} from '@/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase'; +import {useTheme} from '@/theme/HDesignProvider'; -import {FlexDirectionStrictType, FlexProps} from './Flex.type'; - -const flexStyle = ({ - justifyContent = 'flexStart', - alignItems = 'stretch', - flexDirection = 'row', - gap = '0', - padding = '0', - paddingInline = '0', - margin = '0', - width = 'auto', - height = 'auto', - ...rest -}: FlexProps) => - css({ - display: 'flex', - justifyContent: changeCamelCaseToKebabCase(justifyContent), - alignItems: changeCamelCaseToKebabCase(alignItems), - // TODO: (@weadie) as를 사용하지 않으면 방법이 없음. css의 flexDirection속성은 string을 받지 않고 명확한 속성명(ex row-reverse)를 받고 싶어함. 다만 as를 사용해도 된다고 생각한 근거는 케밥함수가 FlexDirectionType에 명시된 모든 타입을 정확하게 변환하며, 받는 문자열이 FlexDirectionType에 제한되기 때문. - flexDirection: changeCamelCaseToKebabCase(flexDirection) as FlexDirectionStrictType, - gap, - padding, - paddingInline, - margin, - width, - height, - ...rest, - }); +import {FlexProps} from './Flex.type'; +import {flexStyle} from './Flex.style'; // TODO: (@weadie) 지정된 프롭 말고 다른 프롭도 가져올 수 있게 하자. function Flex({children, ...props}: StrictPropsWithChildren<FlexProps>) { - return <div css={flexStyle(props)}>{children}</div>; + const {theme} = useTheme(); + return <div css={flexStyle({theme, ...props})}>{children}</div>; } export default Flex; diff --git a/HDesign/src/components/Flex/Flex.type.ts b/HDesign/src/components/Flex/Flex.type.ts index aeb90bc20..75467e97e 100644 --- a/HDesign/src/components/Flex/Flex.type.ts +++ b/HDesign/src/components/Flex/Flex.type.ts @@ -1,5 +1,8 @@ +import {Theme} from '@/theme/theme.type'; + export type FlexDirectionType = 'row' | 'column' | 'rowReverse' | 'columnReverse'; export type FlexDirectionStrictType = 'row' | 'column' | 'row-reverse' | 'column-reverse'; +export type FlexBackgroundColor = 'gray' | 'white'; export interface FlexProps { justifyContent?: 'flexStart' | 'center' | 'flexEnd' | 'spaceBetween' | 'spaceAround' | 'spaceEvenly'; @@ -11,8 +14,6 @@ export interface FlexProps { margin?: string; width?: string; height?: string; -} - -export interface ExtendedFlexProps extends FlexProps { - [key: string]: string | undefined; + backgroundColor?: FlexBackgroundColor; + theme?: Theme; } diff --git a/HDesign/src/components/InOutItem/InOutItem.stories.tsx b/HDesign/src/components/InOutItem/InOutItem.stories.tsx index 13ea625b5..1805fe0db 100644 --- a/HDesign/src/components/InOutItem/InOutItem.stories.tsx +++ b/HDesign/src/components/InOutItem/InOutItem.stories.tsx @@ -16,12 +16,12 @@ const meta = { }, inOutType: { description: '', - control: {type: 'select', options: ['in', 'out']}, + control: {type: 'select', options: ['IN', 'OUT']}, }, }, args: { names: ['감자', '토다리'], - inOutType: 'out', + inOutType: 'OUT', }, } satisfies Meta<typeof InOutItem>; diff --git a/HDesign/src/components/InOutItem/InOutItem.style.ts b/HDesign/src/components/InOutItem/InOutItem.style.ts index 3137d1908..b3f8eee46 100644 --- a/HDesign/src/components/InOutItem/InOutItem.style.ts +++ b/HDesign/src/components/InOutItem/InOutItem.style.ts @@ -16,7 +16,9 @@ export const prefixStyle = css({ gap: '0.25rem', }); -export const textStyle = (theme: Theme) => +export const textStyle = (theme: Theme, hasDragHandle: boolean) => css({ + paddingLeft: hasDragHandle ? '0' : '0.5rem', + color: theme.colors.black, }); diff --git a/HDesign/src/components/InOutItem/InOutItem.tsx b/HDesign/src/components/InOutItem/InOutItem.tsx index 7cc99622f..9393c5e20 100644 --- a/HDesign/src/components/InOutItem/InOutItem.tsx +++ b/HDesign/src/components/InOutItem/InOutItem.tsx @@ -3,17 +3,23 @@ import React from 'react'; import Text from '@components/Text/Text'; +import Text from '@components/Text/Text'; + import {useTheme} from '@theme/HDesignProvider'; -import IconButton from '../IconButton/IconButton'; import DragHandleItem from '../DragHandleItem/DragHandleItem'; -import {InOutItemProps} from './InOutItem.type'; -import {prefixStyle, textStyle} from './InOutItem.style'; +import {InOutItemProps, InOutType} from './InOutItem.type'; +import {textStyle} from './InOutItem.style'; + +const IN_OUT_TEXT: Record<InOutType, string> = { + IN: '들어옴', + OUT: '나감', +}; export const InOutItem: React.FC<InOutItemProps> = ({ names = [], - inOutType = 'out', + inOutType = 'OUT', hasDragHandle = false, ...htmlProps }: InOutItemProps) => { @@ -22,8 +28,8 @@ export const InOutItem: React.FC<InOutItemProps> = ({ // TODO: (@toari) : 사람 수 많을 때 UX writing 처리 return ( <DragHandleItem {...htmlProps} hasDragHandle={hasDragHandle}> - <Text css={textStyle(theme)} size="captionBold"> - {names.join(', ')} {inOutType === 'out' ? '나감' : '들어옴'} + <Text css={textStyle(theme, hasDragHandle)} size="bodyBold"> + {names.join(', ')} {IN_OUT_TEXT[inOutType]} </Text> </DragHandleItem> ); diff --git a/HDesign/src/components/InOutItem/InOutItem.type.ts b/HDesign/src/components/InOutItem/InOutItem.type.ts index 0a7459ccc..2872e5d55 100644 --- a/HDesign/src/components/InOutItem/InOutItem.type.ts +++ b/HDesign/src/components/InOutItem/InOutItem.type.ts @@ -1,4 +1,4 @@ -export type InOutType = 'in' | 'out'; +export type InOutType = 'IN' | 'OUT'; export interface InOutItemStyleProps {} diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts index aeedfeb50..50980be64 100644 --- a/HDesign/src/components/Input/Input.style.ts +++ b/HDesign/src/components/Input/Input.style.ts @@ -21,7 +21,7 @@ export const inputBoxStyle = (theme: Theme, inputType: InputType = 'input') => css({ display: 'flex', justifyContent: 'space-between', - marginInline: '1rem', + padding: '0.75rem 1rem', borderRadius: '1rem', backgroundColor: inputBoxBackgroundColorByInputType(theme, inputType), diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx index d52f74053..f4cd6d567 100644 --- a/HDesign/src/components/Search/Search.stories.tsx +++ b/HDesign/src/components/Search/Search.stories.tsx @@ -2,6 +2,8 @@ import type {Meta, StoryObj} from '@storybook/react'; import React from 'react'; +import React from 'react'; + import Search from '@components/Search/Search'; const meta = { @@ -24,7 +26,7 @@ const meta = { disabled: false, placeholder: 'placeholder', searchTerms: ['todari', 'cookie'], - setKeyword: (keyword: string) => console.log(keyword), + setState: keyword => console.log(keyword), }, } satisfies Meta<typeof Search>; diff --git a/HDesign/src/components/StepItem/StepItem.tsx b/HDesign/src/components/StepItem/StepItem.tsx index 6f096db12..52e79d863 100644 --- a/HDesign/src/components/StepItem/StepItem.tsx +++ b/HDesign/src/components/StepItem/StepItem.tsx @@ -34,7 +34,7 @@ export const StepItem: React.FC<StepItemCustomProps> = ({ 총액 </Text> <Text css={totalAmountStyle(theme)} size="caption"> - {bills.reduce((acc, prev) => acc + (prev.price ?? 0), 0).toLocaleString('ko-kr')} 원 + {bills.reduce((acc, prev) => acc + (prev.price ?? 0), 0).toLocaleString('ko-kr')}원 </Text> </Flex> </div> diff --git a/HDesign/src/components/Switch/Switch.stories.tsx b/HDesign/src/components/Switch/Switch.stories.tsx index 121e20992..a3558754a 100644 --- a/HDesign/src/components/Switch/Switch.stories.tsx +++ b/HDesign/src/components/Switch/Switch.stories.tsx @@ -14,9 +14,6 @@ const meta = { description: '', control: {type: 'select', options: ['홈', '관리']}, }, - initialValue: { - description: '', - }, values: { description: '', }, @@ -26,7 +23,6 @@ const meta = { }, args: { value: '홈', - initialValue: '홈', values: ['홈', '관리'], onChange: value => alert(`${value} 선택됨`), }, diff --git a/HDesign/src/components/Switch/Switch.tsx b/HDesign/src/components/Switch/Switch.tsx index 17118a6fa..4a1275185 100644 --- a/HDesign/src/components/Switch/Switch.tsx +++ b/HDesign/src/components/Switch/Switch.tsx @@ -3,21 +3,18 @@ import TextButton from '../TextButton/TextButton'; import {switchContainerStyle} from './Switch.style'; import {SwitchProps} from './Switch.type'; -import {useSwitch} from './useSwitch'; - -function Switch({value = '', initialValue, values, onChange}: SwitchProps) { - const {selectedValue, handleClick} = useSwitch({value, initialValue, values, onChange}); +function Switch({value, values, onChange}: SwitchProps) { return ( <div css={switchContainerStyle}> - {values.map((value, index) => ( + {values.map((item, index) => ( <TextButton - key={`${index}_${value}`} - textColor={selectedValue === value ? 'black' : 'gray'} + key={`${index}_${item}`} + textColor={value === item ? 'black' : 'gray'} textSize="bodyBold" - onClick={() => handleClick(index)} + onClick={() => onChange(values[index])} > - {value} + {item} </TextButton> ))} </div> diff --git a/HDesign/src/components/Switch/Switch.type.ts b/HDesign/src/components/Switch/Switch.type.ts index ec73febd0..7e0d31d0f 100644 --- a/HDesign/src/components/Switch/Switch.type.ts +++ b/HDesign/src/components/Switch/Switch.type.ts @@ -1,6 +1,5 @@ export interface SwitchProps { - value?: string; - initialValue?: string; + value: string; values: string[]; onChange: (value: string) => void; } diff --git a/HDesign/src/components/Switch/useSwitch.ts b/HDesign/src/components/Switch/useSwitch.ts deleted file mode 100644 index ecfbb0633..000000000 --- a/HDesign/src/components/Switch/useSwitch.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {useEffect, useState} from 'react'; - -interface UseSwitchProps { - value: string; - initialValue?: string; - values: string[]; - onChange: (value: string) => void; -} - -export const useSwitch = ({value, initialValue, values, onChange}: UseSwitchProps) => { - const [selectedValue, setSelectedValue] = useState(initialValue ?? value); - - useEffect(() => { - setSelectedValue(value); - onChange(value); - }, [value]); - - const handleClick = (index: number) => { - setSelectedValue(values[index]); - onChange(values[index]); - }; - - return {selectedValue, handleClick}; -}; diff --git a/HDesign/src/components/Tab/Tab.stories.tsx b/HDesign/src/components/Tab/Tab.stories.tsx deleted file mode 100644 index e92495e1a..000000000 --- a/HDesign/src/components/Tab/Tab.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import React from 'react'; - -import Tab from '@components/Tab/Tab'; - -const meta = { - title: 'Components/Tab', - component: Tab, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - args: { - tabs: [ - {label: '전체 지출 내역', content: <div>없지롱</div>}, - {label: '참여자 별 정산', content: <div>있지롱</div>}, - ], - }, -} satisfies Meta<typeof Tab>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/Tab/Tab.tsx b/HDesign/src/components/Tab/Tab.tsx deleted file mode 100644 index 4981b9e92..000000000 --- a/HDesign/src/components/Tab/Tab.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {css} from '@emotion/react'; -import React, {useState} from 'react'; - -import Text from '@components/Text/Text'; - -import {useTheme} from '@theme/HDesignProvider'; - -import {tabListStyle, tabTextStyle, tabStyle, tabItemStyle, indicatorStyle} from './Tab.style'; -import {TabsProps} from './Tab.type'; - -const Tab: React.FC<TabsProps> = ({tabs}) => { - const {theme} = useTheme(); - const [activeTabIndex, setActiveTabIndex] = useState(0); - - const isActive = (index: number) => { - return activeTabIndex === index; - }; - - return ( - <section css={tabStyle}> - <ul role="tablist" css={tabListStyle(theme)}> - {tabs.map((tab, index) => ( - <li - key={tab.label} - role="tab" - id={`tab-${tab.label}`} - css={tabItemStyle} - aria-selected={isActive(index)} - onClick={() => setActiveTabIndex(index)} - aria-controls={`tabpanel-${tab.label}`} - > - <Text css={tabTextStyle(theme, isActive(index))} size={isActive(index) ? 'bodyBold' : 'body'}> - {tab.label} - </Text> - </li> - ))} - <div css={indicatorStyle(theme, `${(activeTabIndex * 100) / tabs.length}%`, tabs.length)} /> - </ul> - {tabs.map((tab, index) => ( - <section - key={tab.label} - role="tabpanel" - id={`tabpanel-${tab.label}`} - aria-labelledby={`tab-${tab.label}`} - hidden={activeTabIndex !== index} - > - {tab.content} - </section> - ))} - </section> - ); -}; - -export default Tab; diff --git a/HDesign/src/components/Tab/Tab.type.ts b/HDesign/src/components/Tab/Tab.type.ts deleted file mode 100644 index 80ddd4ef9..000000000 --- a/HDesign/src/components/Tab/Tab.type.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface TabProps { - label: string; - content: React.ReactNode; -} - -export interface TabsProps { - tabs: TabProps[]; -} diff --git a/HDesign/src/components/Tabs/Tab.tsx b/HDesign/src/components/Tabs/Tab.tsx new file mode 100644 index 000000000..2a79c1b78 --- /dev/null +++ b/HDesign/src/components/Tabs/Tab.tsx @@ -0,0 +1,8 @@ +/** @jsxImportSource @emotion/react */ +import {TabProps} from './Tab.type'; + +const Tab: React.FC<TabProps> = () => { + return <></>; +}; + +export default Tab; diff --git a/HDesign/src/components/Tabs/Tab.type.ts b/HDesign/src/components/Tabs/Tab.type.ts new file mode 100644 index 000000000..6b9e4972e --- /dev/null +++ b/HDesign/src/components/Tabs/Tab.type.ts @@ -0,0 +1,16 @@ +import {FlexProps} from '../Flex/Flex.type'; + +export interface TabProps { + label: string; + content: React.ReactNode; +} + +export interface TabsCustomProps { + children: React.ReactElement<TabProps>[]; +} + +export interface TabsStyleProps { + tabsContainerStyle?: FlexProps; +} + +export type TabsProps = TabsCustomProps & TabsStyleProps; diff --git a/HDesign/src/components/Tabs/Tabs.stories.tsx b/HDesign/src/components/Tabs/Tabs.stories.tsx new file mode 100644 index 000000000..6d03a7406 --- /dev/null +++ b/HDesign/src/components/Tabs/Tabs.stories.tsx @@ -0,0 +1,31 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import React from 'react'; + +import Tabs from '@/components/Tabs/Tabs'; + +import Tab from './Tab'; + +const meta = { + title: 'Components/Tabs', + component: Tabs, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + args: { + children: [ + <Tab label="전체 지출 내역" content={<div>없지롱</div>} />, + <Tab label="참여자 별 정산" content={<div>있지롱</div>} />, + ], + tabsContainerStyle: { + gap: '0.5rem', + }, + }, +} satisfies Meta<typeof Tabs>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Tab/Tab.style.ts b/HDesign/src/components/Tabs/Tabs.style.ts similarity index 82% rename from HDesign/src/components/Tab/Tab.style.ts rename to HDesign/src/components/Tabs/Tabs.style.ts index b038fadd1..a4a12f630 100644 --- a/HDesign/src/components/Tab/Tab.style.ts +++ b/HDesign/src/components/Tabs/Tabs.style.ts @@ -2,21 +2,9 @@ import {css} from '@emotion/react'; import {Theme} from '@/theme/theme.type'; -export const tabStyle = css({ - display: 'flex', - flexDirection: 'column', - - width: '100%', -}); - export const tabListStyle = (theme: Theme) => css({ - display: 'flex', position: 'relative', - justifyContent: 'space-between', - alignItems: 'center', - - padding: '0.5rem', backgroundColor: theme.colors.white, diff --git a/HDesign/src/components/Tabs/Tabs.tsx b/HDesign/src/components/Tabs/Tabs.tsx new file mode 100644 index 000000000..0245b5ba7 --- /dev/null +++ b/HDesign/src/components/Tabs/Tabs.tsx @@ -0,0 +1,53 @@ +/** @jsxImportSource @emotion/react */ +import React, {useState} from 'react'; +import {css} from '@emotion/react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {tabListStyle, indicatorStyle, tabItemStyle, tabTextStyle} from './Tabs.style'; +import {TabsProps} from './Tab.type'; + +const Tabs: React.FC<TabsProps> = ({children, tabsContainerStyle}) => { + const {theme} = useTheme(); + const [activeTabIndex, setActiveTabIndex] = useState(0); + + const isActive = (index: number) => activeTabIndex === index; + const tabItemCount = children.length; + + return ( + <Flex flexDirection="column" {...tabsContainerStyle}> + <ul role="tablist" css={tabListStyle(theme)}> + <Flex justifyContent="spaceBetween" alignItems="center" padding="0.5rem"> + {children.map((tabItem, index) => ( + <li + key={tabItem.props.label} + role="tab" + id={`tab-${tabItem.props.label}`} + css={tabItemStyle} + aria-selected={isActive(index)} + onClick={() => setActiveTabIndex(index)} + aria-controls={`tabpanel-${tabItem.props.label}`} + > + <Text css={tabTextStyle(theme, isActive(index))} size={isActive(index) ? 'bodyBold' : 'body'}> + {tabItem.props.label} + </Text> + </li> + ))} + <div css={indicatorStyle(theme, `${(activeTabIndex * 100) / tabItemCount}%`, tabItemCount)} /> + </Flex> + </ul> + <section + role="tabpanel" + id={`tabpanel-${children[activeTabIndex].props.label}`} + aria-labelledby={`tab-${children[activeTabIndex].props.label}}`} + > + {children[activeTabIndex].props.content} + </section> + </Flex> + ); +}; + +export default Tabs; diff --git a/HDesign/src/components/Title/Title.tsx b/HDesign/src/components/Title/Title.tsx index 5901bc350..ee7847a0e 100644 --- a/HDesign/src/components/Title/Title.tsx +++ b/HDesign/src/components/Title/Title.tsx @@ -24,12 +24,12 @@ export const Title: React.FC<TitleProps> = ({title, description, price}: TitlePr {description} </Text> )} - {price && ( + {price !== undefined && ( <div css={priceContainerStyle}> <Text css={priceTitleStyle(theme)} size="caption"> 전체 지출 금액 </Text> - <Text css={priceStyle(theme)}>{price.toLocaleString('ko-kr')} 원</Text> + <Text css={priceStyle(theme)}>{price.toLocaleString('ko-kr')}원</Text> </div> )} </div> diff --git a/HDesign/src/components/TopNav/Back.tsx b/HDesign/src/components/TopNav/Back.tsx new file mode 100644 index 000000000..cfb55e24d --- /dev/null +++ b/HDesign/src/components/TopNav/Back.tsx @@ -0,0 +1,17 @@ +/** @jsxImportSource @emotion/react */ +import React from 'react'; +import {useNavigate} from 'react-router-dom'; + +import TextButton from '@components/TextButton/TextButton'; + +function Back() { + const navigate = useNavigate(); + + return ( + <TextButton onClick={() => navigate(-1)} textSize="bodyBold" textColor="gray"> + 뒤로가기 + </TextButton> + ); +} + +export default Back; diff --git a/HDesign/src/components/TopNav/TopNav.stories.ts b/HDesign/src/components/TopNav/TopNav.stories.ts deleted file mode 100644 index f231e8bd7..000000000 --- a/HDesign/src/components/TopNav/TopNav.stories.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import TopNav from '@components/TopNav/TopNav'; - -import Switch from '../Switch/Switch'; - -const meta = { - title: 'Components/TopNav', - component: TopNav, - tags: ['autodocs'], - parameters: { - layout: 'centered', - }, - argTypes: { - navType: { - description: '', - control: {type: 'select', options: ['back', 'home']}, - }, - }, - args: { - navType: 'back', - }, -} satisfies Meta<typeof TopNav>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/TopNav/TopNav.stories.tsx b/HDesign/src/components/TopNav/TopNav.stories.tsx new file mode 100644 index 000000000..0c96161a5 --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.stories.tsx @@ -0,0 +1,50 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import React from 'react'; +import {reactRouterParameters, withRouter} from 'storybook-addon-react-router-v6'; + +import TopNav from '@components/TopNav/TopNav'; + +import Switch from '../Switch/Switch'; + +import Back from './Back'; + +const meta = { + title: 'Components/TopNav', + component: TopNav, + tags: ['autodocs'], + decorators: [withRouter], + parameters: { + reactRouter: reactRouterParameters({ + location: { + pathParams: { + eventId: '123123', + }, + }, + routing: {path: '/event/:eventId/home'}, + }), + // layout: 'centered', + }, + argTypes: { + children: { + description: '', + control: {type: 'select'}, + options: ['Back', 'Switch', 'Any'], + mapping: { + Back: <Back />, + Switch: <Switch values={['홈', '관리']} value="홈" onChange={value => console.log(value)} />, + Any: <div />, + }, + }, + }, + args: { + children: 'Back', + }, +} satisfies Meta<typeof TopNav>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/HDesign/src/components/TopNav/TopNav.style.ts index 88910da47..44e7695e7 100644 --- a/HDesign/src/components/TopNav/TopNav.style.ts +++ b/HDesign/src/components/TopNav/TopNav.style.ts @@ -5,3 +5,10 @@ export const topNavStyle = css({ padding: '0 1rem', width: '100%', }); + +export const topNavNonStyle = css({ + display: 'flex', + padding: '0 1rem', + width: '100%', + height: '1.5rem', +}); diff --git a/HDesign/src/components/TopNav/TopNav.tsx b/HDesign/src/components/TopNav/TopNav.tsx index bcfa72260..643cd5e3b 100644 --- a/HDesign/src/components/TopNav/TopNav.tsx +++ b/HDesign/src/components/TopNav/TopNav.tsx @@ -1,26 +1,20 @@ -import {useNavigate} from 'react-router-dom'; +/** @jsxImportSource @emotion/react */ +import React from 'react'; -import TextButton from '../TextButton/TextButton'; -import Switch from '../Switch/Switch'; +import Switch from '@components/Switch/Switch'; -import {topNavStyle} from './TopNav.style'; -import {TopNavProps} from './TopNav.type'; +import {topNavNonStyle, topNavStyle} from './TopNav.style'; +import Back from './Back'; -// TODO: (@todari) navigation으로 인해 storybook 동작하지 않는 오류 해결해야함 -// + 페이지 정하는 것에 따라, navigate 경로 수정해 줘야 함 -function TopNav({navType}: TopNavProps) { - const navigate = useNavigate(); - return ( - <div css={topNavStyle}> - {navType === 'back' ? ( - <TextButton onClick={() => navigate(-1)} textSize="bodyBold" textColor="gray"> - 뒤로가기 - </TextButton> - ) : ( - <Switch values={['홈', '관리']} onChange={() => navigate('./')} /> - )} - </div> +const TopNav: React.FC<React.PropsWithChildren> = ({children}) => { + const hasBack = React.Children.toArray(children).some(child => React.isValidElement(child) && child.type === Back); + const hasSwitch = React.Children.toArray(children).some( + child => React.isValidElement(child) && child.type === Switch, ); -} + + const isExistNav = hasBack || hasSwitch; + + return <div css={isExistNav ? topNavStyle : topNavNonStyle}>{children}</div>; +}; export default TopNav; diff --git a/HDesign/src/components/TopNav/TopNav.type.ts b/HDesign/src/components/TopNav/TopNav.type.ts deleted file mode 100644 index c84e21894..000000000 --- a/HDesign/src/components/TopNav/TopNav.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type NavType = 'back' | 'home'; - -export interface TopNavProps { - navType: NavType; -} diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index 7f941ad5f..e0b6e6fee 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -11,17 +11,21 @@ import Input from '@components/Input/Input'; import Search from '@components/Search/Search'; import StepItem from '@components/StepItem/StepItem'; import Switch from '@components/Switch/Switch'; -import Tab from '@components/Tab/Tab'; +import Tabs from '@/components/Tabs/Tabs'; import Text from '@components/Text/Text'; import TextButton from '@components/TextButton/TextButton'; import Title from '@components/Title/Title'; import TopNav from '@components/TopNav/TopNav'; - import {MainLayout} from '@layouts/MainLayout'; +import {ContentLayout} from '@layouts/ContentLayout'; import {HDesignProvider} from '@theme/HDesignProvider'; +import Tab from './components/Tabs/Tab'; +import Back from './components/TopNav/Back'; + export { + Back, BillItem, BottomSheet, Button, @@ -36,10 +40,12 @@ export { StepItem, Switch, Tab, + Tabs, Text, TextButton, Title, TopNav, MainLayout, + ContentLayout, HDesignProvider, }; diff --git a/HDesign/src/layouts/ContentLayout.tsx b/HDesign/src/layouts/ContentLayout.tsx new file mode 100644 index 000000000..757a580ec --- /dev/null +++ b/HDesign/src/layouts/ContentLayout.tsx @@ -0,0 +1,25 @@ +import {PropsWithChildren} from 'react'; + +import {Flex} from '..'; + +type ContentLayoutBackground = 'white' | 'gray'; + +interface ContentLayoutProps extends PropsWithChildren { + backgroundColor?: ContentLayoutBackground; +} + +export function ContentLayout({backgroundColor, children}: ContentLayoutProps) { + return ( + <Flex + backgroundColor={backgroundColor} + justifyContent="flexStart" + flexDirection="column" + padding="0 1rem" + gap="1rem" + width="100%" + height="100%" + > + {children} + </Flex> + ); +} diff --git a/HDesign/src/layouts/MainLayout.tsx b/HDesign/src/layouts/MainLayout.tsx index 10032b4d8..b64e3c546 100644 --- a/HDesign/src/layouts/MainLayout.tsx +++ b/HDesign/src/layouts/MainLayout.tsx @@ -2,11 +2,23 @@ import {PropsWithChildren} from 'react'; import {Flex} from '..'; -interface MainLayoutInterface extends PropsWithChildren {} +type MainLayoutBackground = 'white' | 'gray'; -export function MainLayout({children}: MainLayoutInterface) { +interface MainLayoutProps extends PropsWithChildren { + backgroundColor?: MainLayoutBackground; +} + +export function MainLayout({backgroundColor, children}: MainLayoutProps) { return ( - <Flex justifyContent="flexStart" flexDirection="column" margin="1rem 0 0 0" gap="1rem" width="100%" height="100%"> + <Flex + backgroundColor={backgroundColor} + justifyContent="flexStart" + flexDirection="column" + padding="1rem 0 0 0" + gap="1rem" + width="100%" + height="100%" + > {children} </Flex> ); diff --git a/HDesign/src/theme/GlobalStyle.ts b/HDesign/src/theme/GlobalStyle.ts index cbef1c8ea..0c1670b07 100644 --- a/HDesign/src/theme/GlobalStyle.ts +++ b/HDesign/src/theme/GlobalStyle.ts @@ -112,4 +112,8 @@ export const GlobalStyle = css` display: flex; justify-content: center; } + + button { + cursor: pointer; + } `; diff --git a/client/src/pages/Main/Main.tsx b/client/src/pages/Main/Main.tsx index dfd7c406e..2a032b5cf 100644 --- a/client/src/pages/Main/Main.tsx +++ b/client/src/pages/Main/Main.tsx @@ -8,6 +8,8 @@ const Main = () => { return ( <MainLayout> + {/* <TopNav navType="back" /> */} + <Title title="행동대장" description="랜딩페이지입니다. 뿌뿌 잠깐만 테스트해볼게요.." /> <TopNav children={<></>} /> <Title title="행동대장" description="랜딩페이지입니다." /> <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateName)}>행사 생성하기</FixedButton> diff --git a/server/.gitignore b/server/.gitignore deleted file mode 100644 index 671ee930b..000000000 --- a/server/.gitignore +++ /dev/null @@ -1,244 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux -# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij,gradle,macos,windows,linux - -### Intellij ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Intellij Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -# https://plugins.jetbrains.com/plugin/7973-sonarlint -.idea/**/sonarlint/ - -# SonarQube Plugin -# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin -.idea/**/sonarIssues.xml - -# Markdown Navigator plugin -# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced -.idea/**/markdown-navigator.xml -.idea/**/markdown-navigator-enh.xml -.idea/**/markdown-navigator/ - -# Cache file creation bug -# See https://youtrack.jetbrains.com/issue/JBR-2257 -.idea/$CACHE_FILE$ - -# CodeStream plugin -# https://plugins.jetbrains.com/plugin/12206-codestream -.idea/codestream.xml - -# Azure Toolkit for IntelliJ plugin -# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij -.idea/**/azureSettings.xml - -### Java ### -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* - -### Linux ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### macOS Patch ### -# iCloud generated files -*.icloud - -### Windows ### -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -### Gradle ### -.gradle -**/build/ -!src/**/build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Avoid ignore Gradle wrappper properties -!gradle-wrapper.properties - -# Cache of project -.gradletasknamecache - -# Eclipse Gradle plugin generated files -# Eclipse Core -.project -# JDT-specific (Eclipse Java Development Tools) -.classpath - -### Gradle Patch ### -# Java heap dump -*.hprof - -# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux diff --git a/server/Dockerfile b/server/Dockerfile deleted file mode 100644 index 37e37d237..000000000 --- a/server/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM openjdk:17-jdk-slim - -WORKDIR /app - -COPY /build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar - -EXPOSE 8080 -ENTRYPOINT ["java"] -CMD ["-Dspring.profiles.active=dev", "-jar", "haengdong-0.0.1-SNAPSHOT.jar"] diff --git a/server/build.gradle b/server/build.gradle deleted file mode 100644 index 26f6ec262..000000000 --- a/server/build.gradle +++ /dev/null @@ -1,40 +0,0 @@ -plugins { - id 'java' - id 'org.springframework.boot' version '3.3.1' - id 'io.spring.dependency-management' version '1.1.5' -} - -group = 'server' -version = '0.0.1-SNAPSHOT' - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -configurations { - compileOnly { - extendsFrom annotationProcessor - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-validation' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.mysql:mysql-connector-j' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' -} - -tasks.named('test') { - useJUnitPlatform() -} diff --git a/server/gradle/wrapper/gradle-wrapper.jar b/server/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3d4ba8a0da8d277868979cfbc8ad796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 UfUyy3EX0IC28@JalTrWuAK7&_a{vGU diff --git a/server/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a4413138c..000000000 --- a/server/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/server/gradlew b/server/gradlew deleted file mode 100755 index b740cf133..000000000 --- a/server/gradlew +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/server/gradlew.bat b/server/gradlew.bat deleted file mode 100644 index 25da30dbd..000000000 --- a/server/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/server/settings.gradle b/server/settings.gradle deleted file mode 100644 index dbbee46fb..000000000 --- a/server/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'haengdong' diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java deleted file mode 100644 index 31b6e46e7..000000000 --- a/server/src/main/java/server/haengdong/HaengdongApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package server.haengdong; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class HaengdongApplication { - - public static void main(String[] args) { - SpringApplication.run(HaengdongApplication.class, args); - } - -} diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java deleted file mode 100644 index bda638756..000000000 --- a/server/src/main/java/server/haengdong/application/ActionService.java +++ /dev/null @@ -1,37 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberBillReport; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Service -public class ActionService { - - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - private final EventRepository eventRepository; - - public List<MemberBillReportAppResponse> getMemberBillReports(String token) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - List<BillAction> billActions = billActionRepository.findByAction_Event(event); - List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); - - MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - - return memberBillReport.getReports().entrySet().stream() - .map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue())) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java deleted file mode 100644 index 257d33a3e..000000000 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ /dev/null @@ -1,44 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class BillActionService { - - private final BillActionRepository billActionRepository; - private final ActionRepository actionRepository; - private final EventRepository eventRepository; - - @Transactional - public void saveAllBillAction(String eventToken, List<BillActionAppRequest> requests) { - Event event = eventRepository.findByToken(eventToken) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - Action action = createStartAction(event); - - for (BillActionAppRequest request : requests) { - BillAction billAction = request.toBillAction(action); - billActionRepository.save(billAction); - action = action.next(); - } - } - - private Action createStartAction(Event event) { - return actionRepository.findLastByEvent(event) - .map(Action::next) - .orElse(Action.createFirst(event)); - } -} diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java deleted file mode 100644 index 9ad502606..000000000 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ /dev/null @@ -1,91 +0,0 @@ -package server.haengdong.application; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.event.EventTokenProvider; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class EventService { - - private final EventRepository eventRepository; - private final EventTokenProvider eventTokenProvider; - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - - @Transactional - public EventAppResponse saveEvent(EventAppRequest request) { - String token = eventTokenProvider.createToken(); - Event event = request.toEvent(token); - eventRepository.save(event); - - return EventAppResponse.of(event); - } - - public EventDetailAppResponse findEvent(String token) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - - return EventDetailAppResponse.of(event); - } - - public List<ActionAppResponse> findActions(String token) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - - List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() - .sorted(Comparator.comparing(BillAction::getSequence)).toList(); - List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event).stream() - .sorted(Comparator.comparing(MemberAction::getSequence)).toList(); - - return getActionAppResponses(billActions, memberActions); - } - - private List<ActionAppResponse> getActionAppResponses( - List<BillAction> billActions, - List<MemberAction> memberActions - ) { - int billActionIndex = 0; - int memberActionIndex = 0; - List<ActionAppResponse> actionAppResponses = new ArrayList<>(); - - while (billActionIndex < billActions.size() && memberActionIndex < memberActions.size()) { - BillAction billAction = billActions.get(billActionIndex); - MemberAction memberAction = memberActions.get(memberActionIndex); - if (billAction.getSequence() < memberAction.getSequence()) { - actionAppResponses.add(ActionAppResponse.of(billAction)); - billActionIndex++; - } else { - actionAppResponses.add(ActionAppResponse.of(memberAction)); - memberActionIndex++; - } - } - while (billActionIndex < billActions.size()) { - BillAction billAction = billActions.get(billActionIndex++); - actionAppResponses.add(ActionAppResponse.of(billAction)); - } - while (memberActionIndex < memberActions.size()) { - MemberAction memberAction = memberActions.get(memberActionIndex++); - actionAppResponses.add(ActionAppResponse.of(memberAction)); - } - - return actionAppResponses; - } -} diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java deleted file mode 100644 index cbe34f0ef..000000000 --- a/server/src/main/java/server/haengdong/application/MemberActionFactory.java +++ /dev/null @@ -1,82 +0,0 @@ -package server.haengdong.application; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.action.MemberGroupIdProvider; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Component -public class MemberActionFactory { - - private final MemberGroupIdProvider memberGroupIdProvider; - - public List<MemberAction> createMemberActions( - MemberActionsSaveAppRequest request, - List<MemberAction> memberActions, - Action action - ) { - validateMemberNames(request); - validateActions(request, memberActions); - - Long memberGroupId = memberGroupIdProvider.createGroupId(); - List<MemberAction> createdMemberActions = new ArrayList<>(); - List<MemberActionSaveAppRequest> actions = request.actions(); - for (MemberActionSaveAppRequest appRequest : actions) { - MemberAction memberAction = appRequest.toMemberAction(action, memberGroupId); - createdMemberActions.add(memberAction); - action = action.next(); - } - - return createdMemberActions; - } - - private void validateMemberNames(MemberActionsSaveAppRequest request) { - List<String> memberNames = request.actions().stream() - .map(MemberActionSaveAppRequest::name) - .toList(); - - long uniqueCount = memberNames.stream().distinct().count(); - if (uniqueCount != memberNames.size()) { - throw new HaengdongException(HaengdongErrorCode.DUPLICATED_MEMBER_ACTION); - } - } - - private void validateActions(MemberActionsSaveAppRequest request, List<MemberAction> memberActions) { - List<MemberAction> reverseSortedMemberActions = memberActions.stream() - .sorted(Comparator.comparing(MemberAction::getSequence).reversed()) - .toList(); - - for (MemberActionSaveAppRequest action : request.actions()) { - validateAction(action, reverseSortedMemberActions); - } - } - - private void validateAction(MemberActionSaveAppRequest request, List<MemberAction> memberActions) { - MemberActionStatus memberActionStatus = MemberActionStatus.of(request.status()); - if (isInvalidStatus(memberActions, request.name(), memberActionStatus)) { - throw new HaengdongException(HaengdongErrorCode.INVALID_MEMBER_ACTION); - } - } - - private boolean isInvalidStatus( - List<MemberAction> memberActions, - String memberName, - MemberActionStatus memberActionStatus - ) { - return memberActions.stream() - .filter(action -> action.isSameName(memberName)) - .findFirst() - .map(action -> action.isSameStatus(memberActionStatus)) - .orElse(MemberActionStatus.IN != memberActionStatus); - } -} diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java deleted file mode 100644 index 5094bf2c0..000000000 --- a/server/src/main/java/server/haengdong/application/MemberActionService.java +++ /dev/null @@ -1,60 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class MemberActionService { - - private final MemberActionFactory memberActionFactory; - private final MemberActionRepository memberActionRepository; - private final EventRepository eventRepository; - private final ActionRepository actionRepository; - - @Transactional - public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { - Event event = findEvent(token); - - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - Action action = createStartAction(event); - List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, findMemberActions, action); - memberActionRepository.saveAll(memberActions); - } - - private Action createStartAction(Event event) { - return actionRepository.findLastByEvent(event) - .map(Action::next) - .orElse(Action.createFirst(event)); - } - - public List<CurrentMemberAppResponse> getCurrentMembers(String token) { - Event event = findEvent(token); - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); - - return currentMembers.getMembers() - .stream() - .map(CurrentMemberAppResponse::new) - .toList(); - } - - private Event findEvent(String token) { - return eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java deleted file mode 100644 index acd0149f9..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; - -public record BillActionAppRequest( - String title, - Long price -) { - - public BillAction toBillAction(Action action) { - return new BillAction(action, title, price); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java deleted file mode 100644 index 1eea6adf4..000000000 --- a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.event.Event; - -public record EventAppRequest(String name) { - - public Event toEvent(String token) { - return new Event(name, token); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java deleted file mode 100644 index f7f8d8fc2..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; - -public record MemberActionSaveAppRequest(String name, String status) { - - public MemberAction toMemberAction(Action action, Long memberGroupId) { - return new MemberAction(action, name, MemberActionStatus.of(status), memberGroupId); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java deleted file mode 100644 index 650b908df..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package server.haengdong.application.request; - -import java.util.List; - -public record MemberActionsSaveAppRequest(List<MemberActionSaveAppRequest> actions) { -} diff --git a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java deleted file mode 100644 index a1abcc35b..000000000 --- a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java +++ /dev/null @@ -1,54 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; - -public record ActionAppResponse( - Long actionId, - String name, - Long price, - Long sequence, - ActionType actionType -) { - - public static ActionAppResponse of(BillAction billAction) { - return new ActionAppResponse( - billAction.getAction().getId(), - billAction.getTitle(), - billAction.getPrice(), - billAction.getSequence(), - ActionType.BILL - ); - } - - public static ActionAppResponse of(MemberAction memberAction) { - MemberActionStatus status = memberAction.getStatus(); - - return new ActionAppResponse( - memberAction.getAction().getId(), - memberAction.getMemberName(), - null, - memberAction.getSequence(), - ActionType.of(status) - ); - } - - public String actionTypeName() { - return actionType.name(); - } - - public enum ActionType { - BILL, - IN, - OUT, - ; - - private static ActionType of(MemberActionStatus memberActionStatus) { - if (MemberActionStatus.IN == memberActionStatus) { - return IN; - } - return OUT; - } - } -} diff --git a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java deleted file mode 100644 index 6c682d3e9..000000000 --- a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.MemberAction; - -public record CurrentMemberAppResponse(String name) { - - public static CurrentMemberAppResponse of(MemberAction memberAction) { - return new CurrentMemberAppResponse(memberAction.getMemberName()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java deleted file mode 100644 index f331d0011..000000000 --- a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.event.Event; - -public record EventAppResponse(String token) { - - public static EventAppResponse of(Event event) { - return new EventAppResponse(event.getToken()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java deleted file mode 100644 index 6e38826d4..000000000 --- a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.event.Event; - -public record EventDetailAppResponse(String eventName) { - - public static EventDetailAppResponse of(Event event) { - return new EventDetailAppResponse(event.getName()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java deleted file mode 100644 index 21b6cef56..000000000 --- a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package server.haengdong.application.response; - -public record MemberBillReportAppResponse(String name, Long price) { -} diff --git a/server/src/main/java/server/haengdong/config/WebConfig.java b/server/src/main/java/server/haengdong/config/WebConfig.java deleted file mode 100644 index 129d8b790..000000000 --- a/server/src/main/java/server/haengdong/config/WebConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -package server.haengdong.config; - -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@RequiredArgsConstructor -@Configuration -public class WebConfig implements WebMvcConfigurer { - - @Value("${cors.max-age}") - private Long maxAge; - - @Value("${cors.allowed-origins}") - private String[] allowedOrigins; - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins(allowedOrigins) - .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") - .allowedHeaders("*") - .maxAge(maxAge); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/Action.java b/server/src/main/java/server/haengdong/domain/action/Action.java deleted file mode 100644 index 11f91fc38..000000000 --- a/server/src/main/java/server/haengdong/domain/action/Action.java +++ /dev/null @@ -1,42 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.domain.event.Event; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Action { - - private static final long FIRST_SEQUENCE = 1L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Event event; - - private Long sequence; - - public Action(Event event, Long sequence) { - this.event = event; - this.sequence = sequence; - } - - public static Action createFirst(Event event) { - return new Action(event, FIRST_SEQUENCE); - } - - public Action next() { - return new Action(event, sequence + 1); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java deleted file mode 100644 index c2138e42f..000000000 --- a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java +++ /dev/null @@ -1,21 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface ActionRepository extends JpaRepository<Action, Long> { - - @Query(""" - SELECT a - FROM Action a - WHERE a.event = :event - ORDER BY a.sequence DESC - LIMIT 1 - """) - Optional<Action> findLastByEvent(@Param("event") Event event); -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java deleted file mode 100644 index 1027206f5..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillAction.java +++ /dev/null @@ -1,70 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class BillAction implements Comparable<BillAction> { - - private static final int MIN_TITLE_LENGTH = 2; - private static final int MAX_TITLE_LENGTH = 30; - private static final long MIN_PRICE = 1L; - private static final long MAX_PRICE = 10_000_000L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - private Action action; - - @Column(length = MAX_TITLE_LENGTH) - private String title; - - private Long price; - - public BillAction(Action action, String title, Long price) { - validateTitle(title); - validatePrice(price); - this.action = action; - this.title = title.trim(); - this.price = price; - } - - private void validateTitle(String title) { - int titleLength = title.trim().length(); - if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { - throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", MIN_TITLE_LENGTH, MAX_TITLE_LENGTH)); - } - } - - private void validatePrice(Long price) { - if (price < MIN_PRICE || price > MAX_PRICE) { - throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", MAX_PRICE)); - } - } - - public Long getSequence() { - return action.getSequence(); - } - - @Override - public int compareTo(BillAction o) { - return Long.compare(this.getSequence(), o.getSequence()); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java deleted file mode 100644 index 1ad7416aa..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface BillActionRepository extends JpaRepository<BillAction, Long> { - - @EntityGraph(attributePaths = {"action"}) - List<BillAction> findByAction_Event(Event event); -} diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java deleted file mode 100644 index 298a8a965..000000000 --- a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java +++ /dev/null @@ -1,66 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class CurrentMembers { - - private final Set<String> members; - - public CurrentMembers() { - this(new HashSet<>()); - } - - private CurrentMembers(Set<String> members) { - this.members = members; - } - - public static CurrentMembers of(List<MemberAction> memberActions) { - List<MemberAction> sortedMemberActions = getSortedMemberActions(memberActions); - Set<String> members = new HashSet<>(); - for (MemberAction memberAction : sortedMemberActions) { - String member = memberAction.getMemberName(); - if (memberAction.isSameStatus(MemberActionStatus.IN)) { - members.add(member); - continue; - } - members.remove(member); - } - - return new CurrentMembers(members); - } - - private static List<MemberAction> getSortedMemberActions(List<MemberAction> memberActions) { - return memberActions.stream() - .sorted(Comparator.comparing(MemberAction::getSequence)) - .toList(); - } - - public CurrentMembers addMemberAction(MemberAction memberAction) { - String memberName = memberAction.getMemberName(); - - Set<String> currentMembers = new HashSet<>(members); - - if (memberAction.isIn()) { - currentMembers.add(memberName); - } else { - currentMembers.remove(memberName); - } - return new CurrentMembers(currentMembers); - } - - public boolean isEmpty() { - return members.isEmpty(); - } - - public int size() { - return members.size(); - } - - public Set<String> getMembers() { - return Collections.unmodifiableSet(members); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java deleted file mode 100644 index 67387cbde..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberAction.java +++ /dev/null @@ -1,62 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class MemberAction implements Comparable<MemberAction> { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - private Action action; - - private String memberName; - - @Enumerated(EnumType.STRING) - private MemberActionStatus status; - - private Long memberGroupId; - - public MemberAction(Action action, String memberName, MemberActionStatus status, Long memberGroupId) { - this.action = action; - this.memberName = memberName; - this.status = status; - this.memberGroupId = memberGroupId; - } - - public boolean isSameName(String name) { - return memberName.equals(name); - } - - public boolean isIn() { - return status == MemberActionStatus.IN; - } - - public boolean isSameStatus(MemberActionStatus memberActionStatus) { - return status == memberActionStatus; - } - - public Long getSequence() { - return action.getSequence(); - } - - @Override - public int compareTo(MemberAction o) { - return Long.compare(this.getSequence(), o.getSequence()); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java deleted file mode 100644 index 6c4769e61..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface MemberActionRepository extends JpaRepository<MemberAction, Long> { - - @Query("select m from MemberAction m join fetch m.action where m.action.event = :event") - List<MemberAction> findAllByEvent(@Param("event") Event event); -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java deleted file mode 100644 index 0a20817fd..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Arrays; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -public enum MemberActionStatus { - IN, - OUT, - ; - - public static MemberActionStatus of(String status) { - return Arrays.stream(MemberActionStatus.values()) - .filter(s -> s.name().equals(status)) - .findFirst() - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - "존재하지 않는 인원 변동 액션입니다.")); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java deleted file mode 100644 index dbf2b49ac..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java +++ /dev/null @@ -1,75 +0,0 @@ -package server.haengdong.domain.action; - -import static java.util.stream.Collectors.toMap; - -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.function.Function; -import lombok.Getter; - -@Getter -public class MemberBillReport { - - private final Map<String, Long> reports; - - private MemberBillReport(Map<String, Long> reports) { - this.reports = reports; - } - - public static MemberBillReport createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { - PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); - PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); - - Map<String, Long> memberBillReports = initReports(memberActions); - CurrentMembers currentMembers = new CurrentMembers(); - while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { - if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { - MemberAction memberAction = sortedMemberActions.poll(); - currentMembers = currentMembers.addMemberAction(memberAction); - continue; - } - addBillAction(sortedBillActions, currentMembers, memberBillReports); - } - - while (!sortedBillActions.isEmpty()) { - addBillAction(sortedBillActions, currentMembers, memberBillReports); - } - - return new MemberBillReport(memberBillReports); - } - - private static Map<String, Long> initReports(List<MemberAction> memberActions) { - return memberActions.stream() - .map(MemberAction::getMemberName) - .distinct() - .collect(toMap(Function.identity(), i -> 0L)); - } - - private static boolean isMemberActionTurn( - PriorityQueue<MemberAction> memberActions, - PriorityQueue<BillAction> billActions - ) { - MemberAction memberAction = memberActions.peek(); - BillAction billAction = billActions.peek(); - - return memberAction.getSequence() < billAction.getSequence(); - } - - private static void addBillAction( - PriorityQueue<BillAction> sortedBillActions, - CurrentMembers currentMembers, - Map<String, Long> memberBillReports - ) { - BillAction billAction = sortedBillActions.poll(); - if (currentMembers.isEmpty()) { - return; - } - - Long pricePerMember = billAction.getPrice() / currentMembers.size(); - for (String currentMember : currentMembers.getMembers()) { - Long price = memberBillReports.get(currentMember) + pricePerMember; - memberBillReports.put(currentMember, price); - } - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java deleted file mode 100644 index 9e32bd733..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.domain.action; - -import org.springframework.stereotype.Component; - -@Component -public class MemberGroupIdProvider { - - public Long createGroupId() { - return System.currentTimeMillis(); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java deleted file mode 100644 index 24369a184..000000000 --- a/server/src/main/java/server/haengdong/domain/event/Event.java +++ /dev/null @@ -1,54 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Event { - - private static final int MIN_NAME_LENGTH = 2; - private static final int MAX_NAME_LENGTH = 20; - private static final String SPACES = " "; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String name; - - private String token; - - public Event(String name, String token) { - validateName(name); - this.name = name; - this.token = token; - } - - private void validateName(String name) { - int nameLength = name.length(); - if (nameLength < MIN_NAME_LENGTH || MAX_NAME_LENGTH < nameLength) { - throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", - MIN_NAME_LENGTH, - MAX_NAME_LENGTH, - name.length())); - } - if (isBlankContinuous(name)) { - throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", name)); - } - } - - private boolean isBlankContinuous(String name) { - return name.contains(SPACES); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java deleted file mode 100644 index 6038c368b..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.domain.event; - -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface EventRepository extends JpaRepository<Event, Long> { - - Optional<Event> findByToken(String token); -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventStep.java b/server/src/main/java/server/haengdong/domain/event/EventStep.java deleted file mode 100644 index 297abdb66..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventStep.java +++ /dev/null @@ -1,28 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class EventStep { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Event event; - - private String name; - - private Long sequence; -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java deleted file mode 100644 index 6450f0dcf..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.domain.event; - -import java.util.UUID; -import org.springframework.stereotype.Component; - -@Component -public class EventTokenProvider { - - public String createToken() { - return UUID.randomUUID().toString(); - } -} diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java deleted file mode 100644 index c797b811a..000000000 --- a/server/src/main/java/server/haengdong/exception/ErrorResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.exception; - -public record ErrorResponse( - String message -) { - - public static ErrorResponse of(String message) { - return new ErrorResponse(message); - } -} diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java deleted file mode 100644 index bb3138cc7..000000000 --- a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -package server.haengdong.exception; - -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -@Slf4j -@RestControllerAdvice -public class GlobalExceptionHandler { - - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public ResponseEntity<ErrorResponse> haengdongException() { - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.BAD_REQUEST.getMessage())); - } - - @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - String errorMessage = e.getFieldErrors().stream() - .map(error -> error.getField() + " " + error.getDefaultMessage()) - .collect(Collectors.joining(", ")); - - return ResponseEntity.badRequest() - .body(ErrorResponse.of(errorMessage)); - } - - @ExceptionHandler(HaengdongException.class) - public ResponseEntity<ErrorResponse> haengdongException(HaengdongException e) { - return ResponseEntity.status(e.getStatusCode()) - .body(ErrorResponse.of(e.getMessage())); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity<ErrorResponse> handleException(Exception e) { - log.error(e.getMessage(), e); - return ResponseEntity.internalServerError() - .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR.getMessage())); - } -} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java deleted file mode 100644 index 792baa838..000000000 --- a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java +++ /dev/null @@ -1,24 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; -import org.springframework.http.HttpStatus; - -@Getter -public enum HaengdongErrorCode { - BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."), - DUPLICATED_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "올바르지 않은 인원 요청입니다."), - INVALID_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "잘못된 맴버 액션입니다."), - - NOT_FOUND_EVENT(HttpStatus.NOT_FOUND, "존재하지 않는 행사입니다."), - - INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 내부에서 에러가 발생했습니다."), - ; - - private final HttpStatus httpStatus; - private final String message; - - HaengdongErrorCode(HttpStatus httpStatus, String message) { - this.httpStatus = httpStatus; - this.message = message; - } -} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongException.java b/server/src/main/java/server/haengdong/exception/HaengdongException.java deleted file mode 100644 index 812df50f8..000000000 --- a/server/src/main/java/server/haengdong/exception/HaengdongException.java +++ /dev/null @@ -1,32 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; -import org.springframework.http.HttpStatusCode; - -@Getter -public class HaengdongException extends RuntimeException { - - private final HaengdongErrorCode errorCode; - private final String message; - - public HaengdongException(HaengdongErrorCode errorCode) { - this(errorCode, null); - } - - public HaengdongException(HaengdongErrorCode errorCode, String message) { - this.errorCode = errorCode; - this.message = message; - } - - public HttpStatusCode getStatusCode() { - return errorCode.getHttpStatus(); - } - - @Override - public String getMessage() { - if (message == null) { - return errorCode.getMessage(); - } - return message; - } -} diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java deleted file mode 100644 index 657cb567e..000000000 --- a/server/src/main/java/server/haengdong/presentation/ActionController.java +++ /dev/null @@ -1,26 +0,0 @@ -package server.haengdong.presentation; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.ActionService; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.presentation.response.MemberBillReportsResponse; - -@RequiredArgsConstructor -@RestController -public class ActionController { - - private final ActionService actionService; - - @GetMapping("/api/events/{eventId}/actions/reports") - public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("eventId") String token) { - List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); - - return ResponseEntity.ok() - .body(MemberBillReportsResponse.of(memberBillReports)); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java deleted file mode 100644 index fcdacb270..000000000 --- a/server/src/main/java/server/haengdong/presentation/BillActionController.java +++ /dev/null @@ -1,29 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.BillActionService; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -@RequiredArgsConstructor -@RestController -public class BillActionController { - - private final BillActionService billActionService; - - @PostMapping("/api/events/{eventId}/actions/bills") - public ResponseEntity<Void> saveAllBillAction( - @PathVariable("eventId") String token, - @RequestBody @Valid BillActionsSaveRequest request - ) { - billActionService.saveAllBillAction(token, request.toAppRequests()); - - return ResponseEntity.ok() - .build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java deleted file mode 100644 index 9fbe098ce..000000000 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ /dev/null @@ -1,43 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.EventService; -import server.haengdong.presentation.request.EventSaveRequest; -import server.haengdong.presentation.response.EventDetailResponse; -import server.haengdong.presentation.response.EventResponse; -import server.haengdong.presentation.response.StepResponse; - -@RequiredArgsConstructor -@RestController -public class EventController { - - private final EventService eventService; - - @PostMapping("/api/events") - public ResponseEntity<EventResponse> saveEvent(@Valid @RequestBody EventSaveRequest request) { - EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); - - return ResponseEntity.ok(eventResponse); - } - - @GetMapping("/api/events/{eventId}") - public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") String token) { - EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); - - return ResponseEntity.ok(eventDetailResponse); - } - - @GetMapping("/api/events/{eventId}/actions") - public ResponseEntity<StepResponse> findActions(@PathVariable("eventId") String token) { - StepResponse stepResponse = StepResponse.of(eventService.findActions(token)); - - return ResponseEntity.ok(stepResponse); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java deleted file mode 100644 index c12370d86..000000000 --- a/server/src/main/java/server/haengdong/presentation/MemberActionController.java +++ /dev/null @@ -1,39 +0,0 @@ -package server.haengdong.presentation; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.MemberActionService; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionsSaveRequest; -import server.haengdong.presentation.response.CurrentMembersResponse; - -@RequiredArgsConstructor -@RestController -public class MemberActionController { - - private final MemberActionService memberActionService; - - @PostMapping("/api/events/{eventId}/actions/members") - public ResponseEntity<Void> saveMemberAction( - @PathVariable("eventId") String token, - @RequestBody MemberActionsSaveRequest request - ) { - memberActionService.saveMemberAction(token, request.toAppRequest()); - - return ResponseEntity.ok().build(); - } - - @GetMapping("/api/events/{eventId}/members/current") - public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("eventId") String token) { - List<CurrentMemberAppResponse> currentMembers = memberActionService.getCurrentMembers(token); - - return ResponseEntity.ok() - .body(CurrentMembersResponse.of(currentMembers)); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java deleted file mode 100644 index a0d878f7f..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import server.haengdong.application.request.BillActionAppRequest; - -public record BillActionSaveRequest( - - @NotBlank - String title, - - @NotNull - Long price -) { - - public BillActionAppRequest toAppRequest() { - return new BillActionAppRequest(title, price); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java deleted file mode 100644 index 68784039b..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.Valid; -import java.util.List; -import server.haengdong.application.request.BillActionAppRequest; - -public record BillActionsSaveRequest(@Valid List<BillActionSaveRequest> actions) { - - public List<BillActionAppRequest> toAppRequests() { - return actions.stream() - .map(BillActionSaveRequest::toAppRequest) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java deleted file mode 100644 index b28572332..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import server.haengdong.application.request.EventAppRequest; - -public record EventSaveRequest( - - @NotBlank - String eventName -) { - - public EventAppRequest toAppRequest() { - return new EventAppRequest(eventName); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java deleted file mode 100644 index 0b3fcebae..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java +++ /dev/null @@ -1,22 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import java.util.List; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; - -public record MemberActionsSaveRequest( - List<String> members, - - @NotBlank - String status -) { - - public MemberActionsSaveAppRequest toAppRequest() { - List<MemberActionSaveAppRequest> appRequests = members.stream() - .map(name -> new MemberActionSaveAppRequest(name, status)) - .toList(); - - return new MemberActionsSaveAppRequest(appRequests); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java deleted file mode 100644 index a58e60186..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.ActionAppResponse; - -public record ActionResponse( - Long actionId, - String name, - Long price, - Long sequence -) { - - public static ActionResponse of(ActionAppResponse actionAppResponse) { - return new ActionResponse( - actionAppResponse.actionId(), - actionAppResponse.name(), - actionAppResponse.price(), - actionAppResponse.sequence() - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java deleted file mode 100644 index 188c48dc9..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java +++ /dev/null @@ -1,28 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import server.haengdong.application.response.ActionAppResponse; - -public record ActionsResponse( - String type, - String stepName, - Set<String> members, - List<ActionResponse> actions -) { - - public static ActionsResponse of(List<ActionAppResponse> actions, Set<String> members) { - List<ActionResponse> actionResponses = actions.stream() - .map(ActionResponse::of) - .toList(); - - String actionType = actions.get(0).actionTypeName(); - return new ActionsResponse( - actionType, - null, - new HashSet<>(members), - actionResponses - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java deleted file mode 100644 index 4308c7d17..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.CurrentMemberAppResponse; - -public record CurrentMemberResponse(String name) { - - public static CurrentMemberResponse of(CurrentMemberAppResponse response) { - return new CurrentMemberResponse(response.name()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java deleted file mode 100644 index 4eb915dd4..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.CurrentMemberAppResponse; - -public record CurrentMembersResponse(List<CurrentMemberResponse> members) { - - public static CurrentMembersResponse of(List<CurrentMemberAppResponse> currentMembers) { - List<CurrentMemberResponse> responses = currentMembers.stream() - .map(CurrentMemberResponse::of) - .toList(); - - return new CurrentMembersResponse(responses); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java deleted file mode 100644 index c18694393..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.EventDetailAppResponse; - -public record EventDetailResponse(String eventName) { - - public static EventDetailResponse of(EventDetailAppResponse response) { - return new EventDetailResponse(response.eventName()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java deleted file mode 100644 index 506f5e814..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.EventAppResponse; - -public record EventResponse(String eventId) { - - public static EventResponse of(EventAppResponse eventAppResponse) { - return new EventResponse(eventAppResponse.token()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java deleted file mode 100644 index 0ea409202..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.MemberBillReportAppResponse; - -public record MemberBillReportResponse(String name, Long price) { - - public static MemberBillReportResponse of(MemberBillReportAppResponse memberBillReportAppResponse) { - return new MemberBillReportResponse(memberBillReportAppResponse.name(), memberBillReportAppResponse.price()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java deleted file mode 100644 index d350c4009..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.MemberBillReportAppResponse; - -public record MemberBillReportsResponse(List<MemberBillReportResponse> reports) { - - public static MemberBillReportsResponse of(List<MemberBillReportAppResponse> memberBillReports) { - List<MemberBillReportResponse> reports = memberBillReports.stream() - .map(MemberBillReportResponse::of) - .toList(); - - return new MemberBillReportsResponse(reports); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java deleted file mode 100644 index a8f3877ef..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java +++ /dev/null @@ -1,57 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import server.haengdong.application.response.ActionAppResponse; - -public record StepResponse( - List<ActionsResponse> steps -) { - - public static StepResponse of(List<ActionAppResponse> actions) { - if (actions.isEmpty()) { - return new StepResponse(List.of()); - } - List<ActionsResponse> actionsResponse = new ArrayList<>(); - Set<String> members = new HashSet<>(); - ActionAppResponse firstAction = getFirstAction(actions); - List<ActionAppResponse> group = new ArrayList<>(); - group.add(firstAction); - String currentActionType = firstAction.actionTypeName(); - members.add(firstAction.name()); - - for (int i = 1; i < actions.size(); i++) { - ActionAppResponse action = actions.get(i); - String typeName = action.actionTypeName(); - if (currentActionType.equals(typeName)) { - if (typeName.equals("IN")) { - members.add(action.name()); - } - if (typeName.equals("OUT")) { - members.remove(action.name()); - } - group.add(action); - continue; - } - actionsResponse.add(ActionsResponse.of(group, members)); - currentActionType = typeName; - group.clear(); - if (typeName.equals("IN")) { - members.add(action.name()); - } - if (typeName.equals("OUT")) { - members.remove(action.name()); - } - group.add(action); - } - actionsResponse.add(ActionsResponse.of(group, members)); - - return new StepResponse(actionsResponse); - } - - private static ActionAppResponse getFirstAction(List<ActionAppResponse> actions) { - return actions.get(0); - } -} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml deleted file mode 100644 index faf7a36f1..000000000 --- a/server/src/main/resources/application.yml +++ /dev/null @@ -1,31 +0,0 @@ -spring: - datasource: - driver-class-name: org.h2.Driver - url: jdbc:h2:mem:database - username: sa - password: - - h2: - console: - enabled: true - path: /h2-console - - jpa: - hibernate: - ddl-auto: create - properties: - hibernate: - format_sql: true - show-sql: true - -cors: - max-age: 3600 - allowed-origins: http://localhost:3000, https://haengdong.pro, https://dev.haengdong.pro, https://app.haengdong.pro - ---- - -spring: - config: - import: classpath:config/application-dev.yml - activate: - on-profile: dev diff --git a/server/src/main/resources/config b/server/src/main/resources/config deleted file mode 160000 index c12697b65..000000000 --- a/server/src/main/resources/config +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c12697b650b8a8adf27fd66377f6e62bb6b8a49d diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java deleted file mode 100644 index ac2dc4f4f..000000000 --- a/server/src/test/java/server/haengdong/application/ActionServiceTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@SpringBootTest -class ActionServiceTest { - - @Autowired - private ActionService actionService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() { - String token = "tOkEn1"; - Event event = new Event("행동대장", token); - Event savedEvent = eventRepository.save(event); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(savedEvent, 1L), "소하", IN, 1L), - new MemberAction(new Action(savedEvent, 2L), "감자", IN, 1L), - new MemberAction(new Action(savedEvent, 3L), "쿠키", IN, 1L), - new MemberAction(new Action(savedEvent, 5L), "감자", OUT, 2L) - ); - List<BillAction> billActions = List.of( - new BillAction(new Action(savedEvent, 4L), "뽕족", 60_000L), - new BillAction(new Action(savedEvent, 6L), "인생맥주", 40_000L), - new BillAction(new Action(savedEvent, 7L), "인생네컷", 20_000L) - ); - memberActionRepository.saveAll(memberActions); - billActionRepository.saveAll(billActions); - - List<MemberBillReportAppResponse> responses = actionService.getMemberBillReports(token); - - assertThat(responses) - .hasSize(3) - .extracting(MemberBillReportAppResponse::name, MemberBillReportAppResponse::price) - .containsExactlyInAnyOrder( - tuple("감자", 20_000L), - tuple("쿠키", 50_000L), - tuple("소하", 50_000L) - ); - } - - @DisplayName("존재하지 않는 이벤트의 참여자별 정산 현황을 조회하는 경우 예외가 발생한다.") - @Test - void getMemberBillReports1() { - assertThatThrownBy(() -> actionService.getMemberBillReports("invalid token")) - .isInstanceOf(HaengdongException.class) - .hasMessage(HaengdongErrorCode.NOT_FOUND_EVENT.getMessage()); - } -} diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java deleted file mode 100644 index 195d4bdd9..000000000 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; - -@SpringBootTest -class BillActionServiceTest { - - @Autowired - private BillActionService billActionService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() { - String token = "TOKEN"; - Event event = new Event("감자", token); - Event savedEvent = eventRepository.save(event); - - List<BillActionAppRequest> requests = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - billActionService.saveAllBillAction(token, requests); - - List<BillAction> actions = billActionRepository.findByAction_Event(savedEvent); - - assertThat(actions).extracting(BillAction::getTitle, BillAction::getPrice, BillAction::getSequence) - .containsExactlyInAnyOrder( - tuple("뽕족", 10_000L, 1L), - tuple("인생맥주", 15_000L, 2L) - ); - } - - @DisplayName("이벤트가 존재하지 않으면 지출 내역을 생성할 수 없다.") - @Test - void saveAllBillAction1() { - List<BillActionAppRequest> requests = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java deleted file mode 100644 index 5a3e8bce3..000000000 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package server.haengdong.application; - - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.BDDMockito.given; - -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.event.EventTokenProvider; - -@SpringBootTest -class EventServiceTest { - - @Autowired - private EventService eventService; - - @MockBean - private EventTokenProvider eventTokenProvider; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private ActionRepository actionRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @AfterEach - void tearDown() { - billActionRepository.deleteAllInBatch(); - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - - @DisplayName("행사를 생성한다") - @Test - void saveEventTest() { - EventAppRequest request = new EventAppRequest("test"); - given(eventTokenProvider.createToken()).willReturn("TOKEN"); - - EventAppResponse response = eventService.saveEvent(request); - - assertThat(response.token()).isEqualTo("TOKEN"); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() { - String token = "TOKEN"; - Event event = new Event("행동대장 회식", token); - eventRepository.save(event); - - EventDetailAppResponse eventDetailAppResponse = eventService.findEvent(token); - - assertThat(eventDetailAppResponse.eventName()).isEqualTo("행동대장 회식"); - } - - @DisplayName("행사에 속한 모든 액션을 조회한다.") - @Test - void findActionsTest() { - Event event = new Event("행동대장 회식", "웨디_토큰"); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - Action action1 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "쿠키", MemberActionStatus.IN, 1L); - Action action2 = new Action(event, 3L); - BillAction billAction = new BillAction(action2, "뽕나무쟁이족발", 30000L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction, memberAction1)); - billActionRepository.save(billAction); - - List<ActionAppResponse> actionAppResponses = eventService.findActions("웨디_토큰"); - - assertThat(actionAppResponses).hasSize(3) - .extracting(ActionAppResponse::actionId, - ActionAppResponse::name, - ActionAppResponse::price, - ActionAppResponse::sequence, - ActionAppResponse::actionTypeName) - .containsExactly( - tuple(1L, "토다리", null, 1L, "IN"), - tuple(2L, "쿠키", null, 2L, "IN"), - tuple(3L, "뽕나무쟁이족발", 30000L, 3L, "BILL") - ); - } -} diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java deleted file mode 100644 index 40bee2ff6..000000000 --- a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java +++ /dev/null @@ -1,217 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; - -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.exception.HaengdongException; - -@SpringBootTest -class MemberActionFactoryTest { - - @Autowired - private MemberActionFactory memberActionFactory; - - @Autowired - private MemberActionRepository memberActionRepository; - - @Autowired - private ActionRepository actionRepository; - - @Autowired - private EventRepository eventRepository; - - @AfterEach - void tearDown() { - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - - @DisplayName("이전 멤버 액션이 시퀀스 기준으로 정렬되지 않은 상태에서 새로운 멤버 액션 요청을 검증한다.") - @Test - void createMemberActionsTest() { - Event event = eventRepository.save(new Event("우당탕탕 행동대장 백엔드 회식", "토다리_토큰")); - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - List<MemberAction> unorderedMemberActions = List.of(memberAction2, memberAction1); - Action startAction = new Action(event, 3L); - - assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, unorderedMemberActions, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("인원 변동 액션을 생성한다.") - @Test - void createMemberActionsTest1() { - Event event = eventRepository.save(new Event("우당탕탕 행동대장 백엔드 회식", "토다리_토큰")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest memberActionsSaveAppRequest = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - Action startAction = new Action(event, 2L); - - List<MemberAction> memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, - List.of(memberAction), startAction); - - assertThat(memberActions).hasSize(1) - .extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus) - .containsExactly( - tuple(startAction, "토다리", MemberActionStatus.OUT) - ); - } - - @DisplayName("현재 행사에 참여 중인 경우에 퇴장할 수 있다.") - @Test - void createMemberActionsTest2() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") - @Test - void createMemberActionsTest3() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action1 = new Action(event, 1L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction1); - Action action2 = new Action(event, 2L); - MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); - memberActionRepository.save(memberAction2); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "IN"))); - Action startAction = new Action(event, 3L); - - assertThatCode( - () -> memberActionFactory.createMemberActions(request, List.of(memberAction1, memberAction2), - startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장한 적 없는 경우에 입장할 수 있다.") - @Test - void createMemberActionsTest4() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") - @Test - void createMemberActionTest5() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "OUT"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("행사에 이미 참여 중인 경우 다시 입장할 수 없다.") - @Test - void createMemberActionTest6() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 동시에 여러 번 입장할 수 없다.") - @Test - void createMemberActionTest7() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"), - new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 1L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 동시에 여러 번 퇴장할 수 없다.") - @Test - void createMemberActionTest8() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "OUT"), - new MemberActionSaveAppRequest("쿠키", "OUT"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 입장과 퇴장을 동시에 할 수 없다.") - @Test - void createMemberActionTest9() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"), - new MemberActionSaveAppRequest("쿠키", "OUT"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java deleted file mode 100644 index 7212e300d..000000000 --- a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; - -@SpringBootTest -class MemberActionServiceTest { - - @Autowired - private MemberActionService memberActionService; - - @Autowired - private MemberActionRepository memberActionRepository; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private ActionRepository actionRepository; - - @AfterEach - void tearDown() { - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - - @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다.") - @Test - void saveMemberActionTest() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "망쵸", IN, 1L); - memberActionRepository.save(memberAction); - - assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("망쵸", "OUT"))))) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") - @Test - void saveMemberActionTest1() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action actionOne = new Action(event, 1L); - MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", IN, 1L); - memberActionRepository.save(memberActionOne); - - Action actionTwo = new Action(event, 2L); - MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", OUT, 1L); - memberActionRepository.save(memberActionTwo); - - assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("망쵸", "IN"))))) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") - @Test - void saveMemberActionTest2() { - MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); - - assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("이벤트가 없으면 현재 참여 인원을 조회할 수 없다.") - @Test - void getCurrentMembers() { - assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/ActionTest.java b/server/src/test/java/server/haengdong/domain/action/ActionTest.java deleted file mode 100644 index 199a4f628..000000000 --- a/server/src/test/java/server/haengdong/domain/action/ActionTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; - -class ActionTest { - - @DisplayName("액션의 초기 순서번호는 1이다.") - @Test - void createFirst() { - Event event = new Event("name", "token"); - Action action = Action.createFirst(event); - - assertThat(action.getSequence()).isOne(); - } - - @DisplayName("현재 액션의 다음 액션의 순서는 1만큼 증가한다.") - @Test - void next() { - Event event = new Event("name", "token"); - Action action = new Action(event, 2L); - - Action nextAction = action.next(); - - assertThat(nextAction.getSequence()).isEqualTo(3L); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java deleted file mode 100644 index 601ca95d7..000000000 --- a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongException; - -class BillActionTest { - - @DisplayName("지출 내역 제목의 앞뒤 공백을 제거한 길이가 2 ~ 30자가 아니면 지출을 생성할 수 없다.") - @ParameterizedTest - @ValueSource(strings = {" 감 ", "", " ", "1234567890123456789012345678901"}) - void validateTitle(String title) { - Event event = new Event("name", "token"); - Action action = new Action(event, 1L); - Long price = 100L; - - assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(HaengdongException.class) - .hasMessage("앞뒤 공백을 제거한 지출 내역 제목은 2 ~ 30자여야 합니다."); - } - - @DisplayName("금액이 10,000,000 이하의 자연수가 아니면 지출을 생성할 수 없다.") - @ParameterizedTest - @ValueSource(longs = {0, 10_000_001, 20_000_000}) - void validatePrice(long price) { - Event event = new Event("name", "token"); - Action action = new Action(event, 1L); - String title = "title"; - - assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(HaengdongException.class) - .hasMessage("지출 금액은 10,000,000 이하의 자연수여야 합니다."); - } - - @DisplayName("지출 내역을 올바르게 생성한다.") - @Test - void createBillAction() { - Event event = new Event("name", "token"); - Action action = new Action(event, 1L); - String title = "title"; - Long price = 1_000L; - - BillAction billAction = new BillAction(action, title, price); - - assertAll( - () -> assertThat(billAction.getAction()).isEqualTo(action), - () -> assertThat(billAction.getTitle()).isEqualTo(title), - () -> assertThat(billAction.getPrice()).isEqualTo(price) - ); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java deleted file mode 100644 index 389ca70c1..000000000 --- a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import java.util.Set; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; - -class CurrentMembersTest { - - @DisplayName("인원 변동 이력으로 현재 참여 인원을 계산한다.") - @Test - void of() { - Event event = new Event("test", "TOKEN"); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(event, 1L), "망쵸", IN, 1L), - new MemberAction(new Action(event, 2L), "백호", IN, 1L), - new MemberAction(new Action(event, 3L), "백호", OUT, 1L), - new MemberAction(new Action(event, 4L), "웨디", IN, 1L) - ); - - CurrentMembers currentMembers = CurrentMembers.of(memberActions); - - assertThat(currentMembers.getMembers()) - .containsExactlyInAnyOrder("망쵸", "웨디"); - } - - @DisplayName("인원 변동 액션의 상태가 IN이면 현재 인원에 추가한다.") - @Test - void addMemberAction1() { - CurrentMembers currentMembers = new CurrentMembers(); - Event event = new Event("이벤트", "token"); - MemberAction memberAction = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); - - CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction); - Set<String> members = addedCurrentMembers.getMembers(); - - assertThat(members).hasSize(1) - .containsExactly("웨디"); - } - - @DisplayName("인원 변동 액션의 상태가 OUT이면 현재 인원에서 제외한다.") - @Test - void addMemberAction2() { - Event event = new Event("이벤트", "token"); - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); - CurrentMembers currentMembers = new CurrentMembers().addMemberAction(memberAction1); - MemberAction memberAction2 = new MemberAction(new Action(event, 1L), "웨디", OUT, 1L); - - CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction2); - - assertThat(addedCurrentMembers.getMembers()).hasSize(0); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java deleted file mode 100644 index 9ad27d5bc..000000000 --- a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; - -class MemberBillReportTest { - - @DisplayName("액션 목록으로 참가자 정산 리포트를 생성한다.") - @Test - void createByActions() { - String token = "TOK2N"; - Event event = new Event("행동대장", token); - List<BillAction> billActions = List.of( - new BillAction(new Action(event, 4L), "뽕족", 60_000L), - new BillAction(new Action(event, 6L), "인생맥주", 40_000L), - new BillAction(new Action(event, 7L), "인생네컷", 20_000L) - ); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(event, 1L), "소하", IN, 1L), - new MemberAction(new Action(event, 2L), "감자", IN, 1L), - new MemberAction(new Action(event, 3L), "쿠키", IN, 1L), - new MemberAction(new Action(event, 5L), "감자", OUT, 2L) - ); - - MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - - assertThat(memberBillReport.getReports()) - .containsAllEntriesOf( - Map.of( - "감자", 20_000L, - "쿠키", 50_000L, - "소하", 50_000L - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/domain/event/EventTest.java b/server/src/test/java/server/haengdong/domain/event/EventTest.java deleted file mode 100644 index 98f6c7050..000000000 --- a/server/src/test/java/server/haengdong/domain/event/EventTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package server.haengdong.domain.event; - -import static org.assertj.core.api.Assertions.assertThatCode; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.exception.HaengdongException; - -class EventTest { - - @DisplayName("공백 문자가 연속되지 않고, 이름이 2자 이상 20자 이하인 행사를 생성하면 예외가 발생하지 않는다.") - @ParameterizedTest - @ValueSource(strings = {"12", "12345678901234567890", "공 백", " 공백", "공백 ", " 공 백 "}) - void createSuccessTest(String eventName) { - assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) - .doesNotThrowAnyException(); - } - - @DisplayName("공백 문자가 연속되면 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {" 공백", "공백 ", "공백 연속", "공 백"}) - void createFailTest1(String eventName) { - assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class) - .hasMessage(String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", eventName)); - } - - @DisplayName("이름이 2자 미만이거나 20자 초과인 경우 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {"", " ", "123456789012345678901"}) - void createFilTest2(String eventName) { - assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class) - .hasMessage(String.format("행사 이름은 2자 이상 20자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", eventName.length())); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java deleted file mode 100644 index 739ac4962..000000000 --- a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package server.haengdong.presentation; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import server.haengdong.application.ActionService; -import server.haengdong.application.response.MemberBillReportAppResponse; - -@WebMvcTest(ActionController.class) -class ActionControllerTest { - - @Autowired - private MockMvc mockMvc; - - @MockBean - private ActionService actionService; - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() throws Exception { - List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( - new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); - - given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); - - mockMvc.perform(get("/api/events/{token}/actions/reports", "token") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))); - - } -} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java deleted file mode 100644 index 8bf2b292f..000000000 --- a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package server.haengdong.presentation; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import server.haengdong.application.BillActionService; -import server.haengdong.presentation.request.BillActionSaveRequest; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -@WebMvcTest(BillActionController.class) -class BillActionControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private BillActionService billActionService; - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("뽕족", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String token = "TOKEN"; - - mockMvc.perform(post("/api/events/{token}/actions/bills", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("title이 비어 있는 경우 지출 내역을 생성할 수 없다.") - @Test - void saveAllBillAction1() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String token = "TOKEN"; - - mockMvc.perform(post("/api/events/{token}/actions/bills", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isBadRequest()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java deleted file mode 100644 index 55a48630f..000000000 --- a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package server.haengdong.presentation; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import server.haengdong.application.EventService; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.presentation.request.EventSaveRequest; - -@WebMvcTest(EventController.class) -class EventControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private EventService eventService; - - @DisplayName("이벤트를 생성한다.") - @Test - void saveEvent() throws Exception { - EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리"); - String requestBody = objectMapper.writeValueAsString(eventSaveRequest); - String token = "TOKEN"; - EventAppResponse eventAppResponse = new EventAppResponse(token); - given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); - - mockMvc.perform(post("/api/events") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventId").value("TOKEN")); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() throws Exception { - String token = "TOKEN"; - EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); - given(eventService.findEvent(token)).willReturn(eventDetailAppResponse); - - mockMvc.perform(get("/api/events/" + token)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventName").value("행동대장 회식")); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java deleted file mode 100644 index ad8787cc6..000000000 --- a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package server.haengdong.presentation; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import server.haengdong.application.MemberActionService; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionsSaveRequest; - -@WebMvcTest(MemberActionController.class) -class MemberActionControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private MemberActionService memberActionService; - - @DisplayName("참여자 행동을 추가한다.") - @Test - void saveMemberActionTest() throws Exception { - MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( - List.of("웨디", "소하", "토다리", "쿠키"), "IN"); - - String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); - - mockMvc.perform(post("/api/events/TOKEN/actions/members") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("현재 참여 인원을 조회합니다.") - @Test - void getCurrentMembers() throws Exception { - List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( - new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); - - given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); - - mockMvc.perform(get("/api/events/{token}/members/current", "token") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.members[0].name").value(equalTo("소하"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.members[1].name").value(equalTo("토다리"))); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java b/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java deleted file mode 100644 index aac78691c..000000000 --- a/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package server.haengdong.presentation.response; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.ArrayList; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.ActionAppResponse.ActionType; - -@SpringBootTest -class StepResponseTest { - - @Autowired - private ObjectMapper objectMapper; - - @DisplayName("") - @Test - void test() throws JsonProcessingException { - List<ActionAppResponse> actionAppResponse = new ArrayList<>(); - - // IN actions - ActionAppResponse actionAppResponse1 = new ActionAppResponse(3L, "망쵸", null, 3L, ActionType.IN); - actionAppResponse.add(actionAppResponse1); - ActionAppResponse actionAppResponse2 = new ActionAppResponse(4L, "백호", null, 4L, ActionType.IN); - actionAppResponse.add(actionAppResponse2); - - // BILL step 1 - ActionAppResponse actionAppResponse3 = new ActionAppResponse(1L, "감자탕", 10000L, 1L, ActionType.BILL); - actionAppResponse.add(actionAppResponse3); - ActionAppResponse actionAppResponse4 = new ActionAppResponse(2L, "인생네컷", 10000L, 2L, ActionType.BILL); - actionAppResponse.add(actionAppResponse4); - - // IN actions - ActionAppResponse actionAppResponse5 = new ActionAppResponse(5L, "소하", null, 5L, ActionType.IN); - actionAppResponse.add(actionAppResponse5); - ActionAppResponse actionAppResponse6 = new ActionAppResponse(6L, "웨디", null, 6L, ActionType.IN); - actionAppResponse.add(actionAppResponse6); - - // OUT actions - ActionAppResponse actionAppResponse7 = new ActionAppResponse(7L, "망쵸", null, 7L, ActionType.OUT); - actionAppResponse.add(actionAppResponse7); - ActionAppResponse actionAppResponse8 = new ActionAppResponse(8L, "백호", null, 8L, ActionType.OUT); - actionAppResponse.add(actionAppResponse8); - - // BILL step 2 - ActionAppResponse actionAppResponse9 = new ActionAppResponse(9L, "노래방", 20000L, 10L, ActionType.BILL); - actionAppResponse.add(actionAppResponse9); - - // StepResponse creation - StepResponse stepResponse = StepResponse.of(actionAppResponse); - System.out.println("stepResponse = " + stepResponse); - } -} diff --git a/server/src/test/resources/application.yml b/server/src/test/resources/application.yml deleted file mode 100644 index 2d02b2712..000000000 --- a/server/src/test/resources/application.yml +++ /dev/null @@ -1,18 +0,0 @@ -spring: - h2: - console: - enabled: true - path: /h2-console - datasource: - url: jdbc:h2:mem:database - jpa: - defer-datasource-initialization: true - show-sql: true - properties: - hibernate: - format_sql: true - hibernate: - ddl-auto: create-drop -cors: - max-age: 3600 - allowed-origins: http://localhost:8080 From 3b5e73dcc7e7daba5513048669469af85b07a138 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Mon, 29 Jul 2024 19:04:17 +0900 Subject: [PATCH 103/273] =?UTF-8?q?chore:=20server=20directory=20=EB=B3=B5?= =?UTF-8?q?=EA=B5=AC=20(#150)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/.gitignore | 244 +++++++++++++++++ server/Dockerfile | 9 + server/build.gradle | 40 +++ server/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + server/gradlew | 249 ++++++++++++++++++ server/gradlew.bat | 92 +++++++ server/settings.gradle | 1 + .../haengdong/HaengdongApplication.java | 13 + .../haengdong/application/ActionService.java | 37 +++ .../application/BillActionService.java | 44 ++++ .../haengdong/application/EventService.java | 91 +++++++ .../application/MemberActionFactory.java | 82 ++++++ .../application/MemberActionService.java | 60 +++++ .../request/BillActionAppRequest.java | 14 + .../application/request/EventAppRequest.java | 10 + .../request/MemberActionSaveAppRequest.java | 12 + .../request/MemberActionsSaveAppRequest.java | 6 + .../response/ActionAppResponse.java | 54 ++++ .../response/CurrentMemberAppResponse.java | 10 + .../response/EventAppResponse.java | 10 + .../response/EventDetailAppResponse.java | 10 + .../response/MemberBillReportAppResponse.java | 4 + .../server/haengdong/config/WebConfig.java | 27 ++ .../haengdong/domain/action/Action.java | 42 +++ .../domain/action/ActionRepository.java | 21 ++ .../haengdong/domain/action/BillAction.java | 70 +++++ .../domain/action/BillActionRepository.java | 14 + .../domain/action/CurrentMembers.java | 66 +++++ .../haengdong/domain/action/MemberAction.java | 62 +++++ .../domain/action/MemberActionRepository.java | 15 ++ .../domain/action/MemberActionStatus.java | 19 ++ .../domain/action/MemberBillReport.java | 75 ++++++ .../domain/action/MemberGroupIdProvider.java | 11 + .../server/haengdong/domain/event/Event.java | 54 ++++ .../domain/event/EventRepository.java | 11 + .../haengdong/domain/event/EventStep.java | 28 ++ .../domain/event/EventTokenProvider.java | 12 + .../haengdong/exception/ErrorResponse.java | 10 + .../exception/GlobalExceptionHandler.java | 43 +++ .../exception/HaengdongErrorCode.java | 24 ++ .../exception/HaengdongException.java | 32 +++ .../presentation/ActionController.java | 26 ++ .../presentation/BillActionController.java | 29 ++ .../presentation/EventController.java | 43 +++ .../presentation/MemberActionController.java | 39 +++ .../request/BillActionSaveRequest.java | 19 ++ .../request/BillActionsSaveRequest.java | 14 + .../request/EventSaveRequest.java | 15 ++ .../request/MemberActionsSaveRequest.java | 22 ++ .../presentation/response/ActionResponse.java | 20 ++ .../response/ActionsResponse.java | 28 ++ .../response/CurrentMemberResponse.java | 10 + .../response/CurrentMembersResponse.java | 15 ++ .../response/EventDetailResponse.java | 10 + .../presentation/response/EventResponse.java | 10 + .../response/MemberBillReportResponse.java | 10 + .../response/MemberBillReportsResponse.java | 15 ++ .../presentation/response/StepResponse.java | 57 ++++ server/src/main/resources/application.yml | 31 +++ .../application/ActionServiceTest.java | 79 ++++++ .../application/BillActionServiceTest.java | 65 +++++ .../application/EventServiceTest.java | 110 ++++++++ .../application/MemberActionFactoryTest.java | 217 +++++++++++++++ .../application/MemberActionServiceTest.java | 92 +++++++ .../haengdong/domain/action/ActionTest.java | 30 +++ .../domain/action/BillActionTest.java | 58 ++++ .../domain/action/CurrentMembersTest.java | 58 ++++ .../domain/action/MemberBillReportTest.java | 43 +++ .../haengdong/domain/event/EventTest.java | 37 +++ .../presentation/ActionControllerTest.java | 49 ++++ .../BillActionControllerTest.java | 69 +++++ .../presentation/EventControllerTest.java | 66 +++++ .../MemberActionControllerTest.java | 67 +++++ .../response/StepResponseTest.java | 57 ++++ server/src/test/resources/application.yml | 18 ++ 76 files changed, 3263 insertions(+) create mode 100644 server/.gitignore create mode 100644 server/Dockerfile create mode 100644 server/build.gradle create mode 100644 server/gradle/wrapper/gradle-wrapper.jar create mode 100644 server/gradle/wrapper/gradle-wrapper.properties create mode 100644 server/gradlew create mode 100644 server/gradlew.bat create mode 100644 server/settings.gradle create mode 100644 server/src/main/java/server/haengdong/HaengdongApplication.java create mode 100644 server/src/main/java/server/haengdong/application/ActionService.java create mode 100644 server/src/main/java/server/haengdong/application/BillActionService.java create mode 100644 server/src/main/java/server/haengdong/application/EventService.java create mode 100644 server/src/main/java/server/haengdong/application/MemberActionFactory.java create mode 100644 server/src/main/java/server/haengdong/application/MemberActionService.java create mode 100644 server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/EventAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/response/ActionAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/EventAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java create mode 100644 server/src/main/java/server/haengdong/config/WebConfig.java create mode 100644 server/src/main/java/server/haengdong/domain/action/Action.java create mode 100644 server/src/main/java/server/haengdong/domain/action/ActionRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/action/BillAction.java create mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/action/CurrentMembers.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberAction.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberBillReport.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java create mode 100644 server/src/main/java/server/haengdong/domain/event/Event.java create mode 100644 server/src/main/java/server/haengdong/domain/event/EventRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/event/EventStep.java create mode 100644 server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java create mode 100644 server/src/main/java/server/haengdong/exception/ErrorResponse.java create mode 100644 server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java create mode 100644 server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java create mode 100644 server/src/main/java/server/haengdong/exception/HaengdongException.java create mode 100644 server/src/main/java/server/haengdong/presentation/ActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/BillActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/EventController.java create mode 100644 server/src/main/java/server/haengdong/presentation/MemberActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/EventResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/StepResponse.java create mode 100644 server/src/main/resources/application.yml create mode 100644 server/src/test/java/server/haengdong/application/ActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/application/BillActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/application/EventServiceTest.java create mode 100644 server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java create mode 100644 server/src/test/java/server/haengdong/application/MemberActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/domain/action/ActionTest.java create mode 100644 server/src/test/java/server/haengdong/domain/action/BillActionTest.java create mode 100644 server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java create mode 100644 server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java create mode 100644 server/src/test/java/server/haengdong/domain/event/EventTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/ActionControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/EventControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java create mode 100644 server/src/test/resources/application.yml diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 000000000..671ee930b --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,244 @@ +# Created by https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux +# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij,gradle,macos,windows,linux + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### Gradle Patch ### +# Java heap dump +*.hprof + +# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 000000000..37e37d237 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,9 @@ +FROM openjdk:17-jdk-slim + +WORKDIR /app + +COPY /build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar + +EXPOSE 8080 +ENTRYPOINT ["java"] +CMD ["-Dspring.profiles.active=dev", "-jar", "haengdong-0.0.1-SNAPSHOT.jar"] diff --git a/server/build.gradle b/server/build.gradle new file mode 100644 index 000000000..26f6ec262 --- /dev/null +++ b/server/build.gradle @@ -0,0 +1,40 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.3.1' + id 'io.spring.dependency-management' version '1.1.5' +} + +group = 'server' +version = '0.0.1-SNAPSHOT' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.h2database:h2' + runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/server/gradle/wrapper/gradle-wrapper.jar b/server/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e6441136f3d4ba8a0da8d277868979cfbc8ad796 GIT binary patch literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 UfUyy3EX0IC28@JalTrWuAK7&_a{vGU literal 0 HcmV?d00001 diff --git a/server/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..a4413138c --- /dev/null +++ b/server/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/server/gradlew b/server/gradlew new file mode 100644 index 000000000..b740cf133 --- /dev/null +++ b/server/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/server/gradlew.bat b/server/gradlew.bat new file mode 100644 index 000000000..25da30dbd --- /dev/null +++ b/server/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/server/settings.gradle b/server/settings.gradle new file mode 100644 index 000000000..dbbee46fb --- /dev/null +++ b/server/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'haengdong' diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java new file mode 100644 index 000000000..31b6e46e7 --- /dev/null +++ b/server/src/main/java/server/haengdong/HaengdongApplication.java @@ -0,0 +1,13 @@ +package server.haengdong; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class HaengdongApplication { + + public static void main(String[] args) { + SpringApplication.run(HaengdongApplication.class, args); + } + +} diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java new file mode 100644 index 000000000..bda638756 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/ActionService.java @@ -0,0 +1,37 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberBillReport; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Service +public class ActionService { + + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + private final EventRepository eventRepository; + + public List<MemberBillReportAppResponse> getMemberBillReports(String token) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); + List<BillAction> billActions = billActionRepository.findByAction_Event(event); + List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); + + MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); + + return memberBillReport.getReports().entrySet().stream() + .map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue())) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java new file mode 100644 index 000000000..257d33a3e --- /dev/null +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -0,0 +1,44 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.BillActionAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class BillActionService { + + private final BillActionRepository billActionRepository; + private final ActionRepository actionRepository; + private final EventRepository eventRepository; + + @Transactional + public void saveAllBillAction(String eventToken, List<BillActionAppRequest> requests) { + Event event = eventRepository.findByToken(eventToken) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); + Action action = createStartAction(event); + + for (BillActionAppRequest request : requests) { + BillAction billAction = request.toBillAction(action); + billActionRepository.save(billAction); + action = action.next(); + } + } + + private Action createStartAction(Event event) { + return actionRepository.findLastByEvent(event) + .map(Action::next) + .orElse(Action.createFirst(event)); + } +} diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java new file mode 100644 index 000000000..9ad502606 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -0,0 +1,91 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.event.EventTokenProvider; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class EventService { + + private final EventRepository eventRepository; + private final EventTokenProvider eventTokenProvider; + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + + @Transactional + public EventAppResponse saveEvent(EventAppRequest request) { + String token = eventTokenProvider.createToken(); + Event event = request.toEvent(token); + eventRepository.save(event); + + return EventAppResponse.of(event); + } + + public EventDetailAppResponse findEvent(String token) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); + + return EventDetailAppResponse.of(event); + } + + public List<ActionAppResponse> findActions(String token) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); + + List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() + .sorted(Comparator.comparing(BillAction::getSequence)).toList(); + List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event).stream() + .sorted(Comparator.comparing(MemberAction::getSequence)).toList(); + + return getActionAppResponses(billActions, memberActions); + } + + private List<ActionAppResponse> getActionAppResponses( + List<BillAction> billActions, + List<MemberAction> memberActions + ) { + int billActionIndex = 0; + int memberActionIndex = 0; + List<ActionAppResponse> actionAppResponses = new ArrayList<>(); + + while (billActionIndex < billActions.size() && memberActionIndex < memberActions.size()) { + BillAction billAction = billActions.get(billActionIndex); + MemberAction memberAction = memberActions.get(memberActionIndex); + if (billAction.getSequence() < memberAction.getSequence()) { + actionAppResponses.add(ActionAppResponse.of(billAction)); + billActionIndex++; + } else { + actionAppResponses.add(ActionAppResponse.of(memberAction)); + memberActionIndex++; + } + } + while (billActionIndex < billActions.size()) { + BillAction billAction = billActions.get(billActionIndex++); + actionAppResponses.add(ActionAppResponse.of(billAction)); + } + while (memberActionIndex < memberActions.size()) { + MemberAction memberAction = memberActions.get(memberActionIndex++); + actionAppResponses.add(ActionAppResponse.of(memberAction)); + } + + return actionAppResponses; + } +} diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java new file mode 100644 index 000000000..cbe34f0ef --- /dev/null +++ b/server/src/main/java/server/haengdong/application/MemberActionFactory.java @@ -0,0 +1,82 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.action.MemberGroupIdProvider; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Component +public class MemberActionFactory { + + private final MemberGroupIdProvider memberGroupIdProvider; + + public List<MemberAction> createMemberActions( + MemberActionsSaveAppRequest request, + List<MemberAction> memberActions, + Action action + ) { + validateMemberNames(request); + validateActions(request, memberActions); + + Long memberGroupId = memberGroupIdProvider.createGroupId(); + List<MemberAction> createdMemberActions = new ArrayList<>(); + List<MemberActionSaveAppRequest> actions = request.actions(); + for (MemberActionSaveAppRequest appRequest : actions) { + MemberAction memberAction = appRequest.toMemberAction(action, memberGroupId); + createdMemberActions.add(memberAction); + action = action.next(); + } + + return createdMemberActions; + } + + private void validateMemberNames(MemberActionsSaveAppRequest request) { + List<String> memberNames = request.actions().stream() + .map(MemberActionSaveAppRequest::name) + .toList(); + + long uniqueCount = memberNames.stream().distinct().count(); + if (uniqueCount != memberNames.size()) { + throw new HaengdongException(HaengdongErrorCode.DUPLICATED_MEMBER_ACTION); + } + } + + private void validateActions(MemberActionsSaveAppRequest request, List<MemberAction> memberActions) { + List<MemberAction> reverseSortedMemberActions = memberActions.stream() + .sorted(Comparator.comparing(MemberAction::getSequence).reversed()) + .toList(); + + for (MemberActionSaveAppRequest action : request.actions()) { + validateAction(action, reverseSortedMemberActions); + } + } + + private void validateAction(MemberActionSaveAppRequest request, List<MemberAction> memberActions) { + MemberActionStatus memberActionStatus = MemberActionStatus.of(request.status()); + if (isInvalidStatus(memberActions, request.name(), memberActionStatus)) { + throw new HaengdongException(HaengdongErrorCode.INVALID_MEMBER_ACTION); + } + } + + private boolean isInvalidStatus( + List<MemberAction> memberActions, + String memberName, + MemberActionStatus memberActionStatus + ) { + return memberActions.stream() + .filter(action -> action.isSameName(memberName)) + .findFirst() + .map(action -> action.isSameStatus(memberActionStatus)) + .orElse(MemberActionStatus.IN != memberActionStatus); + } +} diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java new file mode 100644 index 000000000..5094bf2c0 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/MemberActionService.java @@ -0,0 +1,60 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class MemberActionService { + + private final MemberActionFactory memberActionFactory; + private final MemberActionRepository memberActionRepository; + private final EventRepository eventRepository; + private final ActionRepository actionRepository; + + @Transactional + public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { + Event event = findEvent(token); + + List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); + Action action = createStartAction(event); + List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, findMemberActions, action); + memberActionRepository.saveAll(memberActions); + } + + private Action createStartAction(Event event) { + return actionRepository.findLastByEvent(event) + .map(Action::next) + .orElse(Action.createFirst(event)); + } + + public List<CurrentMemberAppResponse> getCurrentMembers(String token) { + Event event = findEvent(token); + List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); + CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); + + return currentMembers.getMembers() + .stream() + .map(CurrentMemberAppResponse::new) + .toList(); + } + + private Event findEvent(String token) { + return eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java new file mode 100644 index 000000000..acd0149f9 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java @@ -0,0 +1,14 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; + +public record BillActionAppRequest( + String title, + Long price +) { + + public BillAction toBillAction(Action action) { + return new BillAction(action, title, price); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java new file mode 100644 index 000000000..1eea6adf4 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java @@ -0,0 +1,10 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.event.Event; + +public record EventAppRequest(String name) { + + public Event toEvent(String token) { + return new Event(name, token); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java new file mode 100644 index 000000000..f7f8d8fc2 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java @@ -0,0 +1,12 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; + +public record MemberActionSaveAppRequest(String name, String status) { + + public MemberAction toMemberAction(Action action, Long memberGroupId) { + return new MemberAction(action, name, MemberActionStatus.of(status), memberGroupId); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java new file mode 100644 index 000000000..650b908df --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java @@ -0,0 +1,6 @@ +package server.haengdong.application.request; + +import java.util.List; + +public record MemberActionsSaveAppRequest(List<MemberActionSaveAppRequest> actions) { +} diff --git a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java new file mode 100644 index 000000000..a1abcc35b --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java @@ -0,0 +1,54 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; + +public record ActionAppResponse( + Long actionId, + String name, + Long price, + Long sequence, + ActionType actionType +) { + + public static ActionAppResponse of(BillAction billAction) { + return new ActionAppResponse( + billAction.getAction().getId(), + billAction.getTitle(), + billAction.getPrice(), + billAction.getSequence(), + ActionType.BILL + ); + } + + public static ActionAppResponse of(MemberAction memberAction) { + MemberActionStatus status = memberAction.getStatus(); + + return new ActionAppResponse( + memberAction.getAction().getId(), + memberAction.getMemberName(), + null, + memberAction.getSequence(), + ActionType.of(status) + ); + } + + public String actionTypeName() { + return actionType.name(); + } + + public enum ActionType { + BILL, + IN, + OUT, + ; + + private static ActionType of(MemberActionStatus memberActionStatus) { + if (MemberActionStatus.IN == memberActionStatus) { + return IN; + } + return OUT; + } + } +} diff --git a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java new file mode 100644 index 000000000..6c682d3e9 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.MemberAction; + +public record CurrentMemberAppResponse(String name) { + + public static CurrentMemberAppResponse of(MemberAction memberAction) { + return new CurrentMemberAppResponse(memberAction.getMemberName()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java new file mode 100644 index 000000000..f331d0011 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.event.Event; + +public record EventAppResponse(String token) { + + public static EventAppResponse of(Event event) { + return new EventAppResponse(event.getToken()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java new file mode 100644 index 000000000..6e38826d4 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.event.Event; + +public record EventDetailAppResponse(String eventName) { + + public static EventDetailAppResponse of(Event event) { + return new EventDetailAppResponse(event.getName()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java new file mode 100644 index 000000000..21b6cef56 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java @@ -0,0 +1,4 @@ +package server.haengdong.application.response; + +public record MemberBillReportAppResponse(String name, Long price) { +} diff --git a/server/src/main/java/server/haengdong/config/WebConfig.java b/server/src/main/java/server/haengdong/config/WebConfig.java new file mode 100644 index 000000000..129d8b790 --- /dev/null +++ b/server/src/main/java/server/haengdong/config/WebConfig.java @@ -0,0 +1,27 @@ +package server.haengdong.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@RequiredArgsConstructor +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Value("${cors.max-age}") + private Long maxAge; + + @Value("${cors.allowed-origins}") + private String[] allowedOrigins; + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins(allowedOrigins) + .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") + .allowedHeaders("*") + .maxAge(maxAge); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/Action.java b/server/src/main/java/server/haengdong/domain/action/Action.java new file mode 100644 index 000000000..11f91fc38 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/Action.java @@ -0,0 +1,42 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.domain.event.Event; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Action { + + private static final long FIRST_SEQUENCE = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Event event; + + private Long sequence; + + public Action(Event event, Long sequence) { + this.event = event; + this.sequence = sequence; + } + + public static Action createFirst(Event event) { + return new Action(event, FIRST_SEQUENCE); + } + + public Action next() { + return new Action(event, sequence + 1); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java new file mode 100644 index 000000000..c2138e42f --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java @@ -0,0 +1,21 @@ +package server.haengdong.domain.action; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface ActionRepository extends JpaRepository<Action, Long> { + + @Query(""" + SELECT a + FROM Action a + WHERE a.event = :event + ORDER BY a.sequence DESC + LIMIT 1 + """) + Optional<Action> findLastByEvent(@Param("event") Event event); +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java new file mode 100644 index 000000000..1027206f5 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillAction.java @@ -0,0 +1,70 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class BillAction implements Comparable<BillAction> { + + private static final int MIN_TITLE_LENGTH = 2; + private static final int MAX_TITLE_LENGTH = 30; + private static final long MIN_PRICE = 1L; + private static final long MAX_PRICE = 10_000_000L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + private Action action; + + @Column(length = MAX_TITLE_LENGTH) + private String title; + + private Long price; + + public BillAction(Action action, String title, Long price) { + validateTitle(title); + validatePrice(price); + this.action = action; + this.title = title.trim(); + this.price = price; + } + + private void validateTitle(String title) { + int titleLength = title.trim().length(); + if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { + throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", MIN_TITLE_LENGTH, MAX_TITLE_LENGTH)); + } + } + + private void validatePrice(Long price) { + if (price < MIN_PRICE || price > MAX_PRICE) { + throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", MAX_PRICE)); + } + } + + public Long getSequence() { + return action.getSequence(); + } + + @Override + public int compareTo(BillAction o) { + return Long.compare(this.getSequence(), o.getSequence()); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java new file mode 100644 index 000000000..1ad7416aa --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java @@ -0,0 +1,14 @@ +package server.haengdong.domain.action; + +import java.util.List; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface BillActionRepository extends JpaRepository<BillAction, Long> { + + @EntityGraph(attributePaths = {"action"}) + List<BillAction> findByAction_Event(Event event); +} diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java new file mode 100644 index 000000000..298a8a965 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java @@ -0,0 +1,66 @@ +package server.haengdong.domain.action; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class CurrentMembers { + + private final Set<String> members; + + public CurrentMembers() { + this(new HashSet<>()); + } + + private CurrentMembers(Set<String> members) { + this.members = members; + } + + public static CurrentMembers of(List<MemberAction> memberActions) { + List<MemberAction> sortedMemberActions = getSortedMemberActions(memberActions); + Set<String> members = new HashSet<>(); + for (MemberAction memberAction : sortedMemberActions) { + String member = memberAction.getMemberName(); + if (memberAction.isSameStatus(MemberActionStatus.IN)) { + members.add(member); + continue; + } + members.remove(member); + } + + return new CurrentMembers(members); + } + + private static List<MemberAction> getSortedMemberActions(List<MemberAction> memberActions) { + return memberActions.stream() + .sorted(Comparator.comparing(MemberAction::getSequence)) + .toList(); + } + + public CurrentMembers addMemberAction(MemberAction memberAction) { + String memberName = memberAction.getMemberName(); + + Set<String> currentMembers = new HashSet<>(members); + + if (memberAction.isIn()) { + currentMembers.add(memberName); + } else { + currentMembers.remove(memberName); + } + return new CurrentMembers(currentMembers); + } + + public boolean isEmpty() { + return members.isEmpty(); + } + + public int size() { + return members.size(); + } + + public Set<String> getMembers() { + return Collections.unmodifiableSet(members); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java new file mode 100644 index 000000000..67387cbde --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberAction.java @@ -0,0 +1,62 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class MemberAction implements Comparable<MemberAction> { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + private Action action; + + private String memberName; + + @Enumerated(EnumType.STRING) + private MemberActionStatus status; + + private Long memberGroupId; + + public MemberAction(Action action, String memberName, MemberActionStatus status, Long memberGroupId) { + this.action = action; + this.memberName = memberName; + this.status = status; + this.memberGroupId = memberGroupId; + } + + public boolean isSameName(String name) { + return memberName.equals(name); + } + + public boolean isIn() { + return status == MemberActionStatus.IN; + } + + public boolean isSameStatus(MemberActionStatus memberActionStatus) { + return status == memberActionStatus; + } + + public Long getSequence() { + return action.getSequence(); + } + + @Override + public int compareTo(MemberAction o) { + return Long.compare(this.getSequence(), o.getSequence()); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java new file mode 100644 index 000000000..6c4769e61 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java @@ -0,0 +1,15 @@ +package server.haengdong.domain.action; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface MemberActionRepository extends JpaRepository<MemberAction, Long> { + + @Query("select m from MemberAction m join fetch m.action where m.action.event = :event") + List<MemberAction> findAllByEvent(@Param("event") Event event); +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java new file mode 100644 index 000000000..0a20817fd --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java @@ -0,0 +1,19 @@ +package server.haengdong.domain.action; + +import java.util.Arrays; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +public enum MemberActionStatus { + IN, + OUT, + ; + + public static MemberActionStatus of(String status) { + return Arrays.stream(MemberActionStatus.values()) + .filter(s -> s.name().equals(status)) + .findFirst() + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + "존재하지 않는 인원 변동 액션입니다.")); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java new file mode 100644 index 000000000..dbf2b49ac --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java @@ -0,0 +1,75 @@ +package server.haengdong.domain.action; + +import static java.util.stream.Collectors.toMap; + +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.function.Function; +import lombok.Getter; + +@Getter +public class MemberBillReport { + + private final Map<String, Long> reports; + + private MemberBillReport(Map<String, Long> reports) { + this.reports = reports; + } + + public static MemberBillReport createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { + PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); + PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); + + Map<String, Long> memberBillReports = initReports(memberActions); + CurrentMembers currentMembers = new CurrentMembers(); + while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { + if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { + MemberAction memberAction = sortedMemberActions.poll(); + currentMembers = currentMembers.addMemberAction(memberAction); + continue; + } + addBillAction(sortedBillActions, currentMembers, memberBillReports); + } + + while (!sortedBillActions.isEmpty()) { + addBillAction(sortedBillActions, currentMembers, memberBillReports); + } + + return new MemberBillReport(memberBillReports); + } + + private static Map<String, Long> initReports(List<MemberAction> memberActions) { + return memberActions.stream() + .map(MemberAction::getMemberName) + .distinct() + .collect(toMap(Function.identity(), i -> 0L)); + } + + private static boolean isMemberActionTurn( + PriorityQueue<MemberAction> memberActions, + PriorityQueue<BillAction> billActions + ) { + MemberAction memberAction = memberActions.peek(); + BillAction billAction = billActions.peek(); + + return memberAction.getSequence() < billAction.getSequence(); + } + + private static void addBillAction( + PriorityQueue<BillAction> sortedBillActions, + CurrentMembers currentMembers, + Map<String, Long> memberBillReports + ) { + BillAction billAction = sortedBillActions.poll(); + if (currentMembers.isEmpty()) { + return; + } + + Long pricePerMember = billAction.getPrice() / currentMembers.size(); + for (String currentMember : currentMembers.getMembers()) { + Long price = memberBillReports.get(currentMember) + pricePerMember; + memberBillReports.put(currentMember, price); + } + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java new file mode 100644 index 000000000..9e32bd733 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java @@ -0,0 +1,11 @@ +package server.haengdong.domain.action; + +import org.springframework.stereotype.Component; + +@Component +public class MemberGroupIdProvider { + + public Long createGroupId() { + return System.currentTimeMillis(); + } +} diff --git a/server/src/main/java/server/haengdong/domain/event/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java new file mode 100644 index 000000000..24369a184 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/Event.java @@ -0,0 +1,54 @@ +package server.haengdong.domain.event; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Event { + + private static final int MIN_NAME_LENGTH = 2; + private static final int MAX_NAME_LENGTH = 20; + private static final String SPACES = " "; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + private String token; + + public Event(String name, String token) { + validateName(name); + this.name = name; + this.token = token; + } + + private void validateName(String name) { + int nameLength = name.length(); + if (nameLength < MIN_NAME_LENGTH || MAX_NAME_LENGTH < nameLength) { + throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", + MIN_NAME_LENGTH, + MAX_NAME_LENGTH, + name.length())); + } + if (isBlankContinuous(name)) { + throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, + String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", name)); + } + } + + private boolean isBlankContinuous(String name) { + return name.contains(SPACES); + } +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java new file mode 100644 index 000000000..6038c368b --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventRepository.java @@ -0,0 +1,11 @@ +package server.haengdong.domain.event; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EventRepository extends JpaRepository<Event, Long> { + + Optional<Event> findByToken(String token); +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventStep.java b/server/src/main/java/server/haengdong/domain/event/EventStep.java new file mode 100644 index 000000000..297abdb66 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventStep.java @@ -0,0 +1,28 @@ +package server.haengdong.domain.event; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class EventStep { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Event event; + + private String name; + + private Long sequence; +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java new file mode 100644 index 000000000..6450f0dcf --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java @@ -0,0 +1,12 @@ +package server.haengdong.domain.event; + +import java.util.UUID; +import org.springframework.stereotype.Component; + +@Component +public class EventTokenProvider { + + public String createToken() { + return UUID.randomUUID().toString(); + } +} diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java new file mode 100644 index 000000000..c797b811a --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/ErrorResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.exception; + +public record ErrorResponse( + String message +) { + + public static ErrorResponse of(String message) { + return new ErrorResponse(message); + } +} diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java new file mode 100644 index 000000000..bb3138cc7 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java @@ -0,0 +1,43 @@ +package server.haengdong.exception; + +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ResponseEntity<ErrorResponse> haengdongException() { + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.BAD_REQUEST.getMessage())); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + String errorMessage = e.getFieldErrors().stream() + .map(error -> error.getField() + " " + error.getDefaultMessage()) + .collect(Collectors.joining(", ")); + + return ResponseEntity.badRequest() + .body(ErrorResponse.of(errorMessage)); + } + + @ExceptionHandler(HaengdongException.class) + public ResponseEntity<ErrorResponse> haengdongException(HaengdongException e) { + return ResponseEntity.status(e.getStatusCode()) + .body(ErrorResponse.of(e.getMessage())); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity<ErrorResponse> handleException(Exception e) { + log.error(e.getMessage(), e); + return ResponseEntity.internalServerError() + .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR.getMessage())); + } +} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java new file mode 100644 index 000000000..792baa838 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java @@ -0,0 +1,24 @@ +package server.haengdong.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public enum HaengdongErrorCode { + BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."), + DUPLICATED_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "올바르지 않은 인원 요청입니다."), + INVALID_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "잘못된 맴버 액션입니다."), + + NOT_FOUND_EVENT(HttpStatus.NOT_FOUND, "존재하지 않는 행사입니다."), + + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 내부에서 에러가 발생했습니다."), + ; + + private final HttpStatus httpStatus; + private final String message; + + HaengdongErrorCode(HttpStatus httpStatus, String message) { + this.httpStatus = httpStatus; + this.message = message; + } +} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongException.java b/server/src/main/java/server/haengdong/exception/HaengdongException.java new file mode 100644 index 000000000..812df50f8 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/HaengdongException.java @@ -0,0 +1,32 @@ +package server.haengdong.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatusCode; + +@Getter +public class HaengdongException extends RuntimeException { + + private final HaengdongErrorCode errorCode; + private final String message; + + public HaengdongException(HaengdongErrorCode errorCode) { + this(errorCode, null); + } + + public HaengdongException(HaengdongErrorCode errorCode, String message) { + this.errorCode = errorCode; + this.message = message; + } + + public HttpStatusCode getStatusCode() { + return errorCode.getHttpStatus(); + } + + @Override + public String getMessage() { + if (message == null) { + return errorCode.getMessage(); + } + return message; + } +} diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java new file mode 100644 index 000000000..657cb567e --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/ActionController.java @@ -0,0 +1,26 @@ +package server.haengdong.presentation; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.ActionService; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.presentation.response.MemberBillReportsResponse; + +@RequiredArgsConstructor +@RestController +public class ActionController { + + private final ActionService actionService; + + @GetMapping("/api/events/{eventId}/actions/reports") + public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("eventId") String token) { + List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); + + return ResponseEntity.ok() + .body(MemberBillReportsResponse.of(memberBillReports)); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java new file mode 100644 index 000000000..fcdacb270 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/BillActionController.java @@ -0,0 +1,29 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.BillActionService; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +@RequiredArgsConstructor +@RestController +public class BillActionController { + + private final BillActionService billActionService; + + @PostMapping("/api/events/{eventId}/actions/bills") + public ResponseEntity<Void> saveAllBillAction( + @PathVariable("eventId") String token, + @RequestBody @Valid BillActionsSaveRequest request + ) { + billActionService.saveAllBillAction(token, request.toAppRequests()); + + return ResponseEntity.ok() + .build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java new file mode 100644 index 000000000..9fbe098ce --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -0,0 +1,43 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.EventService; +import server.haengdong.presentation.request.EventSaveRequest; +import server.haengdong.presentation.response.EventDetailResponse; +import server.haengdong.presentation.response.EventResponse; +import server.haengdong.presentation.response.StepResponse; + +@RequiredArgsConstructor +@RestController +public class EventController { + + private final EventService eventService; + + @PostMapping("/api/events") + public ResponseEntity<EventResponse> saveEvent(@Valid @RequestBody EventSaveRequest request) { + EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); + + return ResponseEntity.ok(eventResponse); + } + + @GetMapping("/api/events/{eventId}") + public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") String token) { + EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); + + return ResponseEntity.ok(eventDetailResponse); + } + + @GetMapping("/api/events/{eventId}/actions") + public ResponseEntity<StepResponse> findActions(@PathVariable("eventId") String token) { + StepResponse stepResponse = StepResponse.of(eventService.findActions(token)); + + return ResponseEntity.ok(stepResponse); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java new file mode 100644 index 000000000..c12370d86 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/MemberActionController.java @@ -0,0 +1,39 @@ +package server.haengdong.presentation; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.MemberActionService; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.presentation.request.MemberActionsSaveRequest; +import server.haengdong.presentation.response.CurrentMembersResponse; + +@RequiredArgsConstructor +@RestController +public class MemberActionController { + + private final MemberActionService memberActionService; + + @PostMapping("/api/events/{eventId}/actions/members") + public ResponseEntity<Void> saveMemberAction( + @PathVariable("eventId") String token, + @RequestBody MemberActionsSaveRequest request + ) { + memberActionService.saveMemberAction(token, request.toAppRequest()); + + return ResponseEntity.ok().build(); + } + + @GetMapping("/api/events/{eventId}/members/current") + public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("eventId") String token) { + List<CurrentMemberAppResponse> currentMembers = memberActionService.getCurrentMembers(token); + + return ResponseEntity.ok() + .body(CurrentMembersResponse.of(currentMembers)); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java new file mode 100644 index 000000000..a0d878f7f --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java @@ -0,0 +1,19 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import server.haengdong.application.request.BillActionAppRequest; + +public record BillActionSaveRequest( + + @NotBlank + String title, + + @NotNull + Long price +) { + + public BillActionAppRequest toAppRequest() { + return new BillActionAppRequest(title, price); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java new file mode 100644 index 000000000..68784039b --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java @@ -0,0 +1,14 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.Valid; +import java.util.List; +import server.haengdong.application.request.BillActionAppRequest; + +public record BillActionsSaveRequest(@Valid List<BillActionSaveRequest> actions) { + + public List<BillActionAppRequest> toAppRequests() { + return actions.stream() + .map(BillActionSaveRequest::toAppRequest) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java new file mode 100644 index 000000000..b28572332 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import server.haengdong.application.request.EventAppRequest; + +public record EventSaveRequest( + + @NotBlank + String eventName +) { + + public EventAppRequest toAppRequest() { + return new EventAppRequest(eventName); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java new file mode 100644 index 000000000..0b3fcebae --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java @@ -0,0 +1,22 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import java.util.List; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; + +public record MemberActionsSaveRequest( + List<String> members, + + @NotBlank + String status +) { + + public MemberActionsSaveAppRequest toAppRequest() { + List<MemberActionSaveAppRequest> appRequests = members.stream() + .map(name -> new MemberActionSaveAppRequest(name, status)) + .toList(); + + return new MemberActionsSaveAppRequest(appRequests); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java new file mode 100644 index 000000000..a58e60186 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java @@ -0,0 +1,20 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.ActionAppResponse; + +public record ActionResponse( + Long actionId, + String name, + Long price, + Long sequence +) { + + public static ActionResponse of(ActionAppResponse actionAppResponse) { + return new ActionResponse( + actionAppResponse.actionId(), + actionAppResponse.name(), + actionAppResponse.price(), + actionAppResponse.sequence() + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java new file mode 100644 index 000000000..188c48dc9 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java @@ -0,0 +1,28 @@ +package server.haengdong.presentation.response; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import server.haengdong.application.response.ActionAppResponse; + +public record ActionsResponse( + String type, + String stepName, + Set<String> members, + List<ActionResponse> actions +) { + + public static ActionsResponse of(List<ActionAppResponse> actions, Set<String> members) { + List<ActionResponse> actionResponses = actions.stream() + .map(ActionResponse::of) + .toList(); + + String actionType = actions.get(0).actionTypeName(); + return new ActionsResponse( + actionType, + null, + new HashSet<>(members), + actionResponses + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java new file mode 100644 index 000000000..4308c7d17 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.CurrentMemberAppResponse; + +public record CurrentMemberResponse(String name) { + + public static CurrentMemberResponse of(CurrentMemberAppResponse response) { + return new CurrentMemberResponse(response.name()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java new file mode 100644 index 000000000..4eb915dd4 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.CurrentMemberAppResponse; + +public record CurrentMembersResponse(List<CurrentMemberResponse> members) { + + public static CurrentMembersResponse of(List<CurrentMemberAppResponse> currentMembers) { + List<CurrentMemberResponse> responses = currentMembers.stream() + .map(CurrentMemberResponse::of) + .toList(); + + return new CurrentMembersResponse(responses); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java new file mode 100644 index 000000000..c18694393 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.EventDetailAppResponse; + +public record EventDetailResponse(String eventName) { + + public static EventDetailResponse of(EventDetailAppResponse response) { + return new EventDetailResponse(response.eventName()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java new file mode 100644 index 000000000..506f5e814 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.EventAppResponse; + +public record EventResponse(String eventId) { + + public static EventResponse of(EventAppResponse eventAppResponse) { + return new EventResponse(eventAppResponse.token()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java new file mode 100644 index 000000000..0ea409202 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.MemberBillReportAppResponse; + +public record MemberBillReportResponse(String name, Long price) { + + public static MemberBillReportResponse of(MemberBillReportAppResponse memberBillReportAppResponse) { + return new MemberBillReportResponse(memberBillReportAppResponse.name(), memberBillReportAppResponse.price()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java new file mode 100644 index 000000000..d350c4009 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.MemberBillReportAppResponse; + +public record MemberBillReportsResponse(List<MemberBillReportResponse> reports) { + + public static MemberBillReportsResponse of(List<MemberBillReportAppResponse> memberBillReports) { + List<MemberBillReportResponse> reports = memberBillReports.stream() + .map(MemberBillReportResponse::of) + .toList(); + + return new MemberBillReportsResponse(reports); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java new file mode 100644 index 000000000..a8f3877ef --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java @@ -0,0 +1,57 @@ +package server.haengdong.presentation.response; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import server.haengdong.application.response.ActionAppResponse; + +public record StepResponse( + List<ActionsResponse> steps +) { + + public static StepResponse of(List<ActionAppResponse> actions) { + if (actions.isEmpty()) { + return new StepResponse(List.of()); + } + List<ActionsResponse> actionsResponse = new ArrayList<>(); + Set<String> members = new HashSet<>(); + ActionAppResponse firstAction = getFirstAction(actions); + List<ActionAppResponse> group = new ArrayList<>(); + group.add(firstAction); + String currentActionType = firstAction.actionTypeName(); + members.add(firstAction.name()); + + for (int i = 1; i < actions.size(); i++) { + ActionAppResponse action = actions.get(i); + String typeName = action.actionTypeName(); + if (currentActionType.equals(typeName)) { + if (typeName.equals("IN")) { + members.add(action.name()); + } + if (typeName.equals("OUT")) { + members.remove(action.name()); + } + group.add(action); + continue; + } + actionsResponse.add(ActionsResponse.of(group, members)); + currentActionType = typeName; + group.clear(); + if (typeName.equals("IN")) { + members.add(action.name()); + } + if (typeName.equals("OUT")) { + members.remove(action.name()); + } + group.add(action); + } + actionsResponse.add(ActionsResponse.of(group, members)); + + return new StepResponse(actionsResponse); + } + + private static ActionAppResponse getFirstAction(List<ActionAppResponse> actions) { + return actions.get(0); + } +} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml new file mode 100644 index 000000000..faf7a36f1 --- /dev/null +++ b/server/src/main/resources/application.yml @@ -0,0 +1,31 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:database + username: sa + password: + + h2: + console: + enabled: true + path: /h2-console + + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + format_sql: true + show-sql: true + +cors: + max-age: 3600 + allowed-origins: http://localhost:3000, https://haengdong.pro, https://dev.haengdong.pro, https://app.haengdong.pro + +--- + +spring: + config: + import: classpath:config/application-dev.yml + activate: + on-profile: dev diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java new file mode 100644 index 000000000..ac2dc4f4f --- /dev/null +++ b/server/src/test/java/server/haengdong/application/ActionServiceTest.java @@ -0,0 +1,79 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@SpringBootTest +class ActionServiceTest { + + @Autowired + private ActionService actionService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @DisplayName("참여자별 정산 현황을 조회한다.") + @Test + void getMemberBillReports() { + String token = "tOkEn1"; + Event event = new Event("행동대장", token); + Event savedEvent = eventRepository.save(event); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(savedEvent, 1L), "소하", IN, 1L), + new MemberAction(new Action(savedEvent, 2L), "감자", IN, 1L), + new MemberAction(new Action(savedEvent, 3L), "쿠키", IN, 1L), + new MemberAction(new Action(savedEvent, 5L), "감자", OUT, 2L) + ); + List<BillAction> billActions = List.of( + new BillAction(new Action(savedEvent, 4L), "뽕족", 60_000L), + new BillAction(new Action(savedEvent, 6L), "인생맥주", 40_000L), + new BillAction(new Action(savedEvent, 7L), "인생네컷", 20_000L) + ); + memberActionRepository.saveAll(memberActions); + billActionRepository.saveAll(billActions); + + List<MemberBillReportAppResponse> responses = actionService.getMemberBillReports(token); + + assertThat(responses) + .hasSize(3) + .extracting(MemberBillReportAppResponse::name, MemberBillReportAppResponse::price) + .containsExactlyInAnyOrder( + tuple("감자", 20_000L), + tuple("쿠키", 50_000L), + tuple("소하", 50_000L) + ); + } + + @DisplayName("존재하지 않는 이벤트의 참여자별 정산 현황을 조회하는 경우 예외가 발생한다.") + @Test + void getMemberBillReports1() { + assertThatThrownBy(() -> actionService.getMemberBillReports("invalid token")) + .isInstanceOf(HaengdongException.class) + .hasMessage(HaengdongErrorCode.NOT_FOUND_EVENT.getMessage()); + } +} diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java new file mode 100644 index 000000000..195d4bdd9 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -0,0 +1,65 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.request.BillActionAppRequest; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; + +@SpringBootTest +class BillActionServiceTest { + + @Autowired + private BillActionService billActionService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @DisplayName("지출 내역을 생성한다.") + @Test + void saveAllBillAction() { + String token = "TOKEN"; + Event event = new Event("감자", token); + Event savedEvent = eventRepository.save(event); + + List<BillActionAppRequest> requests = List.of( + new BillActionAppRequest("뽕족", 10_000L), + new BillActionAppRequest("인생맥주", 15_000L) + ); + + billActionService.saveAllBillAction(token, requests); + + List<BillAction> actions = billActionRepository.findByAction_Event(savedEvent); + + assertThat(actions).extracting(BillAction::getTitle, BillAction::getPrice, BillAction::getSequence) + .containsExactlyInAnyOrder( + tuple("뽕족", 10_000L, 1L), + tuple("인생맥주", 15_000L, 2L) + ); + } + + @DisplayName("이벤트가 존재하지 않으면 지출 내역을 생성할 수 없다.") + @Test + void saveAllBillAction1() { + List<BillActionAppRequest> requests = List.of( + new BillActionAppRequest("뽕족", 10_000L), + new BillActionAppRequest("인생맥주", 15_000L) + ); + + assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java new file mode 100644 index 000000000..5a3e8bce3 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -0,0 +1,110 @@ +package server.haengdong.application; + + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.BDDMockito.given; + +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.event.EventTokenProvider; + +@SpringBootTest +class EventServiceTest { + + @Autowired + private EventService eventService; + + @MockBean + private EventTokenProvider eventTokenProvider; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private ActionRepository actionRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @AfterEach + void tearDown() { + billActionRepository.deleteAllInBatch(); + memberActionRepository.deleteAllInBatch(); + actionRepository.deleteAllInBatch(); + eventRepository.deleteAllInBatch(); + } + + @DisplayName("행사를 생성한다") + @Test + void saveEventTest() { + EventAppRequest request = new EventAppRequest("test"); + given(eventTokenProvider.createToken()).willReturn("TOKEN"); + + EventAppResponse response = eventService.saveEvent(request); + + assertThat(response.token()).isEqualTo("TOKEN"); + } + + @DisplayName("토큰으로 행사를 조회한다.") + @Test + void findEventTest() { + String token = "TOKEN"; + Event event = new Event("행동대장 회식", token); + eventRepository.save(event); + + EventDetailAppResponse eventDetailAppResponse = eventService.findEvent(token); + + assertThat(eventDetailAppResponse.eventName()).isEqualTo("행동대장 회식"); + } + + @DisplayName("행사에 속한 모든 액션을 조회한다.") + @Test + void findActionsTest() { + Event event = new Event("행동대장 회식", "웨디_토큰"); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + Action action1 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "쿠키", MemberActionStatus.IN, 1L); + Action action2 = new Action(event, 3L); + BillAction billAction = new BillAction(action2, "뽕나무쟁이족발", 30000L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction, memberAction1)); + billActionRepository.save(billAction); + + List<ActionAppResponse> actionAppResponses = eventService.findActions("웨디_토큰"); + + assertThat(actionAppResponses).hasSize(3) + .extracting(ActionAppResponse::actionId, + ActionAppResponse::name, + ActionAppResponse::price, + ActionAppResponse::sequence, + ActionAppResponse::actionTypeName) + .containsExactly( + tuple(1L, "토다리", null, 1L, "IN"), + tuple(2L, "쿠키", null, 2L, "IN"), + tuple(3L, "뽕나무쟁이족발", 30000L, 3L, "BILL") + ); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java new file mode 100644 index 000000000..40bee2ff6 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java @@ -0,0 +1,217 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; + +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.exception.HaengdongException; + +@SpringBootTest +class MemberActionFactoryTest { + + @Autowired + private MemberActionFactory memberActionFactory; + + @Autowired + private MemberActionRepository memberActionRepository; + + @Autowired + private ActionRepository actionRepository; + + @Autowired + private EventRepository eventRepository; + + @AfterEach + void tearDown() { + memberActionRepository.deleteAllInBatch(); + actionRepository.deleteAllInBatch(); + eventRepository.deleteAllInBatch(); + } + + @DisplayName("이전 멤버 액션이 시퀀스 기준으로 정렬되지 않은 상태에서 새로운 멤버 액션 요청을 검증한다.") + @Test + void createMemberActionsTest() { + Event event = eventRepository.save(new Event("우당탕탕 행동대장 백엔드 회식", "토다리_토큰")); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + List<MemberAction> unorderedMemberActions = List.of(memberAction2, memberAction1); + Action startAction = new Action(event, 3L); + + assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, unorderedMemberActions, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("인원 변동 액션을 생성한다.") + @Test + void createMemberActionsTest1() { + Event event = eventRepository.save(new Event("우당탕탕 행동대장 백엔드 회식", "토다리_토큰")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest memberActionsSaveAppRequest = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + Action startAction = new Action(event, 2L); + + List<MemberAction> memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, + List.of(memberAction), startAction); + + assertThat(memberActions).hasSize(1) + .extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus) + .containsExactly( + tuple(startAction, "토다리", MemberActionStatus.OUT) + ); + } + + @DisplayName("현재 행사에 참여 중인 경우에 퇴장할 수 있다.") + @Test + void createMemberActionsTest2() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") + @Test + void createMemberActionsTest3() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action1 = new Action(event, 1L); + MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction1); + Action action2 = new Action(event, 2L); + MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); + memberActionRepository.save(memberAction2); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "IN"))); + Action startAction = new Action(event, 3L); + + assertThatCode( + () -> memberActionFactory.createMemberActions(request, List.of(memberAction1, memberAction2), + startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장한 적 없는 경우에 입장할 수 있다.") + @Test + void createMemberActionsTest4() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") + @Test + void createMemberActionTest5() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "OUT"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("행사에 이미 참여 중인 경우 다시 입장할 수 없다.") + @Test + void createMemberActionTest6() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("한 명의 사용자는 동시에 여러 번 입장할 수 없다.") + @Test + void createMemberActionTest7() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"), + new MemberActionSaveAppRequest("쿠키", "IN"))); + Action startAction = new Action(event, 1L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("한 명의 사용자는 동시에 여러 번 퇴장할 수 없다.") + @Test + void createMemberActionTest8() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "OUT"), + new MemberActionSaveAppRequest("쿠키", "OUT"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("한 명의 사용자는 입장과 퇴장을 동시에 할 수 없다.") + @Test + void createMemberActionTest9() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"), + new MemberActionSaveAppRequest("쿠키", "OUT"))); + Action startAction = new Action(event, 2L); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java new file mode 100644 index 000000000..7212e300d --- /dev/null +++ b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java @@ -0,0 +1,92 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; + +@SpringBootTest +class MemberActionServiceTest { + + @Autowired + private MemberActionService memberActionService; + + @Autowired + private MemberActionRepository memberActionRepository; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private ActionRepository actionRepository; + + @AfterEach + void tearDown() { + memberActionRepository.deleteAllInBatch(); + actionRepository.deleteAllInBatch(); + eventRepository.deleteAllInBatch(); + } + + @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다.") + @Test + void saveMemberActionTest() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "망쵸", IN, 1L); + memberActionRepository.save(memberAction); + + assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("망쵸", "OUT"))))) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") + @Test + void saveMemberActionTest1() { + Event event = eventRepository.save(new Event("test", "TOKEN")); + Action actionOne = new Action(event, 1L); + MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", IN, 1L); + memberActionRepository.save(memberActionOne); + + Action actionTwo = new Action(event, 2L); + MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", OUT, 1L); + memberActionRepository.save(memberActionTwo); + + assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("망쵸", "IN"))))) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") + @Test + void saveMemberActionTest2() { + MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); + + assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("이벤트가 없으면 현재 참여 인원을 조회할 수 없다.") + @Test + void getCurrentMembers() { + assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/ActionTest.java b/server/src/test/java/server/haengdong/domain/action/ActionTest.java new file mode 100644 index 000000000..199a4f628 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/ActionTest.java @@ -0,0 +1,30 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; + +class ActionTest { + + @DisplayName("액션의 초기 순서번호는 1이다.") + @Test + void createFirst() { + Event event = new Event("name", "token"); + Action action = Action.createFirst(event); + + assertThat(action.getSequence()).isOne(); + } + + @DisplayName("현재 액션의 다음 액션의 순서는 1만큼 증가한다.") + @Test + void next() { + Event event = new Event("name", "token"); + Action action = new Action(event, 2L); + + Action nextAction = action.next(); + + assertThat(nextAction.getSequence()).isEqualTo(3L); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java new file mode 100644 index 000000000..601ca95d7 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java @@ -0,0 +1,58 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongException; + +class BillActionTest { + + @DisplayName("지출 내역 제목의 앞뒤 공백을 제거한 길이가 2 ~ 30자가 아니면 지출을 생성할 수 없다.") + @ParameterizedTest + @ValueSource(strings = {" 감 ", "", " ", "1234567890123456789012345678901"}) + void validateTitle(String title) { + Event event = new Event("name", "token"); + Action action = new Action(event, 1L); + Long price = 100L; + + assertThatThrownBy(() -> new BillAction(action, title, price)) + .isInstanceOf(HaengdongException.class) + .hasMessage("앞뒤 공백을 제거한 지출 내역 제목은 2 ~ 30자여야 합니다."); + } + + @DisplayName("금액이 10,000,000 이하의 자연수가 아니면 지출을 생성할 수 없다.") + @ParameterizedTest + @ValueSource(longs = {0, 10_000_001, 20_000_000}) + void validatePrice(long price) { + Event event = new Event("name", "token"); + Action action = new Action(event, 1L); + String title = "title"; + + assertThatThrownBy(() -> new BillAction(action, title, price)) + .isInstanceOf(HaengdongException.class) + .hasMessage("지출 금액은 10,000,000 이하의 자연수여야 합니다."); + } + + @DisplayName("지출 내역을 올바르게 생성한다.") + @Test + void createBillAction() { + Event event = new Event("name", "token"); + Action action = new Action(event, 1L); + String title = "title"; + Long price = 1_000L; + + BillAction billAction = new BillAction(action, title, price); + + assertAll( + () -> assertThat(billAction.getAction()).isEqualTo(action), + () -> assertThat(billAction.getTitle()).isEqualTo(title), + () -> assertThat(billAction.getPrice()).isEqualTo(price) + ); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java new file mode 100644 index 000000000..389ca70c1 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java @@ -0,0 +1,58 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; + +class CurrentMembersTest { + + @DisplayName("인원 변동 이력으로 현재 참여 인원을 계산한다.") + @Test + void of() { + Event event = new Event("test", "TOKEN"); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(event, 1L), "망쵸", IN, 1L), + new MemberAction(new Action(event, 2L), "백호", IN, 1L), + new MemberAction(new Action(event, 3L), "백호", OUT, 1L), + new MemberAction(new Action(event, 4L), "웨디", IN, 1L) + ); + + CurrentMembers currentMembers = CurrentMembers.of(memberActions); + + assertThat(currentMembers.getMembers()) + .containsExactlyInAnyOrder("망쵸", "웨디"); + } + + @DisplayName("인원 변동 액션의 상태가 IN이면 현재 인원에 추가한다.") + @Test + void addMemberAction1() { + CurrentMembers currentMembers = new CurrentMembers(); + Event event = new Event("이벤트", "token"); + MemberAction memberAction = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); + + CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction); + Set<String> members = addedCurrentMembers.getMembers(); + + assertThat(members).hasSize(1) + .containsExactly("웨디"); + } + + @DisplayName("인원 변동 액션의 상태가 OUT이면 현재 인원에서 제외한다.") + @Test + void addMemberAction2() { + Event event = new Event("이벤트", "token"); + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); + CurrentMembers currentMembers = new CurrentMembers().addMemberAction(memberAction1); + MemberAction memberAction2 = new MemberAction(new Action(event, 1L), "웨디", OUT, 1L); + + CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction2); + + assertThat(addedCurrentMembers.getMembers()).hasSize(0); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java new file mode 100644 index 000000000..9ad27d5bc --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java @@ -0,0 +1,43 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; + +class MemberBillReportTest { + + @DisplayName("액션 목록으로 참가자 정산 리포트를 생성한다.") + @Test + void createByActions() { + String token = "TOK2N"; + Event event = new Event("행동대장", token); + List<BillAction> billActions = List.of( + new BillAction(new Action(event, 4L), "뽕족", 60_000L), + new BillAction(new Action(event, 6L), "인생맥주", 40_000L), + new BillAction(new Action(event, 7L), "인생네컷", 20_000L) + ); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(event, 1L), "소하", IN, 1L), + new MemberAction(new Action(event, 2L), "감자", IN, 1L), + new MemberAction(new Action(event, 3L), "쿠키", IN, 1L), + new MemberAction(new Action(event, 5L), "감자", OUT, 2L) + ); + + MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); + + assertThat(memberBillReport.getReports()) + .containsAllEntriesOf( + Map.of( + "감자", 20_000L, + "쿠키", 50_000L, + "소하", 50_000L + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/domain/event/EventTest.java b/server/src/test/java/server/haengdong/domain/event/EventTest.java new file mode 100644 index 000000000..98f6c7050 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/event/EventTest.java @@ -0,0 +1,37 @@ +package server.haengdong.domain.event; + +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.exception.HaengdongException; + +class EventTest { + + @DisplayName("공백 문자가 연속되지 않고, 이름이 2자 이상 20자 이하인 행사를 생성하면 예외가 발생하지 않는다.") + @ParameterizedTest + @ValueSource(strings = {"12", "12345678901234567890", "공 백", " 공백", "공백 ", " 공 백 "}) + void createSuccessTest(String eventName) { + assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) + .doesNotThrowAnyException(); + } + + @DisplayName("공백 문자가 연속되면 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {" 공백", "공백 ", "공백 연속", "공 백"}) + void createFailTest1(String eventName) { + assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class) + .hasMessage(String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", eventName)); + } + + @DisplayName("이름이 2자 미만이거나 20자 초과인 경우 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"", " ", "123456789012345678901"}) + void createFilTest2(String eventName) { + assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class) + .hasMessage(String.format("행사 이름은 2자 이상 20자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", eventName.length())); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java new file mode 100644 index 000000000..739ac4962 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java @@ -0,0 +1,49 @@ +package server.haengdong.presentation; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import server.haengdong.application.ActionService; +import server.haengdong.application.response.MemberBillReportAppResponse; + +@WebMvcTest(ActionController.class) +class ActionControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private ActionService actionService; + + @DisplayName("참여자별 정산 현황을 조회한다.") + @Test + void getMemberBillReports() throws Exception { + List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( + new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); + + given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); + + mockMvc.perform(get("/api/events/{token}/actions/reports", "token") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))); + + } +} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java new file mode 100644 index 000000000..8bf2b292f --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java @@ -0,0 +1,69 @@ +package server.haengdong.presentation; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import server.haengdong.application.BillActionService; +import server.haengdong.presentation.request.BillActionSaveRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +@WebMvcTest(BillActionController.class) +class BillActionControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private BillActionService billActionService; + + @DisplayName("지출 내역을 생성한다.") + @Test + void saveAllBillAction() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("뽕족", 10_000L), + new BillActionSaveRequest("인생맥주", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String token = "TOKEN"; + + mockMvc.perform(post("/api/events/{token}/actions/bills", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("title이 비어 있는 경우 지출 내역을 생성할 수 없다.") + @Test + void saveAllBillAction1() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("", 10_000L), + new BillActionSaveRequest("인생맥주", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String token = "TOKEN"; + + mockMvc.perform(post("/api/events/{token}/actions/bills", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isBadRequest()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java new file mode 100644 index 000000000..55a48630f --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java @@ -0,0 +1,66 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import server.haengdong.application.EventService; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.presentation.request.EventSaveRequest; + +@WebMvcTest(EventController.class) +class EventControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private EventService eventService; + + @DisplayName("이벤트를 생성한다.") + @Test + void saveEvent() throws Exception { + EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리"); + String requestBody = objectMapper.writeValueAsString(eventSaveRequest); + String token = "TOKEN"; + EventAppResponse eventAppResponse = new EventAppResponse(token); + given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); + + mockMvc.perform(post("/api/events") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.eventId").value("TOKEN")); + } + + @DisplayName("토큰으로 행사를 조회한다.") + @Test + void findEventTest() throws Exception { + String token = "TOKEN"; + EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); + given(eventService.findEvent(token)).willReturn(eventDetailAppResponse); + + mockMvc.perform(get("/api/events/" + token)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.eventName").value("행동대장 회식")); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java new file mode 100644 index 000000000..ad8787cc6 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java @@ -0,0 +1,67 @@ +package server.haengdong.presentation; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import server.haengdong.application.MemberActionService; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.presentation.request.MemberActionsSaveRequest; + +@WebMvcTest(MemberActionController.class) +class MemberActionControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private MemberActionService memberActionService; + + @DisplayName("참여자 행동을 추가한다.") + @Test + void saveMemberActionTest() throws Exception { + MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( + List.of("웨디", "소하", "토다리", "쿠키"), "IN"); + + String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); + + mockMvc.perform(post("/api/events/TOKEN/actions/members") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("현재 참여 인원을 조회합니다.") + @Test + void getCurrentMembers() throws Exception { + List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( + new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); + + given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); + + mockMvc.perform(get("/api/events/{token}/members/current", "token") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.members[0].name").value(equalTo("소하"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.members[1].name").value(equalTo("토다리"))); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java b/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java new file mode 100644 index 000000000..aac78691c --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java @@ -0,0 +1,57 @@ +package server.haengdong.presentation.response; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.ActionAppResponse.ActionType; + +@SpringBootTest +class StepResponseTest { + + @Autowired + private ObjectMapper objectMapper; + + @DisplayName("") + @Test + void test() throws JsonProcessingException { + List<ActionAppResponse> actionAppResponse = new ArrayList<>(); + + // IN actions + ActionAppResponse actionAppResponse1 = new ActionAppResponse(3L, "망쵸", null, 3L, ActionType.IN); + actionAppResponse.add(actionAppResponse1); + ActionAppResponse actionAppResponse2 = new ActionAppResponse(4L, "백호", null, 4L, ActionType.IN); + actionAppResponse.add(actionAppResponse2); + + // BILL step 1 + ActionAppResponse actionAppResponse3 = new ActionAppResponse(1L, "감자탕", 10000L, 1L, ActionType.BILL); + actionAppResponse.add(actionAppResponse3); + ActionAppResponse actionAppResponse4 = new ActionAppResponse(2L, "인생네컷", 10000L, 2L, ActionType.BILL); + actionAppResponse.add(actionAppResponse4); + + // IN actions + ActionAppResponse actionAppResponse5 = new ActionAppResponse(5L, "소하", null, 5L, ActionType.IN); + actionAppResponse.add(actionAppResponse5); + ActionAppResponse actionAppResponse6 = new ActionAppResponse(6L, "웨디", null, 6L, ActionType.IN); + actionAppResponse.add(actionAppResponse6); + + // OUT actions + ActionAppResponse actionAppResponse7 = new ActionAppResponse(7L, "망쵸", null, 7L, ActionType.OUT); + actionAppResponse.add(actionAppResponse7); + ActionAppResponse actionAppResponse8 = new ActionAppResponse(8L, "백호", null, 8L, ActionType.OUT); + actionAppResponse.add(actionAppResponse8); + + // BILL step 2 + ActionAppResponse actionAppResponse9 = new ActionAppResponse(9L, "노래방", 20000L, 10L, ActionType.BILL); + actionAppResponse.add(actionAppResponse9); + + // StepResponse creation + StepResponse stepResponse = StepResponse.of(actionAppResponse); + System.out.println("stepResponse = " + stepResponse); + } +} diff --git a/server/src/test/resources/application.yml b/server/src/test/resources/application.yml new file mode 100644 index 000000000..2d02b2712 --- /dev/null +++ b/server/src/test/resources/application.yml @@ -0,0 +1,18 @@ +spring: + h2: + console: + enabled: true + path: /h2-console + datasource: + url: jdbc:h2:mem:database + jpa: + defer-datasource-initialization: true + show-sql: true + properties: + hibernate: + format_sql: true + hibernate: + ddl-auto: create-drop +cors: + max-age: 3600 + allowed-origins: http://localhost:8080 From 4675795da3fe82e347bf6cd5832dcfc9af49634c Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Mon, 29 Jul 2024 19:27:20 +0900 Subject: [PATCH 104/273] =?UTF-8?q?fix:=20gradlew=20=EA=B6=8C=ED=95=9C=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20(#152)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-pull-request.yml | 3 +++ .github/workflows/backend-push.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml index 113972929..6ede1b600 100644 --- a/.github/workflows/backend-pull-request.yml +++ b/.github/workflows/backend-pull-request.yml @@ -27,6 +27,9 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Test with Gradle Wrapper run: ./gradlew clean build diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml index d385a69c8..c9c2316c8 100644 --- a/.github/workflows/backend-push.yml +++ b/.github/workflows/backend-push.yml @@ -34,6 +34,9 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Test with Gradle Wrapper run: ./gradlew clean build From 36c6f60e23009075aeca552efe4284f2fe1b01b6 Mon Sep 17 00:00:00 2001 From: 3juhwan <13selfesteem91@naver.com> Date: Tue, 30 Jul 2024 10:27:12 +0900 Subject: [PATCH 105/273] =?UTF-8?q?remove:=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-pull-request.yml | 46 ---- .github/workflows/backend-push.yml | 74 ------ .gitmodules | 3 - server/.gitignore | 244 ----------------- server/Dockerfile | 9 - server/build.gradle | 40 --- server/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - server/gradlew | 249 ------------------ server/gradlew.bat | 92 ------- server/settings.gradle | 1 - .../haengdong/HaengdongApplication.java | 13 - .../haengdong/application/ActionService.java | 37 --- .../application/BillActionService.java | 44 ---- .../haengdong/application/EventService.java | 91 ------- .../application/MemberActionFactory.java | 82 ------ .../application/MemberActionService.java | 60 ----- .../request/BillActionAppRequest.java | 14 - .../application/request/EventAppRequest.java | 10 - .../request/MemberActionSaveAppRequest.java | 12 - .../request/MemberActionsSaveAppRequest.java | 6 - .../response/ActionAppResponse.java | 54 ---- .../response/CurrentMemberAppResponse.java | 10 - .../response/EventAppResponse.java | 10 - .../response/EventDetailAppResponse.java | 10 - .../response/MemberBillReportAppResponse.java | 4 - .../server/haengdong/config/WebConfig.java | 27 -- .../haengdong/domain/action/Action.java | 42 --- .../domain/action/ActionRepository.java | 21 -- .../haengdong/domain/action/BillAction.java | 70 ----- .../domain/action/BillActionRepository.java | 14 - .../domain/action/CurrentMembers.java | 66 ----- .../haengdong/domain/action/MemberAction.java | 62 ----- .../domain/action/MemberActionRepository.java | 15 -- .../domain/action/MemberActionStatus.java | 19 -- .../domain/action/MemberBillReport.java | 75 ------ .../domain/action/MemberGroupIdProvider.java | 11 - .../server/haengdong/domain/event/Event.java | 54 ---- .../domain/event/EventRepository.java | 11 - .../haengdong/domain/event/EventStep.java | 28 -- .../domain/event/EventTokenProvider.java | 12 - .../haengdong/exception/ErrorResponse.java | 10 - .../exception/GlobalExceptionHandler.java | 43 --- .../exception/HaengdongErrorCode.java | 24 -- .../exception/HaengdongException.java | 32 --- .../presentation/ActionController.java | 26 -- .../presentation/BillActionController.java | 29 -- .../presentation/EventController.java | 43 --- .../presentation/MemberActionController.java | 39 --- .../request/BillActionSaveRequest.java | 19 -- .../request/BillActionsSaveRequest.java | 14 - .../request/EventSaveRequest.java | 15 -- .../request/MemberActionsSaveRequest.java | 22 -- .../presentation/response/ActionResponse.java | 20 -- .../response/ActionsResponse.java | 28 -- .../response/CurrentMemberResponse.java | 10 - .../response/CurrentMembersResponse.java | 15 -- .../response/EventDetailResponse.java | 10 - .../presentation/response/EventResponse.java | 10 - .../response/MemberBillReportResponse.java | 10 - .../response/MemberBillReportsResponse.java | 15 -- .../presentation/response/StepResponse.java | 57 ---- server/src/main/resources/application.yml | 31 --- .../application/ActionServiceTest.java | 79 ------ .../application/BillActionServiceTest.java | 65 ----- .../application/EventServiceTest.java | 110 -------- .../application/MemberActionFactoryTest.java | 217 --------------- .../application/MemberActionServiceTest.java | 92 ------- .../haengdong/domain/action/ActionTest.java | 30 --- .../domain/action/BillActionTest.java | 58 ---- .../domain/action/CurrentMembersTest.java | 58 ---- .../domain/action/MemberBillReportTest.java | 43 --- .../haengdong/domain/event/EventTest.java | 37 --- .../presentation/ActionControllerTest.java | 49 ---- .../BillActionControllerTest.java | 69 ----- .../presentation/EventControllerTest.java | 66 ----- .../MemberActionControllerTest.java | 67 ----- .../response/StepResponseTest.java | 57 ---- server/src/test/resources/application.yml | 18 -- 79 files changed, 3386 deletions(-) delete mode 100644 .github/workflows/backend-pull-request.yml delete mode 100644 .github/workflows/backend-push.yml delete mode 100644 .gitmodules delete mode 100644 server/.gitignore delete mode 100644 server/Dockerfile delete mode 100644 server/build.gradle delete mode 100644 server/gradle/wrapper/gradle-wrapper.jar delete mode 100644 server/gradle/wrapper/gradle-wrapper.properties delete mode 100644 server/gradlew delete mode 100644 server/gradlew.bat delete mode 100644 server/settings.gradle delete mode 100644 server/src/main/java/server/haengdong/HaengdongApplication.java delete mode 100644 server/src/main/java/server/haengdong/application/ActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/BillActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/EventService.java delete mode 100644 server/src/main/java/server/haengdong/application/MemberActionFactory.java delete mode 100644 server/src/main/java/server/haengdong/application/MemberActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/EventAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/response/ActionAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/EventAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/config/WebConfig.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/Action.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/ActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillAction.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/CurrentMembers.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberAction.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberBillReport.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/Event.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventStep.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java delete mode 100644 server/src/main/java/server/haengdong/exception/ErrorResponse.java delete mode 100644 server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java delete mode 100644 server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java delete mode 100644 server/src/main/java/server/haengdong/exception/HaengdongException.java delete mode 100644 server/src/main/java/server/haengdong/presentation/ActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/BillActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/EventController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/MemberActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/EventResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/StepResponse.java delete mode 100644 server/src/main/resources/application.yml delete mode 100644 server/src/test/java/server/haengdong/application/ActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/BillActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/EventServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java delete mode 100644 server/src/test/java/server/haengdong/application/MemberActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/ActionTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/BillActionTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/event/EventTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/ActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/EventControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java delete mode 100644 server/src/test/resources/application.yml diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml deleted file mode 100644 index 6ede1b600..000000000 --- a/.github/workflows/backend-pull-request.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: backend-pull-request - -on: - pull_request: - branches: [ "main", "develop" ] - paths: - - 'server/**' - -jobs: - build: - runs-on: ubuntu-latest - - defaults: - run: - working-directory: ./server - - steps: - - name: CheckOut - uses: actions/checkout@v4 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Test with Gradle Wrapper - run: ./gradlew clean build - - - name: publish unit test results - uses: EnricoMi/publish-unit-test-result-action@v2 - if: always() - with: - files: server/build/test-results/test/TEST-*.xml - - - name: add comments to a pull request - uses: mikepenz/action-junit-report@v3 - if: always() - with: - report_paths: server/build/test-results/test/TEST-*.xml diff --git a/.github/workflows/backend-push.yml b/.github/workflows/backend-push.yml deleted file mode 100644 index c9c2316c8..000000000 --- a/.github/workflows/backend-push.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: backend-push - -on: - push: - branches: [ "main", "develop" ] - paths: - - 'server/**' - -jobs: - build: - runs-on: ubuntu-latest - - defaults: - run: - shell: bash - working-directory: ./server - - permissions: - contents: read - - steps: - - name: CheckOut - uses: actions/checkout@v4 - with: - token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} - submodules: true - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Test with Gradle Wrapper - run: ./gradlew clean build - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Set up Docker BuildX - uses: docker/setup-buildx-action@v3 - - - name: Build and push - run: | - docker buildx build --platform linux/arm64 -t \ - ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev --push . - - deploy: - needs: build - runs-on: self-hosted - steps: - - name: Docker remove - run: | - CONTAINER_IDS=$(sudo docker ps -qa) - if [ -n "$CONTAINER_IDS" ]; then - sudo docker rm -f $CONTAINER_IDS - else - echo "No running containers found." - fi - - - name: Docker Image pull - run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev - - - name: Docker run - run: sudo docker run -d -p 8080:8080 --name haengdong-backend-dev ${{ secrets.DOCKER_USERNAME }}/haengdong-backend-dev diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index a067fc391..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "server/src/main/resources/config"] - path = server/src/main/resources/config - url = https://github.com/woowacourse-teams/2024-haeng-dong-config.git diff --git a/server/.gitignore b/server/.gitignore deleted file mode 100644 index 671ee930b..000000000 --- a/server/.gitignore +++ /dev/null @@ -1,244 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux -# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij,gradle,macos,windows,linux - -### Intellij ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Intellij Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -# https://plugins.jetbrains.com/plugin/7973-sonarlint -.idea/**/sonarlint/ - -# SonarQube Plugin -# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin -.idea/**/sonarIssues.xml - -# Markdown Navigator plugin -# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced -.idea/**/markdown-navigator.xml -.idea/**/markdown-navigator-enh.xml -.idea/**/markdown-navigator/ - -# Cache file creation bug -# See https://youtrack.jetbrains.com/issue/JBR-2257 -.idea/$CACHE_FILE$ - -# CodeStream plugin -# https://plugins.jetbrains.com/plugin/12206-codestream -.idea/codestream.xml - -# Azure Toolkit for IntelliJ plugin -# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij -.idea/**/azureSettings.xml - -### Java ### -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* - -### Linux ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### macOS Patch ### -# iCloud generated files -*.icloud - -### Windows ### -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -### Gradle ### -.gradle -**/build/ -!src/**/build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Avoid ignore Gradle wrappper properties -!gradle-wrapper.properties - -# Cache of project -.gradletasknamecache - -# Eclipse Gradle plugin generated files -# Eclipse Core -.project -# JDT-specific (Eclipse Java Development Tools) -.classpath - -### Gradle Patch ### -# Java heap dump -*.hprof - -# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux diff --git a/server/Dockerfile b/server/Dockerfile deleted file mode 100644 index 37e37d237..000000000 --- a/server/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM openjdk:17-jdk-slim - -WORKDIR /app - -COPY /build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar - -EXPOSE 8080 -ENTRYPOINT ["java"] -CMD ["-Dspring.profiles.active=dev", "-jar", "haengdong-0.0.1-SNAPSHOT.jar"] diff --git a/server/build.gradle b/server/build.gradle deleted file mode 100644 index 26f6ec262..000000000 --- a/server/build.gradle +++ /dev/null @@ -1,40 +0,0 @@ -plugins { - id 'java' - id 'org.springframework.boot' version '3.3.1' - id 'io.spring.dependency-management' version '1.1.5' -} - -group = 'server' -version = '0.0.1-SNAPSHOT' - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -configurations { - compileOnly { - extendsFrom annotationProcessor - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-validation' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.mysql:mysql-connector-j' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' -} - -tasks.named('test') { - useJUnitPlatform() -} diff --git a/server/gradle/wrapper/gradle-wrapper.jar b/server/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3d4ba8a0da8d277868979cfbc8ad796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 UfUyy3EX0IC28@JalTrWuAK7&_a{vGU diff --git a/server/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a4413138c..000000000 --- a/server/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/server/gradlew b/server/gradlew deleted file mode 100644 index b740cf133..000000000 --- a/server/gradlew +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/server/gradlew.bat b/server/gradlew.bat deleted file mode 100644 index 25da30dbd..000000000 --- a/server/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/server/settings.gradle b/server/settings.gradle deleted file mode 100644 index dbbee46fb..000000000 --- a/server/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'haengdong' diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java deleted file mode 100644 index 31b6e46e7..000000000 --- a/server/src/main/java/server/haengdong/HaengdongApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package server.haengdong; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class HaengdongApplication { - - public static void main(String[] args) { - SpringApplication.run(HaengdongApplication.class, args); - } - -} diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java deleted file mode 100644 index bda638756..000000000 --- a/server/src/main/java/server/haengdong/application/ActionService.java +++ /dev/null @@ -1,37 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberBillReport; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Service -public class ActionService { - - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - private final EventRepository eventRepository; - - public List<MemberBillReportAppResponse> getMemberBillReports(String token) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - List<BillAction> billActions = billActionRepository.findByAction_Event(event); - List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); - - MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - - return memberBillReport.getReports().entrySet().stream() - .map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue())) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java deleted file mode 100644 index 257d33a3e..000000000 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ /dev/null @@ -1,44 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class BillActionService { - - private final BillActionRepository billActionRepository; - private final ActionRepository actionRepository; - private final EventRepository eventRepository; - - @Transactional - public void saveAllBillAction(String eventToken, List<BillActionAppRequest> requests) { - Event event = eventRepository.findByToken(eventToken) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - Action action = createStartAction(event); - - for (BillActionAppRequest request : requests) { - BillAction billAction = request.toBillAction(action); - billActionRepository.save(billAction); - action = action.next(); - } - } - - private Action createStartAction(Event event) { - return actionRepository.findLastByEvent(event) - .map(Action::next) - .orElse(Action.createFirst(event)); - } -} diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java deleted file mode 100644 index 9ad502606..000000000 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ /dev/null @@ -1,91 +0,0 @@ -package server.haengdong.application; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.event.EventTokenProvider; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class EventService { - - private final EventRepository eventRepository; - private final EventTokenProvider eventTokenProvider; - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - - @Transactional - public EventAppResponse saveEvent(EventAppRequest request) { - String token = eventTokenProvider.createToken(); - Event event = request.toEvent(token); - eventRepository.save(event); - - return EventAppResponse.of(event); - } - - public EventDetailAppResponse findEvent(String token) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - - return EventDetailAppResponse.of(event); - } - - public List<ActionAppResponse> findActions(String token) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - - List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() - .sorted(Comparator.comparing(BillAction::getSequence)).toList(); - List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event).stream() - .sorted(Comparator.comparing(MemberAction::getSequence)).toList(); - - return getActionAppResponses(billActions, memberActions); - } - - private List<ActionAppResponse> getActionAppResponses( - List<BillAction> billActions, - List<MemberAction> memberActions - ) { - int billActionIndex = 0; - int memberActionIndex = 0; - List<ActionAppResponse> actionAppResponses = new ArrayList<>(); - - while (billActionIndex < billActions.size() && memberActionIndex < memberActions.size()) { - BillAction billAction = billActions.get(billActionIndex); - MemberAction memberAction = memberActions.get(memberActionIndex); - if (billAction.getSequence() < memberAction.getSequence()) { - actionAppResponses.add(ActionAppResponse.of(billAction)); - billActionIndex++; - } else { - actionAppResponses.add(ActionAppResponse.of(memberAction)); - memberActionIndex++; - } - } - while (billActionIndex < billActions.size()) { - BillAction billAction = billActions.get(billActionIndex++); - actionAppResponses.add(ActionAppResponse.of(billAction)); - } - while (memberActionIndex < memberActions.size()) { - MemberAction memberAction = memberActions.get(memberActionIndex++); - actionAppResponses.add(ActionAppResponse.of(memberAction)); - } - - return actionAppResponses; - } -} diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java deleted file mode 100644 index cbe34f0ef..000000000 --- a/server/src/main/java/server/haengdong/application/MemberActionFactory.java +++ /dev/null @@ -1,82 +0,0 @@ -package server.haengdong.application; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.action.MemberGroupIdProvider; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Component -public class MemberActionFactory { - - private final MemberGroupIdProvider memberGroupIdProvider; - - public List<MemberAction> createMemberActions( - MemberActionsSaveAppRequest request, - List<MemberAction> memberActions, - Action action - ) { - validateMemberNames(request); - validateActions(request, memberActions); - - Long memberGroupId = memberGroupIdProvider.createGroupId(); - List<MemberAction> createdMemberActions = new ArrayList<>(); - List<MemberActionSaveAppRequest> actions = request.actions(); - for (MemberActionSaveAppRequest appRequest : actions) { - MemberAction memberAction = appRequest.toMemberAction(action, memberGroupId); - createdMemberActions.add(memberAction); - action = action.next(); - } - - return createdMemberActions; - } - - private void validateMemberNames(MemberActionsSaveAppRequest request) { - List<String> memberNames = request.actions().stream() - .map(MemberActionSaveAppRequest::name) - .toList(); - - long uniqueCount = memberNames.stream().distinct().count(); - if (uniqueCount != memberNames.size()) { - throw new HaengdongException(HaengdongErrorCode.DUPLICATED_MEMBER_ACTION); - } - } - - private void validateActions(MemberActionsSaveAppRequest request, List<MemberAction> memberActions) { - List<MemberAction> reverseSortedMemberActions = memberActions.stream() - .sorted(Comparator.comparing(MemberAction::getSequence).reversed()) - .toList(); - - for (MemberActionSaveAppRequest action : request.actions()) { - validateAction(action, reverseSortedMemberActions); - } - } - - private void validateAction(MemberActionSaveAppRequest request, List<MemberAction> memberActions) { - MemberActionStatus memberActionStatus = MemberActionStatus.of(request.status()); - if (isInvalidStatus(memberActions, request.name(), memberActionStatus)) { - throw new HaengdongException(HaengdongErrorCode.INVALID_MEMBER_ACTION); - } - } - - private boolean isInvalidStatus( - List<MemberAction> memberActions, - String memberName, - MemberActionStatus memberActionStatus - ) { - return memberActions.stream() - .filter(action -> action.isSameName(memberName)) - .findFirst() - .map(action -> action.isSameStatus(memberActionStatus)) - .orElse(MemberActionStatus.IN != memberActionStatus); - } -} diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java deleted file mode 100644 index 5094bf2c0..000000000 --- a/server/src/main/java/server/haengdong/application/MemberActionService.java +++ /dev/null @@ -1,60 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class MemberActionService { - - private final MemberActionFactory memberActionFactory; - private final MemberActionRepository memberActionRepository; - private final EventRepository eventRepository; - private final ActionRepository actionRepository; - - @Transactional - public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { - Event event = findEvent(token); - - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - Action action = createStartAction(event); - List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, findMemberActions, action); - memberActionRepository.saveAll(memberActions); - } - - private Action createStartAction(Event event) { - return actionRepository.findLastByEvent(event) - .map(Action::next) - .orElse(Action.createFirst(event)); - } - - public List<CurrentMemberAppResponse> getCurrentMembers(String token) { - Event event = findEvent(token); - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); - - return currentMembers.getMembers() - .stream() - .map(CurrentMemberAppResponse::new) - .toList(); - } - - private Event findEvent(String token) { - return eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT)); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java deleted file mode 100644 index acd0149f9..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; - -public record BillActionAppRequest( - String title, - Long price -) { - - public BillAction toBillAction(Action action) { - return new BillAction(action, title, price); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java deleted file mode 100644 index 1eea6adf4..000000000 --- a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.event.Event; - -public record EventAppRequest(String name) { - - public Event toEvent(String token) { - return new Event(name, token); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java deleted file mode 100644 index f7f8d8fc2..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; - -public record MemberActionSaveAppRequest(String name, String status) { - - public MemberAction toMemberAction(Action action, Long memberGroupId) { - return new MemberAction(action, name, MemberActionStatus.of(status), memberGroupId); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java deleted file mode 100644 index 650b908df..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package server.haengdong.application.request; - -import java.util.List; - -public record MemberActionsSaveAppRequest(List<MemberActionSaveAppRequest> actions) { -} diff --git a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java deleted file mode 100644 index a1abcc35b..000000000 --- a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java +++ /dev/null @@ -1,54 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; - -public record ActionAppResponse( - Long actionId, - String name, - Long price, - Long sequence, - ActionType actionType -) { - - public static ActionAppResponse of(BillAction billAction) { - return new ActionAppResponse( - billAction.getAction().getId(), - billAction.getTitle(), - billAction.getPrice(), - billAction.getSequence(), - ActionType.BILL - ); - } - - public static ActionAppResponse of(MemberAction memberAction) { - MemberActionStatus status = memberAction.getStatus(); - - return new ActionAppResponse( - memberAction.getAction().getId(), - memberAction.getMemberName(), - null, - memberAction.getSequence(), - ActionType.of(status) - ); - } - - public String actionTypeName() { - return actionType.name(); - } - - public enum ActionType { - BILL, - IN, - OUT, - ; - - private static ActionType of(MemberActionStatus memberActionStatus) { - if (MemberActionStatus.IN == memberActionStatus) { - return IN; - } - return OUT; - } - } -} diff --git a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java deleted file mode 100644 index 6c682d3e9..000000000 --- a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.MemberAction; - -public record CurrentMemberAppResponse(String name) { - - public static CurrentMemberAppResponse of(MemberAction memberAction) { - return new CurrentMemberAppResponse(memberAction.getMemberName()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java deleted file mode 100644 index f331d0011..000000000 --- a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.event.Event; - -public record EventAppResponse(String token) { - - public static EventAppResponse of(Event event) { - return new EventAppResponse(event.getToken()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java deleted file mode 100644 index 6e38826d4..000000000 --- a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.event.Event; - -public record EventDetailAppResponse(String eventName) { - - public static EventDetailAppResponse of(Event event) { - return new EventDetailAppResponse(event.getName()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java deleted file mode 100644 index 21b6cef56..000000000 --- a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package server.haengdong.application.response; - -public record MemberBillReportAppResponse(String name, Long price) { -} diff --git a/server/src/main/java/server/haengdong/config/WebConfig.java b/server/src/main/java/server/haengdong/config/WebConfig.java deleted file mode 100644 index 129d8b790..000000000 --- a/server/src/main/java/server/haengdong/config/WebConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -package server.haengdong.config; - -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -@RequiredArgsConstructor -@Configuration -public class WebConfig implements WebMvcConfigurer { - - @Value("${cors.max-age}") - private Long maxAge; - - @Value("${cors.allowed-origins}") - private String[] allowedOrigins; - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins(allowedOrigins) - .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") - .allowedHeaders("*") - .maxAge(maxAge); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/Action.java b/server/src/main/java/server/haengdong/domain/action/Action.java deleted file mode 100644 index 11f91fc38..000000000 --- a/server/src/main/java/server/haengdong/domain/action/Action.java +++ /dev/null @@ -1,42 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.domain.event.Event; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Action { - - private static final long FIRST_SEQUENCE = 1L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Event event; - - private Long sequence; - - public Action(Event event, Long sequence) { - this.event = event; - this.sequence = sequence; - } - - public static Action createFirst(Event event) { - return new Action(event, FIRST_SEQUENCE); - } - - public Action next() { - return new Action(event, sequence + 1); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java deleted file mode 100644 index c2138e42f..000000000 --- a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java +++ /dev/null @@ -1,21 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface ActionRepository extends JpaRepository<Action, Long> { - - @Query(""" - SELECT a - FROM Action a - WHERE a.event = :event - ORDER BY a.sequence DESC - LIMIT 1 - """) - Optional<Action> findLastByEvent(@Param("event") Event event); -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java deleted file mode 100644 index 1027206f5..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillAction.java +++ /dev/null @@ -1,70 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class BillAction implements Comparable<BillAction> { - - private static final int MIN_TITLE_LENGTH = 2; - private static final int MAX_TITLE_LENGTH = 30; - private static final long MIN_PRICE = 1L; - private static final long MAX_PRICE = 10_000_000L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - private Action action; - - @Column(length = MAX_TITLE_LENGTH) - private String title; - - private Long price; - - public BillAction(Action action, String title, Long price) { - validateTitle(title); - validatePrice(price); - this.action = action; - this.title = title.trim(); - this.price = price; - } - - private void validateTitle(String title) { - int titleLength = title.trim().length(); - if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { - throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", MIN_TITLE_LENGTH, MAX_TITLE_LENGTH)); - } - } - - private void validatePrice(Long price) { - if (price < MIN_PRICE || price > MAX_PRICE) { - throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", MAX_PRICE)); - } - } - - public Long getSequence() { - return action.getSequence(); - } - - @Override - public int compareTo(BillAction o) { - return Long.compare(this.getSequence(), o.getSequence()); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java deleted file mode 100644 index 1ad7416aa..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface BillActionRepository extends JpaRepository<BillAction, Long> { - - @EntityGraph(attributePaths = {"action"}) - List<BillAction> findByAction_Event(Event event); -} diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java deleted file mode 100644 index 298a8a965..000000000 --- a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java +++ /dev/null @@ -1,66 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class CurrentMembers { - - private final Set<String> members; - - public CurrentMembers() { - this(new HashSet<>()); - } - - private CurrentMembers(Set<String> members) { - this.members = members; - } - - public static CurrentMembers of(List<MemberAction> memberActions) { - List<MemberAction> sortedMemberActions = getSortedMemberActions(memberActions); - Set<String> members = new HashSet<>(); - for (MemberAction memberAction : sortedMemberActions) { - String member = memberAction.getMemberName(); - if (memberAction.isSameStatus(MemberActionStatus.IN)) { - members.add(member); - continue; - } - members.remove(member); - } - - return new CurrentMembers(members); - } - - private static List<MemberAction> getSortedMemberActions(List<MemberAction> memberActions) { - return memberActions.stream() - .sorted(Comparator.comparing(MemberAction::getSequence)) - .toList(); - } - - public CurrentMembers addMemberAction(MemberAction memberAction) { - String memberName = memberAction.getMemberName(); - - Set<String> currentMembers = new HashSet<>(members); - - if (memberAction.isIn()) { - currentMembers.add(memberName); - } else { - currentMembers.remove(memberName); - } - return new CurrentMembers(currentMembers); - } - - public boolean isEmpty() { - return members.isEmpty(); - } - - public int size() { - return members.size(); - } - - public Set<String> getMembers() { - return Collections.unmodifiableSet(members); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java deleted file mode 100644 index 67387cbde..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberAction.java +++ /dev/null @@ -1,62 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class MemberAction implements Comparable<MemberAction> { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - private Action action; - - private String memberName; - - @Enumerated(EnumType.STRING) - private MemberActionStatus status; - - private Long memberGroupId; - - public MemberAction(Action action, String memberName, MemberActionStatus status, Long memberGroupId) { - this.action = action; - this.memberName = memberName; - this.status = status; - this.memberGroupId = memberGroupId; - } - - public boolean isSameName(String name) { - return memberName.equals(name); - } - - public boolean isIn() { - return status == MemberActionStatus.IN; - } - - public boolean isSameStatus(MemberActionStatus memberActionStatus) { - return status == memberActionStatus; - } - - public Long getSequence() { - return action.getSequence(); - } - - @Override - public int compareTo(MemberAction o) { - return Long.compare(this.getSequence(), o.getSequence()); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java deleted file mode 100644 index 6c4769e61..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface MemberActionRepository extends JpaRepository<MemberAction, Long> { - - @Query("select m from MemberAction m join fetch m.action where m.action.event = :event") - List<MemberAction> findAllByEvent(@Param("event") Event event); -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java deleted file mode 100644 index 0a20817fd..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Arrays; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -public enum MemberActionStatus { - IN, - OUT, - ; - - public static MemberActionStatus of(String status) { - return Arrays.stream(MemberActionStatus.values()) - .filter(s -> s.name().equals(status)) - .findFirst() - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - "존재하지 않는 인원 변동 액션입니다.")); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java deleted file mode 100644 index dbf2b49ac..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java +++ /dev/null @@ -1,75 +0,0 @@ -package server.haengdong.domain.action; - -import static java.util.stream.Collectors.toMap; - -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.function.Function; -import lombok.Getter; - -@Getter -public class MemberBillReport { - - private final Map<String, Long> reports; - - private MemberBillReport(Map<String, Long> reports) { - this.reports = reports; - } - - public static MemberBillReport createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { - PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); - PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); - - Map<String, Long> memberBillReports = initReports(memberActions); - CurrentMembers currentMembers = new CurrentMembers(); - while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { - if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { - MemberAction memberAction = sortedMemberActions.poll(); - currentMembers = currentMembers.addMemberAction(memberAction); - continue; - } - addBillAction(sortedBillActions, currentMembers, memberBillReports); - } - - while (!sortedBillActions.isEmpty()) { - addBillAction(sortedBillActions, currentMembers, memberBillReports); - } - - return new MemberBillReport(memberBillReports); - } - - private static Map<String, Long> initReports(List<MemberAction> memberActions) { - return memberActions.stream() - .map(MemberAction::getMemberName) - .distinct() - .collect(toMap(Function.identity(), i -> 0L)); - } - - private static boolean isMemberActionTurn( - PriorityQueue<MemberAction> memberActions, - PriorityQueue<BillAction> billActions - ) { - MemberAction memberAction = memberActions.peek(); - BillAction billAction = billActions.peek(); - - return memberAction.getSequence() < billAction.getSequence(); - } - - private static void addBillAction( - PriorityQueue<BillAction> sortedBillActions, - CurrentMembers currentMembers, - Map<String, Long> memberBillReports - ) { - BillAction billAction = sortedBillActions.poll(); - if (currentMembers.isEmpty()) { - return; - } - - Long pricePerMember = billAction.getPrice() / currentMembers.size(); - for (String currentMember : currentMembers.getMembers()) { - Long price = memberBillReports.get(currentMember) + pricePerMember; - memberBillReports.put(currentMember, price); - } - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java deleted file mode 100644 index 9e32bd733..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.domain.action; - -import org.springframework.stereotype.Component; - -@Component -public class MemberGroupIdProvider { - - public Long createGroupId() { - return System.currentTimeMillis(); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java deleted file mode 100644 index 24369a184..000000000 --- a/server/src/main/java/server/haengdong/domain/event/Event.java +++ /dev/null @@ -1,54 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Event { - - private static final int MIN_NAME_LENGTH = 2; - private static final int MAX_NAME_LENGTH = 20; - private static final String SPACES = " "; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String name; - - private String token; - - public Event(String name, String token) { - validateName(name); - this.name = name; - this.token = token; - } - - private void validateName(String name) { - int nameLength = name.length(); - if (nameLength < MIN_NAME_LENGTH || MAX_NAME_LENGTH < nameLength) { - throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", - MIN_NAME_LENGTH, - MAX_NAME_LENGTH, - name.length())); - } - if (isBlankContinuous(name)) { - throw new HaengdongException(HaengdongErrorCode.BAD_REQUEST, - String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", name)); - } - } - - private boolean isBlankContinuous(String name) { - return name.contains(SPACES); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java deleted file mode 100644 index 6038c368b..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.domain.event; - -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface EventRepository extends JpaRepository<Event, Long> { - - Optional<Event> findByToken(String token); -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventStep.java b/server/src/main/java/server/haengdong/domain/event/EventStep.java deleted file mode 100644 index 297abdb66..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventStep.java +++ /dev/null @@ -1,28 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class EventStep { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Event event; - - private String name; - - private Long sequence; -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java deleted file mode 100644 index 6450f0dcf..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.domain.event; - -import java.util.UUID; -import org.springframework.stereotype.Component; - -@Component -public class EventTokenProvider { - - public String createToken() { - return UUID.randomUUID().toString(); - } -} diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java deleted file mode 100644 index c797b811a..000000000 --- a/server/src/main/java/server/haengdong/exception/ErrorResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.exception; - -public record ErrorResponse( - String message -) { - - public static ErrorResponse of(String message) { - return new ErrorResponse(message); - } -} diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java deleted file mode 100644 index bb3138cc7..000000000 --- a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java +++ /dev/null @@ -1,43 +0,0 @@ -package server.haengdong.exception; - -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -@Slf4j -@RestControllerAdvice -public class GlobalExceptionHandler { - - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public ResponseEntity<ErrorResponse> haengdongException() { - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.BAD_REQUEST.getMessage())); - } - - @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - String errorMessage = e.getFieldErrors().stream() - .map(error -> error.getField() + " " + error.getDefaultMessage()) - .collect(Collectors.joining(", ")); - - return ResponseEntity.badRequest() - .body(ErrorResponse.of(errorMessage)); - } - - @ExceptionHandler(HaengdongException.class) - public ResponseEntity<ErrorResponse> haengdongException(HaengdongException e) { - return ResponseEntity.status(e.getStatusCode()) - .body(ErrorResponse.of(e.getMessage())); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity<ErrorResponse> handleException(Exception e) { - log.error(e.getMessage(), e); - return ResponseEntity.internalServerError() - .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR.getMessage())); - } -} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java deleted file mode 100644 index 792baa838..000000000 --- a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java +++ /dev/null @@ -1,24 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; -import org.springframework.http.HttpStatus; - -@Getter -public enum HaengdongErrorCode { - BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 요청입니다."), - DUPLICATED_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "올바르지 않은 인원 요청입니다."), - INVALID_MEMBER_ACTION(HttpStatus.BAD_REQUEST, "잘못된 맴버 액션입니다."), - - NOT_FOUND_EVENT(HttpStatus.NOT_FOUND, "존재하지 않는 행사입니다."), - - INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 내부에서 에러가 발생했습니다."), - ; - - private final HttpStatus httpStatus; - private final String message; - - HaengdongErrorCode(HttpStatus httpStatus, String message) { - this.httpStatus = httpStatus; - this.message = message; - } -} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongException.java b/server/src/main/java/server/haengdong/exception/HaengdongException.java deleted file mode 100644 index 812df50f8..000000000 --- a/server/src/main/java/server/haengdong/exception/HaengdongException.java +++ /dev/null @@ -1,32 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; -import org.springframework.http.HttpStatusCode; - -@Getter -public class HaengdongException extends RuntimeException { - - private final HaengdongErrorCode errorCode; - private final String message; - - public HaengdongException(HaengdongErrorCode errorCode) { - this(errorCode, null); - } - - public HaengdongException(HaengdongErrorCode errorCode, String message) { - this.errorCode = errorCode; - this.message = message; - } - - public HttpStatusCode getStatusCode() { - return errorCode.getHttpStatus(); - } - - @Override - public String getMessage() { - if (message == null) { - return errorCode.getMessage(); - } - return message; - } -} diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java deleted file mode 100644 index 657cb567e..000000000 --- a/server/src/main/java/server/haengdong/presentation/ActionController.java +++ /dev/null @@ -1,26 +0,0 @@ -package server.haengdong.presentation; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.ActionService; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.presentation.response.MemberBillReportsResponse; - -@RequiredArgsConstructor -@RestController -public class ActionController { - - private final ActionService actionService; - - @GetMapping("/api/events/{eventId}/actions/reports") - public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("eventId") String token) { - List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); - - return ResponseEntity.ok() - .body(MemberBillReportsResponse.of(memberBillReports)); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java deleted file mode 100644 index fcdacb270..000000000 --- a/server/src/main/java/server/haengdong/presentation/BillActionController.java +++ /dev/null @@ -1,29 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.BillActionService; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -@RequiredArgsConstructor -@RestController -public class BillActionController { - - private final BillActionService billActionService; - - @PostMapping("/api/events/{eventId}/actions/bills") - public ResponseEntity<Void> saveAllBillAction( - @PathVariable("eventId") String token, - @RequestBody @Valid BillActionsSaveRequest request - ) { - billActionService.saveAllBillAction(token, request.toAppRequests()); - - return ResponseEntity.ok() - .build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java deleted file mode 100644 index 9fbe098ce..000000000 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ /dev/null @@ -1,43 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.EventService; -import server.haengdong.presentation.request.EventSaveRequest; -import server.haengdong.presentation.response.EventDetailResponse; -import server.haengdong.presentation.response.EventResponse; -import server.haengdong.presentation.response.StepResponse; - -@RequiredArgsConstructor -@RestController -public class EventController { - - private final EventService eventService; - - @PostMapping("/api/events") - public ResponseEntity<EventResponse> saveEvent(@Valid @RequestBody EventSaveRequest request) { - EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); - - return ResponseEntity.ok(eventResponse); - } - - @GetMapping("/api/events/{eventId}") - public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") String token) { - EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); - - return ResponseEntity.ok(eventDetailResponse); - } - - @GetMapping("/api/events/{eventId}/actions") - public ResponseEntity<StepResponse> findActions(@PathVariable("eventId") String token) { - StepResponse stepResponse = StepResponse.of(eventService.findActions(token)); - - return ResponseEntity.ok(stepResponse); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java deleted file mode 100644 index c12370d86..000000000 --- a/server/src/main/java/server/haengdong/presentation/MemberActionController.java +++ /dev/null @@ -1,39 +0,0 @@ -package server.haengdong.presentation; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.MemberActionService; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionsSaveRequest; -import server.haengdong.presentation.response.CurrentMembersResponse; - -@RequiredArgsConstructor -@RestController -public class MemberActionController { - - private final MemberActionService memberActionService; - - @PostMapping("/api/events/{eventId}/actions/members") - public ResponseEntity<Void> saveMemberAction( - @PathVariable("eventId") String token, - @RequestBody MemberActionsSaveRequest request - ) { - memberActionService.saveMemberAction(token, request.toAppRequest()); - - return ResponseEntity.ok().build(); - } - - @GetMapping("/api/events/{eventId}/members/current") - public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("eventId") String token) { - List<CurrentMemberAppResponse> currentMembers = memberActionService.getCurrentMembers(token); - - return ResponseEntity.ok() - .body(CurrentMembersResponse.of(currentMembers)); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java deleted file mode 100644 index a0d878f7f..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import server.haengdong.application.request.BillActionAppRequest; - -public record BillActionSaveRequest( - - @NotBlank - String title, - - @NotNull - Long price -) { - - public BillActionAppRequest toAppRequest() { - return new BillActionAppRequest(title, price); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java deleted file mode 100644 index 68784039b..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.Valid; -import java.util.List; -import server.haengdong.application.request.BillActionAppRequest; - -public record BillActionsSaveRequest(@Valid List<BillActionSaveRequest> actions) { - - public List<BillActionAppRequest> toAppRequests() { - return actions.stream() - .map(BillActionSaveRequest::toAppRequest) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java deleted file mode 100644 index b28572332..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import server.haengdong.application.request.EventAppRequest; - -public record EventSaveRequest( - - @NotBlank - String eventName -) { - - public EventAppRequest toAppRequest() { - return new EventAppRequest(eventName); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java deleted file mode 100644 index 0b3fcebae..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java +++ /dev/null @@ -1,22 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import java.util.List; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; - -public record MemberActionsSaveRequest( - List<String> members, - - @NotBlank - String status -) { - - public MemberActionsSaveAppRequest toAppRequest() { - List<MemberActionSaveAppRequest> appRequests = members.stream() - .map(name -> new MemberActionSaveAppRequest(name, status)) - .toList(); - - return new MemberActionsSaveAppRequest(appRequests); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java deleted file mode 100644 index a58e60186..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java +++ /dev/null @@ -1,20 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.ActionAppResponse; - -public record ActionResponse( - Long actionId, - String name, - Long price, - Long sequence -) { - - public static ActionResponse of(ActionAppResponse actionAppResponse) { - return new ActionResponse( - actionAppResponse.actionId(), - actionAppResponse.name(), - actionAppResponse.price(), - actionAppResponse.sequence() - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java deleted file mode 100644 index 188c48dc9..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java +++ /dev/null @@ -1,28 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import server.haengdong.application.response.ActionAppResponse; - -public record ActionsResponse( - String type, - String stepName, - Set<String> members, - List<ActionResponse> actions -) { - - public static ActionsResponse of(List<ActionAppResponse> actions, Set<String> members) { - List<ActionResponse> actionResponses = actions.stream() - .map(ActionResponse::of) - .toList(); - - String actionType = actions.get(0).actionTypeName(); - return new ActionsResponse( - actionType, - null, - new HashSet<>(members), - actionResponses - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java deleted file mode 100644 index 4308c7d17..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/CurrentMemberResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.CurrentMemberAppResponse; - -public record CurrentMemberResponse(String name) { - - public static CurrentMemberResponse of(CurrentMemberAppResponse response) { - return new CurrentMemberResponse(response.name()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java deleted file mode 100644 index 4eb915dd4..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.CurrentMemberAppResponse; - -public record CurrentMembersResponse(List<CurrentMemberResponse> members) { - - public static CurrentMembersResponse of(List<CurrentMemberAppResponse> currentMembers) { - List<CurrentMemberResponse> responses = currentMembers.stream() - .map(CurrentMemberResponse::of) - .toList(); - - return new CurrentMembersResponse(responses); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java deleted file mode 100644 index c18694393..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.EventDetailAppResponse; - -public record EventDetailResponse(String eventName) { - - public static EventDetailResponse of(EventDetailAppResponse response) { - return new EventDetailResponse(response.eventName()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java deleted file mode 100644 index 506f5e814..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.EventAppResponse; - -public record EventResponse(String eventId) { - - public static EventResponse of(EventAppResponse eventAppResponse) { - return new EventResponse(eventAppResponse.token()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java deleted file mode 100644 index 0ea409202..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.MemberBillReportAppResponse; - -public record MemberBillReportResponse(String name, Long price) { - - public static MemberBillReportResponse of(MemberBillReportAppResponse memberBillReportAppResponse) { - return new MemberBillReportResponse(memberBillReportAppResponse.name(), memberBillReportAppResponse.price()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java deleted file mode 100644 index d350c4009..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.MemberBillReportAppResponse; - -public record MemberBillReportsResponse(List<MemberBillReportResponse> reports) { - - public static MemberBillReportsResponse of(List<MemberBillReportAppResponse> memberBillReports) { - List<MemberBillReportResponse> reports = memberBillReports.stream() - .map(MemberBillReportResponse::of) - .toList(); - - return new MemberBillReportsResponse(reports); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java deleted file mode 100644 index a8f3877ef..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java +++ /dev/null @@ -1,57 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import server.haengdong.application.response.ActionAppResponse; - -public record StepResponse( - List<ActionsResponse> steps -) { - - public static StepResponse of(List<ActionAppResponse> actions) { - if (actions.isEmpty()) { - return new StepResponse(List.of()); - } - List<ActionsResponse> actionsResponse = new ArrayList<>(); - Set<String> members = new HashSet<>(); - ActionAppResponse firstAction = getFirstAction(actions); - List<ActionAppResponse> group = new ArrayList<>(); - group.add(firstAction); - String currentActionType = firstAction.actionTypeName(); - members.add(firstAction.name()); - - for (int i = 1; i < actions.size(); i++) { - ActionAppResponse action = actions.get(i); - String typeName = action.actionTypeName(); - if (currentActionType.equals(typeName)) { - if (typeName.equals("IN")) { - members.add(action.name()); - } - if (typeName.equals("OUT")) { - members.remove(action.name()); - } - group.add(action); - continue; - } - actionsResponse.add(ActionsResponse.of(group, members)); - currentActionType = typeName; - group.clear(); - if (typeName.equals("IN")) { - members.add(action.name()); - } - if (typeName.equals("OUT")) { - members.remove(action.name()); - } - group.add(action); - } - actionsResponse.add(ActionsResponse.of(group, members)); - - return new StepResponse(actionsResponse); - } - - private static ActionAppResponse getFirstAction(List<ActionAppResponse> actions) { - return actions.get(0); - } -} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml deleted file mode 100644 index faf7a36f1..000000000 --- a/server/src/main/resources/application.yml +++ /dev/null @@ -1,31 +0,0 @@ -spring: - datasource: - driver-class-name: org.h2.Driver - url: jdbc:h2:mem:database - username: sa - password: - - h2: - console: - enabled: true - path: /h2-console - - jpa: - hibernate: - ddl-auto: create - properties: - hibernate: - format_sql: true - show-sql: true - -cors: - max-age: 3600 - allowed-origins: http://localhost:3000, https://haengdong.pro, https://dev.haengdong.pro, https://app.haengdong.pro - ---- - -spring: - config: - import: classpath:config/application-dev.yml - activate: - on-profile: dev diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java deleted file mode 100644 index ac2dc4f4f..000000000 --- a/server/src/test/java/server/haengdong/application/ActionServiceTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@SpringBootTest -class ActionServiceTest { - - @Autowired - private ActionService actionService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() { - String token = "tOkEn1"; - Event event = new Event("행동대장", token); - Event savedEvent = eventRepository.save(event); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(savedEvent, 1L), "소하", IN, 1L), - new MemberAction(new Action(savedEvent, 2L), "감자", IN, 1L), - new MemberAction(new Action(savedEvent, 3L), "쿠키", IN, 1L), - new MemberAction(new Action(savedEvent, 5L), "감자", OUT, 2L) - ); - List<BillAction> billActions = List.of( - new BillAction(new Action(savedEvent, 4L), "뽕족", 60_000L), - new BillAction(new Action(savedEvent, 6L), "인생맥주", 40_000L), - new BillAction(new Action(savedEvent, 7L), "인생네컷", 20_000L) - ); - memberActionRepository.saveAll(memberActions); - billActionRepository.saveAll(billActions); - - List<MemberBillReportAppResponse> responses = actionService.getMemberBillReports(token); - - assertThat(responses) - .hasSize(3) - .extracting(MemberBillReportAppResponse::name, MemberBillReportAppResponse::price) - .containsExactlyInAnyOrder( - tuple("감자", 20_000L), - tuple("쿠키", 50_000L), - tuple("소하", 50_000L) - ); - } - - @DisplayName("존재하지 않는 이벤트의 참여자별 정산 현황을 조회하는 경우 예외가 발생한다.") - @Test - void getMemberBillReports1() { - assertThatThrownBy(() -> actionService.getMemberBillReports("invalid token")) - .isInstanceOf(HaengdongException.class) - .hasMessage(HaengdongErrorCode.NOT_FOUND_EVENT.getMessage()); - } -} diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java deleted file mode 100644 index 195d4bdd9..000000000 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; - -@SpringBootTest -class BillActionServiceTest { - - @Autowired - private BillActionService billActionService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() { - String token = "TOKEN"; - Event event = new Event("감자", token); - Event savedEvent = eventRepository.save(event); - - List<BillActionAppRequest> requests = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - billActionService.saveAllBillAction(token, requests); - - List<BillAction> actions = billActionRepository.findByAction_Event(savedEvent); - - assertThat(actions).extracting(BillAction::getTitle, BillAction::getPrice, BillAction::getSequence) - .containsExactlyInAnyOrder( - tuple("뽕족", 10_000L, 1L), - tuple("인생맥주", 15_000L, 2L) - ); - } - - @DisplayName("이벤트가 존재하지 않으면 지출 내역을 생성할 수 없다.") - @Test - void saveAllBillAction1() { - List<BillActionAppRequest> requests = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java deleted file mode 100644 index 5a3e8bce3..000000000 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package server.haengdong.application; - - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.BDDMockito.given; - -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.event.EventTokenProvider; - -@SpringBootTest -class EventServiceTest { - - @Autowired - private EventService eventService; - - @MockBean - private EventTokenProvider eventTokenProvider; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private ActionRepository actionRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @AfterEach - void tearDown() { - billActionRepository.deleteAllInBatch(); - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - - @DisplayName("행사를 생성한다") - @Test - void saveEventTest() { - EventAppRequest request = new EventAppRequest("test"); - given(eventTokenProvider.createToken()).willReturn("TOKEN"); - - EventAppResponse response = eventService.saveEvent(request); - - assertThat(response.token()).isEqualTo("TOKEN"); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() { - String token = "TOKEN"; - Event event = new Event("행동대장 회식", token); - eventRepository.save(event); - - EventDetailAppResponse eventDetailAppResponse = eventService.findEvent(token); - - assertThat(eventDetailAppResponse.eventName()).isEqualTo("행동대장 회식"); - } - - @DisplayName("행사에 속한 모든 액션을 조회한다.") - @Test - void findActionsTest() { - Event event = new Event("행동대장 회식", "웨디_토큰"); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - Action action1 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "쿠키", MemberActionStatus.IN, 1L); - Action action2 = new Action(event, 3L); - BillAction billAction = new BillAction(action2, "뽕나무쟁이족발", 30000L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction, memberAction1)); - billActionRepository.save(billAction); - - List<ActionAppResponse> actionAppResponses = eventService.findActions("웨디_토큰"); - - assertThat(actionAppResponses).hasSize(3) - .extracting(ActionAppResponse::actionId, - ActionAppResponse::name, - ActionAppResponse::price, - ActionAppResponse::sequence, - ActionAppResponse::actionTypeName) - .containsExactly( - tuple(1L, "토다리", null, 1L, "IN"), - tuple(2L, "쿠키", null, 2L, "IN"), - tuple(3L, "뽕나무쟁이족발", 30000L, 3L, "BILL") - ); - } -} diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java deleted file mode 100644 index 40bee2ff6..000000000 --- a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java +++ /dev/null @@ -1,217 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; - -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.exception.HaengdongException; - -@SpringBootTest -class MemberActionFactoryTest { - - @Autowired - private MemberActionFactory memberActionFactory; - - @Autowired - private MemberActionRepository memberActionRepository; - - @Autowired - private ActionRepository actionRepository; - - @Autowired - private EventRepository eventRepository; - - @AfterEach - void tearDown() { - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - - @DisplayName("이전 멤버 액션이 시퀀스 기준으로 정렬되지 않은 상태에서 새로운 멤버 액션 요청을 검증한다.") - @Test - void createMemberActionsTest() { - Event event = eventRepository.save(new Event("우당탕탕 행동대장 백엔드 회식", "토다리_토큰")); - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - List<MemberAction> unorderedMemberActions = List.of(memberAction2, memberAction1); - Action startAction = new Action(event, 3L); - - assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, unorderedMemberActions, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("인원 변동 액션을 생성한다.") - @Test - void createMemberActionsTest1() { - Event event = eventRepository.save(new Event("우당탕탕 행동대장 백엔드 회식", "토다리_토큰")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest memberActionsSaveAppRequest = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - Action startAction = new Action(event, 2L); - - List<MemberAction> memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, - List.of(memberAction), startAction); - - assertThat(memberActions).hasSize(1) - .extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus) - .containsExactly( - tuple(startAction, "토다리", MemberActionStatus.OUT) - ); - } - - @DisplayName("현재 행사에 참여 중인 경우에 퇴장할 수 있다.") - @Test - void createMemberActionsTest2() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") - @Test - void createMemberActionsTest3() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action1 = new Action(event, 1L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction1); - Action action2 = new Action(event, 2L); - MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); - memberActionRepository.save(memberAction2); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "IN"))); - Action startAction = new Action(event, 3L); - - assertThatCode( - () -> memberActionFactory.createMemberActions(request, List.of(memberAction1, memberAction2), - startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장한 적 없는 경우에 입장할 수 있다.") - @Test - void createMemberActionsTest4() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") - @Test - void createMemberActionTest5() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "OUT"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("행사에 이미 참여 중인 경우 다시 입장할 수 없다.") - @Test - void createMemberActionTest6() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 동시에 여러 번 입장할 수 없다.") - @Test - void createMemberActionTest7() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"), - new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 1L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(), startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 동시에 여러 번 퇴장할 수 없다.") - @Test - void createMemberActionTest8() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "OUT"), - new MemberActionSaveAppRequest("쿠키", "OUT"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 입장과 퇴장을 동시에 할 수 없다.") - @Test - void createMemberActionTest9() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"), - new MemberActionSaveAppRequest("쿠키", "OUT"))); - Action startAction = new Action(event, 2L); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, List.of(memberAction), startAction)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java deleted file mode 100644 index 7212e300d..000000000 --- a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; - -@SpringBootTest -class MemberActionServiceTest { - - @Autowired - private MemberActionService memberActionService; - - @Autowired - private MemberActionRepository memberActionRepository; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private ActionRepository actionRepository; - - @AfterEach - void tearDown() { - memberActionRepository.deleteAllInBatch(); - actionRepository.deleteAllInBatch(); - eventRepository.deleteAllInBatch(); - } - - @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다.") - @Test - void saveMemberActionTest() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "망쵸", IN, 1L); - memberActionRepository.save(memberAction); - - assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("망쵸", "OUT"))))) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") - @Test - void saveMemberActionTest1() { - Event event = eventRepository.save(new Event("test", "TOKEN")); - Action actionOne = new Action(event, 1L); - MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", IN, 1L); - memberActionRepository.save(memberActionOne); - - Action actionTwo = new Action(event, 2L); - MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", OUT, 1L); - memberActionRepository.save(memberActionTwo); - - assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("망쵸", "IN"))))) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") - @Test - void saveMemberActionTest2() { - MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); - - assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("이벤트가 없으면 현재 참여 인원을 조회할 수 없다.") - @Test - void getCurrentMembers() { - assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/ActionTest.java b/server/src/test/java/server/haengdong/domain/action/ActionTest.java deleted file mode 100644 index 199a4f628..000000000 --- a/server/src/test/java/server/haengdong/domain/action/ActionTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; - -class ActionTest { - - @DisplayName("액션의 초기 순서번호는 1이다.") - @Test - void createFirst() { - Event event = new Event("name", "token"); - Action action = Action.createFirst(event); - - assertThat(action.getSequence()).isOne(); - } - - @DisplayName("현재 액션의 다음 액션의 순서는 1만큼 증가한다.") - @Test - void next() { - Event event = new Event("name", "token"); - Action action = new Action(event, 2L); - - Action nextAction = action.next(); - - assertThat(nextAction.getSequence()).isEqualTo(3L); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java deleted file mode 100644 index 601ca95d7..000000000 --- a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongException; - -class BillActionTest { - - @DisplayName("지출 내역 제목의 앞뒤 공백을 제거한 길이가 2 ~ 30자가 아니면 지출을 생성할 수 없다.") - @ParameterizedTest - @ValueSource(strings = {" 감 ", "", " ", "1234567890123456789012345678901"}) - void validateTitle(String title) { - Event event = new Event("name", "token"); - Action action = new Action(event, 1L); - Long price = 100L; - - assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(HaengdongException.class) - .hasMessage("앞뒤 공백을 제거한 지출 내역 제목은 2 ~ 30자여야 합니다."); - } - - @DisplayName("금액이 10,000,000 이하의 자연수가 아니면 지출을 생성할 수 없다.") - @ParameterizedTest - @ValueSource(longs = {0, 10_000_001, 20_000_000}) - void validatePrice(long price) { - Event event = new Event("name", "token"); - Action action = new Action(event, 1L); - String title = "title"; - - assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(HaengdongException.class) - .hasMessage("지출 금액은 10,000,000 이하의 자연수여야 합니다."); - } - - @DisplayName("지출 내역을 올바르게 생성한다.") - @Test - void createBillAction() { - Event event = new Event("name", "token"); - Action action = new Action(event, 1L); - String title = "title"; - Long price = 1_000L; - - BillAction billAction = new BillAction(action, title, price); - - assertAll( - () -> assertThat(billAction.getAction()).isEqualTo(action), - () -> assertThat(billAction.getTitle()).isEqualTo(title), - () -> assertThat(billAction.getPrice()).isEqualTo(price) - ); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java deleted file mode 100644 index 389ca70c1..000000000 --- a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java +++ /dev/null @@ -1,58 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import java.util.Set; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; - -class CurrentMembersTest { - - @DisplayName("인원 변동 이력으로 현재 참여 인원을 계산한다.") - @Test - void of() { - Event event = new Event("test", "TOKEN"); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(event, 1L), "망쵸", IN, 1L), - new MemberAction(new Action(event, 2L), "백호", IN, 1L), - new MemberAction(new Action(event, 3L), "백호", OUT, 1L), - new MemberAction(new Action(event, 4L), "웨디", IN, 1L) - ); - - CurrentMembers currentMembers = CurrentMembers.of(memberActions); - - assertThat(currentMembers.getMembers()) - .containsExactlyInAnyOrder("망쵸", "웨디"); - } - - @DisplayName("인원 변동 액션의 상태가 IN이면 현재 인원에 추가한다.") - @Test - void addMemberAction1() { - CurrentMembers currentMembers = new CurrentMembers(); - Event event = new Event("이벤트", "token"); - MemberAction memberAction = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); - - CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction); - Set<String> members = addedCurrentMembers.getMembers(); - - assertThat(members).hasSize(1) - .containsExactly("웨디"); - } - - @DisplayName("인원 변동 액션의 상태가 OUT이면 현재 인원에서 제외한다.") - @Test - void addMemberAction2() { - Event event = new Event("이벤트", "token"); - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); - CurrentMembers currentMembers = new CurrentMembers().addMemberAction(memberAction1); - MemberAction memberAction2 = new MemberAction(new Action(event, 1L), "웨디", OUT, 1L); - - CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction2); - - assertThat(addedCurrentMembers.getMembers()).hasSize(0); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java deleted file mode 100644 index 9ad27d5bc..000000000 --- a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; - -class MemberBillReportTest { - - @DisplayName("액션 목록으로 참가자 정산 리포트를 생성한다.") - @Test - void createByActions() { - String token = "TOK2N"; - Event event = new Event("행동대장", token); - List<BillAction> billActions = List.of( - new BillAction(new Action(event, 4L), "뽕족", 60_000L), - new BillAction(new Action(event, 6L), "인생맥주", 40_000L), - new BillAction(new Action(event, 7L), "인생네컷", 20_000L) - ); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(event, 1L), "소하", IN, 1L), - new MemberAction(new Action(event, 2L), "감자", IN, 1L), - new MemberAction(new Action(event, 3L), "쿠키", IN, 1L), - new MemberAction(new Action(event, 5L), "감자", OUT, 2L) - ); - - MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - - assertThat(memberBillReport.getReports()) - .containsAllEntriesOf( - Map.of( - "감자", 20_000L, - "쿠키", 50_000L, - "소하", 50_000L - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/domain/event/EventTest.java b/server/src/test/java/server/haengdong/domain/event/EventTest.java deleted file mode 100644 index 98f6c7050..000000000 --- a/server/src/test/java/server/haengdong/domain/event/EventTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package server.haengdong.domain.event; - -import static org.assertj.core.api.Assertions.assertThatCode; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.exception.HaengdongException; - -class EventTest { - - @DisplayName("공백 문자가 연속되지 않고, 이름이 2자 이상 20자 이하인 행사를 생성하면 예외가 발생하지 않는다.") - @ParameterizedTest - @ValueSource(strings = {"12", "12345678901234567890", "공 백", " 공백", "공백 ", " 공 백 "}) - void createSuccessTest(String eventName) { - assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) - .doesNotThrowAnyException(); - } - - @DisplayName("공백 문자가 연속되면 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {" 공백", "공백 ", "공백 연속", "공 백"}) - void createFailTest1(String eventName) { - assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class) - .hasMessage(String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", eventName)); - } - - @DisplayName("이름이 2자 미만이거나 20자 초과인 경우 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {"", " ", "123456789012345678901"}) - void createFilTest2(String eventName) { - assertThatCode(() -> new Event(eventName, "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class) - .hasMessage(String.format("행사 이름은 2자 이상 20자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", eventName.length())); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java deleted file mode 100644 index 739ac4962..000000000 --- a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package server.haengdong.presentation; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import server.haengdong.application.ActionService; -import server.haengdong.application.response.MemberBillReportAppResponse; - -@WebMvcTest(ActionController.class) -class ActionControllerTest { - - @Autowired - private MockMvc mockMvc; - - @MockBean - private ActionService actionService; - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() throws Exception { - List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( - new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); - - given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); - - mockMvc.perform(get("/api/events/{token}/actions/reports", "token") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))); - - } -} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java deleted file mode 100644 index 8bf2b292f..000000000 --- a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java +++ /dev/null @@ -1,69 +0,0 @@ -package server.haengdong.presentation; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import server.haengdong.application.BillActionService; -import server.haengdong.presentation.request.BillActionSaveRequest; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -@WebMvcTest(BillActionController.class) -class BillActionControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private BillActionService billActionService; - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("뽕족", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String token = "TOKEN"; - - mockMvc.perform(post("/api/events/{token}/actions/bills", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("title이 비어 있는 경우 지출 내역을 생성할 수 없다.") - @Test - void saveAllBillAction1() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String token = "TOKEN"; - - mockMvc.perform(post("/api/events/{token}/actions/bills", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isBadRequest()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java deleted file mode 100644 index 55a48630f..000000000 --- a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package server.haengdong.presentation; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import server.haengdong.application.EventService; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.presentation.request.EventSaveRequest; - -@WebMvcTest(EventController.class) -class EventControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private EventService eventService; - - @DisplayName("이벤트를 생성한다.") - @Test - void saveEvent() throws Exception { - EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리"); - String requestBody = objectMapper.writeValueAsString(eventSaveRequest); - String token = "TOKEN"; - EventAppResponse eventAppResponse = new EventAppResponse(token); - given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); - - mockMvc.perform(post("/api/events") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventId").value("TOKEN")); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() throws Exception { - String token = "TOKEN"; - EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); - given(eventService.findEvent(token)).willReturn(eventDetailAppResponse); - - mockMvc.perform(get("/api/events/" + token)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventName").value("행동대장 회식")); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java deleted file mode 100644 index ad8787cc6..000000000 --- a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package server.haengdong.presentation; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import server.haengdong.application.MemberActionService; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionsSaveRequest; - -@WebMvcTest(MemberActionController.class) -class MemberActionControllerTest { - - @Autowired - private MockMvc mockMvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private MemberActionService memberActionService; - - @DisplayName("참여자 행동을 추가한다.") - @Test - void saveMemberActionTest() throws Exception { - MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( - List.of("웨디", "소하", "토다리", "쿠키"), "IN"); - - String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); - - mockMvc.perform(post("/api/events/TOKEN/actions/members") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("현재 참여 인원을 조회합니다.") - @Test - void getCurrentMembers() throws Exception { - List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( - new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); - - given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); - - mockMvc.perform(get("/api/events/{token}/members/current", "token") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.members[0].name").value(equalTo("소하"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.members[1].name").value(equalTo("토다리"))); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java b/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java deleted file mode 100644 index aac78691c..000000000 --- a/server/src/test/java/server/haengdong/presentation/response/StepResponseTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package server.haengdong.presentation.response; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.ArrayList; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.ActionAppResponse.ActionType; - -@SpringBootTest -class StepResponseTest { - - @Autowired - private ObjectMapper objectMapper; - - @DisplayName("") - @Test - void test() throws JsonProcessingException { - List<ActionAppResponse> actionAppResponse = new ArrayList<>(); - - // IN actions - ActionAppResponse actionAppResponse1 = new ActionAppResponse(3L, "망쵸", null, 3L, ActionType.IN); - actionAppResponse.add(actionAppResponse1); - ActionAppResponse actionAppResponse2 = new ActionAppResponse(4L, "백호", null, 4L, ActionType.IN); - actionAppResponse.add(actionAppResponse2); - - // BILL step 1 - ActionAppResponse actionAppResponse3 = new ActionAppResponse(1L, "감자탕", 10000L, 1L, ActionType.BILL); - actionAppResponse.add(actionAppResponse3); - ActionAppResponse actionAppResponse4 = new ActionAppResponse(2L, "인생네컷", 10000L, 2L, ActionType.BILL); - actionAppResponse.add(actionAppResponse4); - - // IN actions - ActionAppResponse actionAppResponse5 = new ActionAppResponse(5L, "소하", null, 5L, ActionType.IN); - actionAppResponse.add(actionAppResponse5); - ActionAppResponse actionAppResponse6 = new ActionAppResponse(6L, "웨디", null, 6L, ActionType.IN); - actionAppResponse.add(actionAppResponse6); - - // OUT actions - ActionAppResponse actionAppResponse7 = new ActionAppResponse(7L, "망쵸", null, 7L, ActionType.OUT); - actionAppResponse.add(actionAppResponse7); - ActionAppResponse actionAppResponse8 = new ActionAppResponse(8L, "백호", null, 8L, ActionType.OUT); - actionAppResponse.add(actionAppResponse8); - - // BILL step 2 - ActionAppResponse actionAppResponse9 = new ActionAppResponse(9L, "노래방", 20000L, 10L, ActionType.BILL); - actionAppResponse.add(actionAppResponse9); - - // StepResponse creation - StepResponse stepResponse = StepResponse.of(actionAppResponse); - System.out.println("stepResponse = " + stepResponse); - } -} diff --git a/server/src/test/resources/application.yml b/server/src/test/resources/application.yml deleted file mode 100644 index 2d02b2712..000000000 --- a/server/src/test/resources/application.yml +++ /dev/null @@ -1,18 +0,0 @@ -spring: - h2: - console: - enabled: true - path: /h2-console - datasource: - url: jdbc:h2:mem:database - jpa: - defer-datasource-initialization: true - show-sql: true - properties: - hibernate: - format_sql: true - hibernate: - ddl-auto: create-drop -cors: - max-age: 3600 - allowed-origins: http://localhost:8080 From 60ea18b78e4e67b704604f33c0c6ece755e321ff Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:29:14 +0900 Subject: [PATCH 106/273] =?UTF-8?q?[FE]=20=EC=8A=A4=ED=94=84=EB=A6=B0?= =?UTF-8?q?=ED=8A=B83=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20(#162)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 <rhymint@gmail.com> --- .github/workflows/design-pull-request.yml | 19 +- HDesign/package-lock.json | 1189 +++++++++++++++-- HDesign/package.json | 7 +- HDesign/src/assets/error.svg | 3 + HDesign/src/assets/index.ts | 2 + HDesign/src/assets/trash.svg | 3 + .../src/components/Button/Button.stories.tsx | 2 +- HDesign/src/components/Button/Button.style.ts | 4 + HDesign/src/components/Button/Button.type.ts | 2 +- .../components/ExpenseList/ExpenseList.tsx | 6 - .../FixedButton/FixedButton.stories.tsx | 6 + .../FixedButton/FixedButton.style.ts | 27 +- .../components/FixedButton/FixedButton.tsx | 20 +- .../FixedButton/FixedButton.type.ts | 6 +- .../src/components/InOutItem/InOutItem.tsx | 2 - HDesign/src/components/Input/Input.style.ts | 10 +- HDesign/src/components/Input/Input.tsx | 20 +- HDesign/src/components/Input/Input.type.ts | 1 + HDesign/src/components/Input/useInput.ts | 7 +- .../LabelInput/LabelInput.stories.tsx | 35 + .../components/LabelInput/LabelInput.style.ts | 24 + .../src/components/LabelInput/LabelInput.tsx | 30 + .../components/LabelInput/LabelInput.type.ts | 13 + .../src/components/Search/Search.stories.tsx | 2 - .../src/components/Toast/Toast.stories.tsx | 26 + HDesign/src/components/Toast/Toast.style.ts | 33 + HDesign/src/components/Toast/Toast.tsx | 30 + HDesign/src/components/Toast/Toast.type.ts | 16 + HDesign/src/components/Toast/useToast.ts | 34 + HDesign/src/index.tsx | 1 + HDesign/src/token/colors.ts | 45 +- 31 files changed, 1441 insertions(+), 184 deletions(-) create mode 100644 HDesign/src/assets/error.svg create mode 100644 HDesign/src/assets/trash.svg create mode 100644 HDesign/src/components/LabelInput/LabelInput.stories.tsx create mode 100644 HDesign/src/components/LabelInput/LabelInput.style.ts create mode 100644 HDesign/src/components/LabelInput/LabelInput.tsx create mode 100644 HDesign/src/components/LabelInput/LabelInput.type.ts create mode 100644 HDesign/src/components/Toast/Toast.stories.tsx create mode 100644 HDesign/src/components/Toast/Toast.style.ts create mode 100644 HDesign/src/components/Toast/Toast.tsx create mode 100644 HDesign/src/components/Toast/Toast.type.ts create mode 100644 HDesign/src/components/Toast/useToast.ts diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml index 4d54e8b39..03bb1bd08 100644 --- a/.github/workflows/design-pull-request.yml +++ b/.github/workflows/design-pull-request.yml @@ -3,9 +3,9 @@ run-name: ${{ github.actor }}의 스토리북 배포 on: pull_request: branches: - - develop + - fe-dev paths: - - 'HDesign/**' + - 'HDesign/**' jobs: storybook: @@ -28,12 +28,12 @@ jobs: id: cache uses: actions/cache@v3 with: - path: "**/node_modules" + path: '**/node_modules' key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-storybook - name: Set up Node.js - uses: actions/setup-node@v2 - with: + uses: actions/setup-node@v2 + with: node-version: '20.15.1' - name: depedency install @@ -44,8 +44,12 @@ jobs: working-directory: ./HDesign run: npm run lint + - name: run storybook build + working-directory: ./HDesign + run: npm run build-storybook + - name: publish to chromatic - working-directory: ./HDesign + working-directory: ./HDesign id: chromatic uses: chromaui/action@v1 with: @@ -57,5 +61,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - message: "🚀storybook: ${{ steps.chromatic.outputs.storybookUrl }}" - \ No newline at end of file + message: '🚀storybook: ${{ steps.chromatic.outputs.storybookUrl }}' diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 3747523df..916bd1ae5 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,15 +1,16 @@ { "name": "haengdong-design", - "version": "0.1.35", + "version": "0.1.36", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.35", + "version": "0.1.36", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -23,7 +24,6 @@ "@storybook/addon-interactions": "^8.2.2", "@storybook/addon-links": "^8.2.2", "@storybook/addon-onboarding": "^8.2.2", - "@storybook/addon-webpack5-compiler-swc": "^1.0.4", "@storybook/blocks": "^8.2.2", "@storybook/react": "^8.2.2", "@storybook/react-webpack5": "^8.2.3", @@ -32,7 +32,8 @@ "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", - "eslint": "^9.7.0", + "esbuild": "^0.23.0", + "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", @@ -2323,10 +2324,378 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", + "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", + "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", + "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", + "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", + "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", + "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", + "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", + "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", + "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", + "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", + "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", + "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", + "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", + "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", + "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", + "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", + "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", + "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", + "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", + "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", + "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", + "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", "cpu": [ "x64" ], @@ -2336,7 +2705,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -2397,9 +2766,9 @@ } }, "node_modules/@eslint/config-array/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -2465,9 +2834,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -2512,9 +2881,9 @@ "dev": true }, "node_modules/@eslint/js": { - "version": "9.7.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", - "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2986,12 +3355,11 @@ } }, "node_modules/@storybook/addon-webpack5-compiler-swc": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.4.tgz", - "integrity": "sha512-S/ypdAK9oqwUAt3ZOn44qi3RWdH5uBLbBgtfHSXckqTpQRu7F7A9bRzjK+H5ti4xVADRhxu/xzIBwxWgcCeIXA==", - "dev": true, + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", "dependencies": { - "@swc/core": "1.5.7", + "@swc/core": "^1.7.3", "swc-loader": "^0.2.3" }, "engines": { @@ -3319,77 +3687,454 @@ "unicorn-magic": "^0.1.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/core": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.2.tgz", + "integrity": "sha512-L4ojYI+Os/i5bCReDIlFgEDQSS94mbJlNU9WRzEGZpqNC5/hbFEC9Tip7P1MiRx9NrewkzU7b+UCP7mi3e4drQ==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@types/express": "^4.17.21", + "@types/node": "^18.0.0", + "browser-assert": "^1.2.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", + "esbuild-register": "^3.5.0", + "express": "^4.19.2", + "process": "^0.11.10", + "recast": "^0.23.5", + "util": "^0.12.4", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-webpack": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", + "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", + "dev": true, + "dependencies": { + "@types/node": "^18.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.3" + } + }, + "node_modules/@storybook/core-webpack/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@storybook/codemod/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "node_modules/@storybook/core/node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "sunos" + ], "engines": { "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@storybook/codemod/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "node_modules/@storybook/core/node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@storybook/core": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.2.tgz", - "integrity": "sha512-L4ojYI+Os/i5bCReDIlFgEDQSS94mbJlNU9WRzEGZpqNC5/hbFEC9Tip7P1MiRx9NrewkzU7b+UCP7mi3e4drQ==", + "node_modules/@storybook/core/node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@types/express": "^4.17.21", - "@types/node": "^18.0.0", - "browser-assert": "^1.2.1", - "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", - "esbuild-register": "^3.5.0", - "express": "^4.19.2", - "process": "^0.11.10", - "recast": "^0.23.5", - "util": "^0.12.4", - "ws": "^8.2.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@storybook/core-webpack": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", - "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", + "node_modules/@storybook/core/node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@types/node": "^18.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.3" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@storybook/core-webpack/node_modules/@types/node": { + "node_modules/@storybook/core/node_modules/@types/node": { "version": "18.19.39", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", @@ -3398,13 +4143,42 @@ "undici-types": "~5.26.4" } }, - "node_modules/@storybook/core/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "node_modules/@storybook/core/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, - "dependencies": { - "undici-types": "~5.26.4" + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" } }, "node_modules/@storybook/csf": { @@ -4050,14 +4824,13 @@ } }, "node_modules/@swc/core": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.7.tgz", - "integrity": "sha512-U4qJRBefIJNJDRCCiVtkfa/hpiZ7w0R6kASea+/KLp+vkus3zcLSB8Ub8SvKgTIxjWpwsKcZlPf5nrv4ls46SQ==", - "dev": true, + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.3.tgz", + "integrity": "sha512-HHAlbXjWI6Kl9JmmUW1LSygT1YbblXgj2UvvDzMkTBPRzYMhW6xchxdO8HbtMPtFYRt/EQq9u1z7j4ttRSrFsA==", "hasInstallScript": true, "dependencies": { - "@swc/counter": "^0.1.2", - "@swc/types": "0.1.7" + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" }, "engines": { "node": ">=10" @@ -4067,19 +4840,19 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.5.7", - "@swc/core-darwin-x64": "1.5.7", - "@swc/core-linux-arm-gnueabihf": "1.5.7", - "@swc/core-linux-arm64-gnu": "1.5.7", - "@swc/core-linux-arm64-musl": "1.5.7", - "@swc/core-linux-x64-gnu": "1.5.7", - "@swc/core-linux-x64-musl": "1.5.7", - "@swc/core-win32-arm64-msvc": "1.5.7", - "@swc/core-win32-ia32-msvc": "1.5.7", - "@swc/core-win32-x64-msvc": "1.5.7" + "@swc/core-darwin-arm64": "1.7.3", + "@swc/core-darwin-x64": "1.7.3", + "@swc/core-linux-arm-gnueabihf": "1.7.3", + "@swc/core-linux-arm64-gnu": "1.7.3", + "@swc/core-linux-arm64-musl": "1.7.3", + "@swc/core-linux-x64-gnu": "1.7.3", + "@swc/core-linux-x64-musl": "1.7.3", + "@swc/core-win32-arm64-msvc": "1.7.3", + "@swc/core-win32-ia32-msvc": "1.7.3", + "@swc/core-win32-x64-msvc": "1.7.3" }, "peerDependencies": { - "@swc/helpers": "^0.5.0" + "@swc/helpers": "*" }, "peerDependenciesMeta": { "@swc/helpers": { @@ -4087,14 +4860,148 @@ } } }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.3.tgz", + "integrity": "sha512-CTkHa6MJdov9t41vuV2kmQIMu+Q19LrEHGIR/UiJYH06SC/sOu35ZZH8DyfLp9ZoaCn21gwgWd61ixOGQlwzTw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.3.tgz", + "integrity": "sha512-mun623y6rCoZ2EFIYfIRqXYRFufJOopoYSJcxYhZUrfTpAvQ1zLngjQpWCUU1krggXR2U0PQj+ls0DfXUTraNg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.3.tgz", + "integrity": "sha512-4Jz4UcIcvZNMp9qoHbBx35bo3rjt8hpYLPqnR4FFq6gkAsJIMFC56UhRZwdEQoDuYiOFMBnnrsg31Fyo6YQypA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.3.tgz", + "integrity": "sha512-p+U/M/oqV7HC4erQ5TVWHhJU1984QD+wQBPxslAYq751bOQGm0R/mXK42GjugqjnR6yYrAiwKKbpq4iWVXNePA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.3.tgz", + "integrity": "sha512-s6VzyaJwaRGTi2mz2h6Ywxfmgpkc69IxhuMzl+sl34plH0V0RgnZDm14HoCGIKIzRk4+a2EcBV1ZLAfWmPACQg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.3.tgz", + "integrity": "sha512-IrFY48C356Z2dU2pjYg080yvMXzmSV3Lmm/Wna4cfcB1nkVLjWsuYwwRAk9CY7E19c+q8N1sMNggubAUDYoX2g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.3.tgz", + "integrity": "sha512-qoLgxBlBnnyUEDu5vmRQqX90h9jldU1JXI96e6eh2d1gJyKRA0oSK7xXmTzorv1fGHiHulv9qiJOUG+g6uzJWg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.3.tgz", + "integrity": "sha512-OAd7jVVJ7nb0Ev80VAa1aeK+FldPeC4eZ35H4Qn6EICzIz0iqJo2T33qLKkSZiZEBKSoF4KcwrqYfkjLOp5qWg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.3.tgz", + "integrity": "sha512-31+Le1NyfSnILFV9+AhxfFOG0DK0272MNhbIlbcv4w/iqpjkhaOnNQnLsYJD1Ow7lTX1MtIZzTjOhRlzSviRWg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.7.tgz", - "integrity": "sha512-tp43WfJLCsKLQKBmjmY/0vv1slVywR5Q4qKjF5OIY8QijaEW7/8VwPyUyVoJZEnDgv9jKtUTG5PzqtIYPZGnyg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.3.tgz", + "integrity": "sha512-jVQPbYrwcuueI4QB0fHC29SVrkFOBcfIspYDlgSoHnEz6tmLMqUy+txZUypY/ZH/KaK0HEY74JkzgbRC1S6LFQ==", "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -4106,14 +5013,12 @@ "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" }, "node_modules/@swc/types": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.7.tgz", - "integrity": "sha512-scHWahbHF0eyj3JsxG9CFJgFdFNaVQCNAimBlT6PzS3n/HptxqREjsm4OH6AN3lYcffZYSPxXW8ua2BEHp0lJQ==", - "dev": true, + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", "dependencies": { "@swc/counter": "^0.1.3" } @@ -7070,41 +7975,42 @@ } }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" } }, "node_modules/esbuild-register": { @@ -7195,16 +8101,16 @@ } }, "node_modules/eslint": { - "version": "9.7.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.7.0.tgz", - "integrity": "sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.17.0", + "@eslint/config-array": "^0.17.1", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.7.0", + "@eslint/js": "9.8.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -12498,7 +13404,6 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", - "dev": true, "dependencies": { "@swc/counter": "^0.1.3" }, diff --git a/HDesign/package.json b/HDesign/package.json index b587d3be8..a10d83b7b 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.35", + "version": "0.1.36", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", @@ -27,7 +27,6 @@ "@storybook/addon-interactions": "^8.2.2", "@storybook/addon-links": "^8.2.2", "@storybook/addon-onboarding": "^8.2.2", - "@storybook/addon-webpack5-compiler-swc": "^1.0.4", "@storybook/blocks": "^8.2.2", "@storybook/react": "^8.2.2", "@storybook/react-webpack5": "^8.2.3", @@ -36,7 +35,8 @@ "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", - "eslint": "^9.7.0", + "esbuild": "^0.23.0", + "eslint": "^9.8.0", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", @@ -57,6 +57,7 @@ }, "dependencies": { "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/HDesign/src/assets/error.svg b/HDesign/src/assets/error.svg new file mode 100644 index 000000000..81d9689c5 --- /dev/null +++ b/HDesign/src/assets/error.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M13 13H11V7H13M13 17H11V15H13M12 2C10.6868 2 9.38642 2.25866 8.17317 2.7612C6.95991 3.26375 5.85752 4.00035 4.92893 4.92893C3.05357 6.8043 2 9.34784 2 12C2 14.6522 3.05357 17.1957 4.92893 19.0711C5.85752 19.9997 6.95991 20.7362 8.17317 21.2388C9.38642 21.7413 10.6868 22 12 22C14.6522 22 17.1957 20.9464 19.0711 19.0711C20.9464 17.1957 22 14.6522 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7362 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2Z" fill="#ECFF59"/> +</svg> diff --git a/HDesign/src/assets/index.ts b/HDesign/src/assets/index.ts index 3f92063cd..b20e4ad3d 100644 --- a/HDesign/src/assets/index.ts +++ b/HDesign/src/assets/index.ts @@ -2,3 +2,5 @@ export {default as InputDelete} from '@assets/inputDelete.svg'; export {default as Plus} from '@assets/plus.svg'; export {default as Buljusa} from '@assets/buljusa.svg'; export {default as Arrow} from '@assets/arrow.svg'; +export {default as Error} from '@assets/error.svg'; +export {default as Trash} from '@assets/trash.svg'; diff --git a/HDesign/src/assets/trash.svg b/HDesign/src/assets/trash.svg new file mode 100644 index 000000000..086ebc748 --- /dev/null +++ b/HDesign/src/assets/trash.svg @@ -0,0 +1,3 @@ +<svg width="22" height="24" viewBox="0 0 22 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M8.5 4H13.5C13.5 3.33696 13.2366 2.70107 12.7678 2.23223C12.2989 1.76339 11.663 1.5 11 1.5C10.337 1.5 9.70107 1.76339 9.23223 2.23223C8.76339 2.70107 8.5 3.33696 8.5 4ZM7 4C7 2.93913 7.42143 1.92172 8.17157 1.17157C8.92172 0.421427 9.93913 0 11 0C12.0609 0 13.0783 0.421427 13.8284 1.17157C14.5786 1.92172 15 2.93913 15 4H21.25C21.4489 4 21.6397 4.07902 21.7803 4.21967C21.921 4.36032 22 4.55109 22 4.75C22 4.94891 21.921 5.13968 21.7803 5.28033C21.6397 5.42098 21.4489 5.5 21.25 5.5H19.94L18.723 20.103C18.6345 21.1653 18.1499 22.1556 17.3655 22.8774C16.5811 23.5992 15.554 23.9999 14.488 24H7.512C6.44599 23.9999 5.41894 23.5992 4.6345 22.8774C3.85007 22.1556 3.36554 21.1653 3.277 20.103L2.06 5.5H0.75C0.551088 5.5 0.360322 5.42098 0.21967 5.28033C0.0790175 5.13968 0 4.94891 0 4.75C0 4.55109 0.0790175 4.36032 0.21967 4.21967C0.360322 4.07902 0.551088 4 0.75 4H7ZM9.5 9.75C9.5 9.55109 9.42098 9.36032 9.28033 9.21967C9.13968 9.07902 8.94891 9 8.75 9C8.55109 9 8.36032 9.07902 8.21967 9.21967C8.07902 9.36032 8 9.55109 8 9.75V18.25C8 18.4489 8.07902 18.6397 8.21967 18.7803C8.36032 18.921 8.55109 19 8.75 19C8.94891 19 9.13968 18.921 9.28033 18.7803C9.42098 18.6397 9.5 18.4489 9.5 18.25V9.75ZM13.25 9C13.0511 9 12.8603 9.07902 12.7197 9.21967C12.579 9.36032 12.5 9.55109 12.5 9.75V18.25C12.5 18.4489 12.579 18.6397 12.7197 18.7803C12.8603 18.921 13.0511 19 13.25 19C13.4489 19 13.6397 18.921 13.7803 18.7803C13.921 18.6397 14 18.4489 14 18.25V9.75C14 9.55109 13.921 9.36032 13.7803 9.21967C13.6397 9.07902 13.4489 9 13.25 9Z" fill="white"/> +</svg> diff --git a/HDesign/src/components/Button/Button.stories.tsx b/HDesign/src/components/Button/Button.stories.tsx index 2e8b00bb3..3ba8a4129 100644 --- a/HDesign/src/components/Button/Button.stories.tsx +++ b/HDesign/src/components/Button/Button.stories.tsx @@ -13,7 +13,7 @@ const meta = { variants: { description: '', control: {type: 'select'}, - options: ['', 'primary', 'secondary', 'tertiary'], + options: ['', 'primary', 'secondary', 'tertiary', 'destructive'], }, size: { description: '', diff --git a/HDesign/src/components/Button/Button.style.ts b/HDesign/src/components/Button/Button.style.ts index b0a3720ac..2862e9538 100644 --- a/HDesign/src/components/Button/Button.style.ts +++ b/HDesign/src/components/Button/Button.style.ts @@ -66,6 +66,10 @@ const getButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => { backgroundColor: theme.colors.tertiary, color: theme.colors.onTertiary, }), + destructive: css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), }; return style[variants]; diff --git a/HDesign/src/components/Button/Button.type.ts b/HDesign/src/components/Button/Button.type.ts index 7c200574f..52da8a18d 100644 --- a/HDesign/src/components/Button/Button.type.ts +++ b/HDesign/src/components/Button/Button.type.ts @@ -1,7 +1,7 @@ import {Theme} from '@theme/theme.type'; export type ButtonSize = 'small' | 'medium' | 'large'; -export type ButtonVariants = 'primary' | 'secondary' | 'tertiary'; +export type ButtonVariants = 'primary' | 'secondary' | 'tertiary' | 'destructive'; export interface ButtonStyleProps { variants?: ButtonVariants; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx index 2990458bb..e637c7b1b 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.tsx +++ b/HDesign/src/components/ExpenseList/ExpenseList.tsx @@ -2,13 +2,10 @@ import Text from '@components/Text/Text'; - import {Arrow} from '@assets/index'; import {useTheme} from '@theme/HDesignProvider'; -import {useTheme} from '@theme/HDesignProvider'; - import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle, TextStyle} from './ExpenseList.style'; @@ -27,9 +24,7 @@ function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { </button> ); } -} -function ExpenseList({expenseList = []}: ExpenseListProps) { function ExpenseList({expenseList = []}: ExpenseListProps) { const {theme} = useTheme(); return ( @@ -40,6 +35,5 @@ function ExpenseList({expenseList = []}: ExpenseListProps) { </div> ); } -} export default ExpenseList; diff --git a/HDesign/src/components/FixedButton/FixedButton.stories.tsx b/HDesign/src/components/FixedButton/FixedButton.stories.tsx index a07260d2c..fb7fdc008 100644 --- a/HDesign/src/components/FixedButton/FixedButton.stories.tsx +++ b/HDesign/src/components/FixedButton/FixedButton.stories.tsx @@ -18,11 +18,17 @@ const meta = { description: '', control: {type: 'boolean'}, }, + onDeleteClick: { + description: '', + control: {type: 'select'}, + options: [undefined, () => alert('delete')], + }, }, args: { variants: 'primary', disabled: false, children: 'button', + onDeleteClick: () => alert('delete'), }, decorators: [ Story => ( diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/HDesign/src/components/FixedButton/FixedButton.style.ts index 19e011893..5c3e69d77 100644 --- a/HDesign/src/components/FixedButton/FixedButton.style.ts +++ b/HDesign/src/components/FixedButton/FixedButton.style.ts @@ -16,6 +16,28 @@ export const fixedButtonContainerStyle = (theme: Theme) => boxSizing: 'border-box', }); +export const buttonContainerStyle = css({ + display: 'flex', + gap: '1rem', + margin: '1rem 1rem 2rem 1rem', + width: '100%', +}); + +export const deleteButtonStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + padding: '0.875rem 1rem', + borderRadius: '1.25rem', + backgroundColor: theme.colors.error, + color: theme.colors.white, + + fontFamily: 'Pretendard', + fontSize: '1.25rem', + fontWeight: '700', + lineHeight: '1', + }); + export const fixedButtonStyle = (props: Required<FixedButtonStyleProps>) => { return [getFixedButtonDefaultStyle(props.theme), getFixedButtonVariantsStyle(props.variants, props.theme)]; }; @@ -26,7 +48,6 @@ const getFixedButtonDefaultStyle = (theme: Theme) => justifyContent: 'center', padding: '1rem 1.5rem', borderRadius: '1.25rem', - margin: '1.5rem 1rem 3rem 1rem', width: '100%', fontFamily: 'Pretendard', @@ -54,6 +75,10 @@ const getFixedButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => backgroundColor: theme.colors.tertiary, color: theme.colors.onTertiary, }), + destructive: css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), }; return style[variants]; diff --git a/HDesign/src/components/FixedButton/FixedButton.tsx b/HDesign/src/components/FixedButton/FixedButton.tsx index e98db5918..275059172 100644 --- a/HDesign/src/components/FixedButton/FixedButton.tsx +++ b/HDesign/src/components/FixedButton/FixedButton.tsx @@ -1,19 +1,33 @@ /** @jsxImportSource @emotion/react */ import {forwardRef} from 'react'; -import {fixedButtonContainerStyle, fixedButtonStyle} from '@components/FixedButton/FixedButton.style'; +import { + fixedButtonContainerStyle, + fixedButtonStyle, + deleteButtonStyle, + buttonContainerStyle, +} from '@components/FixedButton/FixedButton.style'; import {FixedButtonProps} from '@components/FixedButton/FixedButton.type'; +import Trash from '@assets/trash.svg'; + import {useTheme} from '@theme/HDesignProvider'; export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElement, FixedButtonProps>(function Button( - {variants = 'primary', ...htmlProps}: FixedButtonProps, + {variants = 'primary', onDeleteClick, ...htmlProps}: FixedButtonProps, ref, ) { const {theme} = useTheme(); return ( <div css={fixedButtonContainerStyle(theme)}> - <button css={fixedButtonStyle({variants, theme})} ref={ref} {...htmlProps} /> + <div css={buttonContainerStyle}> + {onDeleteClick && ( + <button css={deleteButtonStyle(theme)} onClick={onDeleteClick}> + <Trash /> + </button> + )} + <button css={fixedButtonStyle({variants, theme})} ref={ref} {...htmlProps} /> + </div> </div> ); }); diff --git a/HDesign/src/components/FixedButton/FixedButton.type.ts b/HDesign/src/components/FixedButton/FixedButton.type.ts index 84f38ca35..1e8c55144 100644 --- a/HDesign/src/components/FixedButton/FixedButton.type.ts +++ b/HDesign/src/components/FixedButton/FixedButton.type.ts @@ -7,8 +7,10 @@ export interface FixedButtonStyleProps { theme?: Theme; } -export interface ButtonCustomProps {} +export interface ButtonCustomProps { + onDeleteClick?: () => void; +} -export type FixedButtonOptionProps = FixedButtonStyleProps; +export type FixedButtonOptionProps = FixedButtonStyleProps & ButtonCustomProps; export type FixedButtonProps = React.ComponentProps<'button'> & FixedButtonOptionProps; diff --git a/HDesign/src/components/InOutItem/InOutItem.tsx b/HDesign/src/components/InOutItem/InOutItem.tsx index 9393c5e20..2f506f5f3 100644 --- a/HDesign/src/components/InOutItem/InOutItem.tsx +++ b/HDesign/src/components/InOutItem/InOutItem.tsx @@ -3,8 +3,6 @@ import React from 'react'; import Text from '@components/Text/Text'; -import Text from '@components/Text/Text'; - import {useTheme} from '@theme/HDesignProvider'; import DragHandleItem from '../DragHandleItem/DragHandleItem'; diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts index 50980be64..285908bab 100644 --- a/HDesign/src/components/Input/Input.style.ts +++ b/HDesign/src/components/Input/Input.style.ts @@ -17,7 +17,12 @@ const inputBoxBackgroundColorByInputType = (theme: Theme, inputType: InputType = } }; -export const inputBoxStyle = (theme: Theme, inputType: InputType = 'input') => +export const inputBoxStyle = ( + theme: Theme, + inputType: InputType = 'input', + isFocus: boolean, + isError: boolean | undefined, +) => css({ display: 'flex', justifyContent: 'space-between', @@ -25,6 +30,9 @@ export const inputBoxStyle = (theme: Theme, inputType: InputType = 'input') => padding: '0.75rem 1rem', borderRadius: '1rem', backgroundColor: inputBoxBackgroundColorByInputType(theme, inputType), + + boxSizing: 'border-box', + outline: isFocus ? `1px solid ${theme.colors.primary}` : isError ? `1px solid ${theme.colors.error}` : 'none', }); export const inputStyle = (theme: Theme) => diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx index 4e8ac6e5d..81f0f1c93 100644 --- a/HDesign/src/components/Input/Input.tsx +++ b/HDesign/src/components/Input/Input.tsx @@ -1,5 +1,5 @@ /** @jsxImportSource @emotion/react */ -import React, {forwardRef, useImperativeHandle, useRef} from 'react'; +import React, {forwardRef, useImperativeHandle, useRef, useState} from 'react'; import IconButton from '@components/IconButton/IconButton'; import {InputProps} from '@components/Input/Input.type'; @@ -9,7 +9,7 @@ import {useInput} from '@components/Input/useInput'; import {useTheme} from '@theme/HDesignProvider'; export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( - {value: propsValue, onChange, inputType, ...htmlProps}: InputProps, + {value: propsValue, onChange, inputType, isError, ...htmlProps}: InputProps, ref, ) { const {theme} = useTheme(); @@ -17,12 +17,20 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro useImperativeHandle(ref, () => inputRef.current!); - const {value, handleChange, handleClickDelete} = useInput({propsValue, onChange, inputRef}); + const {value, hasFocus, handleChange, handleClickDelete, toggleFocus} = useInput({propsValue, onChange, inputRef}); return ( - <div css={inputBoxStyle(theme, inputType)}> - <input css={inputStyle(theme)} ref={inputRef} value={value} onChange={handleChange} {...htmlProps} /> - {value && <IconButton iconType="inputDelete" onClick={handleClickDelete} />} + <div css={inputBoxStyle(theme, inputType, hasFocus, isError)}> + <input + css={inputStyle(theme)} + ref={inputRef} + value={value} + onChange={handleChange} + onFocus={toggleFocus} + onBlur={toggleFocus} + {...htmlProps} + /> + {value && hasFocus && <IconButton iconType="inputDelete" onClick={handleClickDelete} />} </div> ); }); diff --git a/HDesign/src/components/Input/Input.type.ts b/HDesign/src/components/Input/Input.type.ts index b2f2fc827..2cfdfcd4a 100644 --- a/HDesign/src/components/Input/Input.type.ts +++ b/HDesign/src/components/Input/Input.type.ts @@ -8,6 +8,7 @@ export type InputType = 'input' | 'search'; export interface InputCustomProps { inputType?: InputType; + isError?: boolean; } export type InputOptionProps = InputStyleProps & InputCustomProps; diff --git a/HDesign/src/components/Input/useInput.ts b/HDesign/src/components/Input/useInput.ts index af4892964..5b37d275a 100644 --- a/HDesign/src/components/Input/useInput.ts +++ b/HDesign/src/components/Input/useInput.ts @@ -8,6 +8,7 @@ interface UseInputProps<T> { export const useInput = <T>({propsValue, onChange, inputRef}: UseInputProps<T>) => { const [value, setValue] = useState(propsValue || ''); + const [hasFocus, setHasFocus] = useState(false); useEffect(() => { setValue(propsValue || ''); @@ -32,5 +33,9 @@ export const useInput = <T>({propsValue, onChange, inputRef}: UseInputProps<T>) } }; - return {value, handleChange, handleClickDelete}; + const toggleFocus = () => { + setHasFocus(!hasFocus); + }; + + return {value, hasFocus, handleChange, handleClickDelete, toggleFocus}; }; diff --git a/HDesign/src/components/LabelInput/LabelInput.stories.tsx b/HDesign/src/components/LabelInput/LabelInput.stories.tsx new file mode 100644 index 000000000..63ebcea37 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.stories.tsx @@ -0,0 +1,35 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import LabelInput from '@components/LabelInput/LabelInput'; +import Input from '@components/Input/Input'; + +const meta = { + title: 'Components/LabelInput', + component: LabelInput, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + labelText: { + description: 'label에 들어갈 텍스트를 작성', + control: {type: 'text'}, + }, + errorText: { + description: 'error에 들어갈 텍스트를 작성', + control: {type: 'text'}, + }, + }, + args: { + labelText: 'label 내용', + errorText: 'error가 발생했을 때 나타납니다!', + children: <Input placeholder="labelInput 테스트를 위한 Input" />, + }, +} satisfies Meta<typeof LabelInput>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/LabelInput/LabelInput.style.ts b/HDesign/src/components/LabelInput/LabelInput.style.ts new file mode 100644 index 000000000..208d6e56c --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.style.ts @@ -0,0 +1,24 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@/theme/theme.type'; + +export const labelGroupStyle = () => + css({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%', + + paddingInline: '0.5rem', + marginBottom: '0.375rem', + }); + +export const labelTextStyle = (theme: Theme) => + css({ + color: theme.colors.gray, + }); + +export const errorTextStyle = (theme: Theme) => + css({ + color: theme.colors.onErrorContainer, + }); diff --git a/HDesign/src/components/LabelInput/LabelInput.tsx b/HDesign/src/components/LabelInput/LabelInput.tsx new file mode 100644 index 000000000..97cc9bcd1 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.tsx @@ -0,0 +1,30 @@ +/** @jsxImportSource @emotion/react */ + +import Text from '@components/Text/Text'; +import {useTheme} from '@/theme/HDesignProvider'; + +import {LabelInputProps} from './LabelInput.type'; +import {errorTextStyle, labelGroupStyle, labelTextStyle} from './LabelInput.style'; + +const LabelInput = ({labelText, errorText, children}: LabelInputProps) => { + const {theme} = useTheme(); + return ( + <> + <div css={labelGroupStyle}> + <label> + <Text size="caption" css={labelTextStyle(theme)}> + {labelText} + </Text> + </label> + {errorText && ( + <Text size="caption" css={errorTextStyle(theme)}> + {errorText} + </Text> + )} + </div> + {children} + </> + ); +}; + +export default LabelInput; diff --git a/HDesign/src/components/LabelInput/LabelInput.type.ts b/HDesign/src/components/LabelInput/LabelInput.type.ts new file mode 100644 index 000000000..539a10da1 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.type.ts @@ -0,0 +1,13 @@ +import {InputProps} from '../Input/Input.type'; + +export interface LabelInputStyleProps {} + +export interface ButtonCustomProps { + labelText: string; + errorText?: string; + children?: React.ReactElement<InputProps>[] | React.ReactElement<InputProps>; +} + +export type LabelInputOptionProps = LabelInputStyleProps & ButtonCustomProps; + +export type LabelInputProps = React.ComponentProps<'div'> & LabelInputOptionProps; diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx index f4cd6d567..2ce93f3a5 100644 --- a/HDesign/src/components/Search/Search.stories.tsx +++ b/HDesign/src/components/Search/Search.stories.tsx @@ -2,8 +2,6 @@ import type {Meta, StoryObj} from '@storybook/react'; import React from 'react'; -import React from 'react'; - import Search from '@components/Search/Search'; const meta = { diff --git a/HDesign/src/components/Toast/Toast.stories.tsx b/HDesign/src/components/Toast/Toast.stories.tsx new file mode 100644 index 000000000..35789224a --- /dev/null +++ b/HDesign/src/components/Toast/Toast.stories.tsx @@ -0,0 +1,26 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Toast from '@components/Toast/Toast'; + +const meta = { + title: 'Components/Toast', + component: Toast, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + args: { + top: 80, + message: `서버 오류로 인해 인원을 설정하는데 실패했어요. +두글자면 이렇게 보여요.`, + showingTime: 1000, + alwaysShow: false, + }, +} satisfies Meta<typeof Toast>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Toast/Toast.style.ts b/HDesign/src/components/Toast/Toast.style.ts new file mode 100644 index 000000000..ac0597675 --- /dev/null +++ b/HDesign/src/components/Toast/Toast.style.ts @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@/theme/theme.type'; + +export const toastStyle = (top: number, isShow: boolean, theme: Theme) => + css({ + display: isShow ? 'flex' : 'none', + alignItems: 'center', + + position: 'absolute', + top: `${top}%`, + left: 0, + gap: '0.5rem', + + maxWidth: '48rem', + width: '100%', + margin: '1.25rem', + padding: '0.625rem', + + backgroundColor: theme.colors.gray, + boxShadow: '0 8px 12px rgba(0, 0, 0, 0.16);', + + borderRadius: '1.25rem', + }); + +export const textStyle = (theme: Theme) => + css({ + width: '100%', + + color: theme.colors.white, + + whiteSpace: 'pre-line', + }); diff --git a/HDesign/src/components/Toast/Toast.tsx b/HDesign/src/components/Toast/Toast.tsx new file mode 100644 index 000000000..b8a921d34 --- /dev/null +++ b/HDesign/src/components/Toast/Toast.tsx @@ -0,0 +1,30 @@ +/** @jsxImportSource @emotion/react */ +import {createPortal} from 'react-dom'; + +import Text from '@components/Text/Text'; + +import ErrorIcon from '@assets/error.svg'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {toastStyle, textStyle} from './Toast.style'; +import {ToastProps} from './Toast.type'; +import useToast from './useToast'; + +const Toast: React.FC<ToastProps> = ({top = 80, message, showingTime, alwaysShow}) => { + const {theme} = useTheme(); + const {isShow} = useToast({message, showingTime, alwaysShow}); + + return createPortal( + // TODO: (@cookie) toast를 위한 시멘틱 태그 알아보기 + <div css={toastStyle(top, isShow, theme)}> + <ErrorIcon /> + <Text size="smallBodyBold" css={textStyle(theme)}> + {message} + </Text> + </div>, + document.body, + ); +}; + +export default Toast; diff --git a/HDesign/src/components/Toast/Toast.type.ts b/HDesign/src/components/Toast/Toast.type.ts new file mode 100644 index 000000000..4e3a13ea8 --- /dev/null +++ b/HDesign/src/components/Toast/Toast.type.ts @@ -0,0 +1,16 @@ +export interface ToastStyleProps { + top?: number; +} + +export interface ToastCustomProps { + showingTime?: number; + alwaysShow?: boolean; +} + +export interface ToastRequiredProps { + message: string; +} + +export type ToastOptionProps = ToastStyleProps & ToastCustomProps; + +export type ToastProps = React.ComponentProps<'aside'> & ToastOptionProps & ToastRequiredProps; diff --git a/HDesign/src/components/Toast/useToast.ts b/HDesign/src/components/Toast/useToast.ts new file mode 100644 index 000000000..570f5b5a9 --- /dev/null +++ b/HDesign/src/components/Toast/useToast.ts @@ -0,0 +1,34 @@ +import {useState, useEffect} from 'react'; + +interface UseToastProps { + message: string; + showingTime?: number; + alwaysShow?: boolean; +} + +const useToast = ({message, showingTime = 3000, alwaysShow = false}: UseToastProps) => { + const [isShow, setIsShow] = useState(false); + + const showToast = () => { + setIsShow(true); + }; + + const untilShowingTimeAndDisappear = () => { + setTimeout(() => { + setIsShow(false); + }, showingTime); + }; + + useEffect(() => { + showToast(); + if (!alwaysShow) { + untilShowingTimeAndDisappear(); + } + }, [message]); + + return { + isShow, + }; +}; + +export default useToast; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index e0b6e6fee..9cac56e5d 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -16,6 +16,7 @@ import Text from '@components/Text/Text'; import TextButton from '@components/TextButton/TextButton'; import Title from '@components/Title/Title'; import TopNav from '@components/TopNav/TopNav'; + import {MainLayout} from '@layouts/MainLayout'; import {ContentLayout} from '@layouts/ContentLayout'; diff --git a/HDesign/src/token/colors.ts b/HDesign/src/token/colors.ts index 01bbf8f02..d01c6883e 100644 --- a/HDesign/src/token/colors.ts +++ b/HDesign/src/token/colors.ts @@ -12,6 +12,30 @@ const PRIMITIVE_COLORS = { 800: '#6712db', 900: '#5100cd', }, + pink: { + 50: '#ffe1ff', + 100: '#feafd9', + 200: '#ff75bf', + 300: '#fc28a1', + 400: '#f60087', + 500: '#f2006d', + 600: '#e1006a', + 700: '#ca0065', + 800: '#b30062', + 900: '#8b005b', + }, + yellow: { + 50: '#fdffe9', + 100: '#f7fdc5', + 200: '#f0fb9d', + 300: '#e8f972', + 400: '#ecff59', + 500: '#e5fb31', + 600: '#daeb2e', + 700: '#c9d323', + 800: '#b9bb17', + 900: '#9e9305', + }, gray: { 50: '#F9F8FD', 100: '#F1F0F5', @@ -30,8 +54,6 @@ type Color = string; export type ColorKeys = | 'white' - | 'gray' - | 'darkGray' | 'black' | 'primary' | 'onPrimary' @@ -39,22 +61,35 @@ export type ColorKeys = | 'onSecondary' | 'tertiary' | 'onTertiary' + | 'gray' + | 'darkGray' | 'grayContainer' - | 'lightGrayContainer'; + | 'lightGrayContainer' + | 'error' + | 'errorContainer' + | 'onErrorContainer' + | 'warn'; export type ColorTokens = Record<ColorKeys, Color>; // TODO: (@soha) 대괄호 사용에 대해 논의 export const COLORS: ColorTokens = { white: PRIMITIVE_COLORS.white, - gray: PRIMITIVE_COLORS.gray[400], - darkGray: PRIMITIVE_COLORS.gray[500], black: PRIMITIVE_COLORS.gray[700], + primary: PRIMITIVE_COLORS.purple[300], onPrimary: PRIMITIVE_COLORS.white, secondary: PRIMITIVE_COLORS.purple[50], onSecondary: PRIMITIVE_COLORS.purple[600], tertiary: PRIMITIVE_COLORS.gray[200], onTertiary: PRIMITIVE_COLORS.gray[700], + + gray: PRIMITIVE_COLORS.gray[400], + darkGray: PRIMITIVE_COLORS.gray[500], grayContainer: PRIMITIVE_COLORS.gray[100], lightGrayContainer: PRIMITIVE_COLORS.gray[50], + + error: PRIMITIVE_COLORS.pink[200], + errorContainer: PRIMITIVE_COLORS.pink[50], + onErrorContainer: PRIMITIVE_COLORS.pink[300], + warn: PRIMITIVE_COLORS.yellow[400], }; From 5229370ee7f261d0642e3f1c1eb9c032f96c2923 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Tue, 30 Jul 2024 17:18:08 +0900 Subject: [PATCH 107/273] =?UTF-8?q?chore:=20branch=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20yml=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#165)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/design-pull-request.yml | 16 ++++++---------- .github/workflows/frontend-pull-request.yml | 4 ++-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml index 03bb1bd08..3045c9d8f 100644 --- a/.github/workflows/design-pull-request.yml +++ b/.github/workflows/design-pull-request.yml @@ -5,7 +5,7 @@ on: branches: - fe-dev paths: - - 'HDesign/**' + - 'HDesign/**' jobs: storybook: @@ -28,12 +28,12 @@ jobs: id: cache uses: actions/cache@v3 with: - path: '**/node_modules' + path: "**/node_modules" key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-storybook - name: Set up Node.js - uses: actions/setup-node@v2 - with: + uses: actions/setup-node@v2 + with: node-version: '20.15.1' - name: depedency install @@ -44,15 +44,11 @@ jobs: working-directory: ./HDesign run: npm run lint - - name: run storybook build - working-directory: ./HDesign - run: npm run build-storybook - - name: publish to chromatic - working-directory: ./HDesign id: chromatic uses: chromaui/action@v1 with: + workingDirectory: ./HDesign projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }} @@ -61,4 +57,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - message: '🚀storybook: ${{ steps.chromatic.outputs.storybookUrl }}' + message: "🚀storybook: ${{ steps.chromatic.outputs.storybookUrl }}" diff --git a/.github/workflows/frontend-pull-request.yml b/.github/workflows/frontend-pull-request.yml index b94c4ceeb..c9efc26cc 100644 --- a/.github/workflows/frontend-pull-request.yml +++ b/.github/workflows/frontend-pull-request.yml @@ -3,13 +3,13 @@ name: frontend-pull-request on: pull_request: types: [opened, synchronize] - branches: [main, develop] + branches: [main, fe-dev] paths: - 'client/**' jobs: test: - runs-on: ubuntu-latest + runs-on: ubuntu-latest log defaults: run: From fcb1efd7bbb79e31235a2a0975d8849147887dd5 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:06:13 +0900 Subject: [PATCH 108/273] =?UTF-8?q?fix:=20=EC=8A=A4=ED=86=A0=EB=A6=AC?= =?UTF-8?q?=EB=B6=81=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20(#168)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 --- .github/workflows/design-pull-request.yml | 63 +++++++++++------------ 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml index 3045c9d8f..3c88c82b1 100644 --- a/.github/workflows/design-pull-request.yml +++ b/.github/workflows/design-pull-request.yml @@ -1,60 +1,55 @@ name: Storybook Deployment run-name: ${{ github.actor }}의 스토리북 배포 + on: pull_request: branches: - fe-dev paths: - - 'HDesign/**' + - 'HDesign/**' jobs: - storybook: + chromatic: + name: Run Chromatic runs-on: ubuntu-latest - outputs: - status: ${{ job.status }} - - defaults: - run: - shell: bash - working-directory: ./HDesign - steps: - - name: checkout repository - uses: actions/checkout@v3 + - name: Checkout code + uses: actions/checkout@v4 with: fetch-depth: 0 - - name: cache dependencies + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.15.1' + + - name: Cache dependencies id: cache uses: actions/cache@v3 with: - path: "**/node_modules" - key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-storybook - - - name: Set up Node.js - uses: actions/setup-node@v2 - with: - node-version: '20.15.1' + path: '**/node_modules' + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-npm- - - name: depedency install + - name: Install dependencies if: steps.cache.outputs.cache-hit != 'true' - run: npm ci + run: | + cd HDesign + npm install - - name: run lint - working-directory: ./HDesign + - name: Run lint run: npm run lint + working-directory: ./HDesign - - name: publish to chromatic - id: chromatic - uses: chromaui/action@v1 + - name: Run Chromatic + uses: chromaui/action@latest + id: publish_chromatic with: - workingDirectory: ./HDesign + workingDir: HDesign projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - token: ${{ secrets.GITHUB_TOKEN }} - - name: comment PR - uses: thollander/actions-comment-pull-request@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Comment on PR + uses: thollander/actions-comment-pull-request@v2 with: - message: "🚀storybook: ${{ steps.chromatic.outputs.storybookUrl }}" + message: '🚀 **storybook**: ${{ steps.publish_chromatic.outputs.storybookUrl }}' From 1460d1e2823df97f25ee6c381d2fb3c575411acb Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Sat, 3 Aug 2024 04:59:41 +0900 Subject: [PATCH 109/273] =?UTF-8?q?feat:=20=ED=86=A0=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20(#166)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --- HDesign/package-lock.json | 2067 ++++++----------- HDesign/src/assets/confirm.svg | 10 + HDesign/src/assets/error.svg | 2 +- HDesign/src/components/Button/Button.style.ts | 1 + .../src/components/Toast/Toast.stories.tsx | 53 +- HDesign/src/components/Toast/Toast.style.ts | 29 +- HDesign/src/components/Toast/Toast.tsx | 67 +- HDesign/src/components/Toast/Toast.type.ts | 19 +- .../Toast/ToastProvider.stories.tsx | 46 + .../src/components/Toast/ToastProvider.tsx | 59 + HDesign/src/components/Toast/useToast.ts | 34 - HDesign/src/index.tsx | 5 + 12 files changed, 968 insertions(+), 1424 deletions(-) create mode 100644 HDesign/src/assets/confirm.svg create mode 100644 HDesign/src/components/Toast/ToastProvider.stories.tsx create mode 100644 HDesign/src/components/Toast/ToastProvider.tsx delete mode 100644 HDesign/src/components/Toast/useToast.ts diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 916bd1ae5..58d306b1a 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -2202,6 +2202,15 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", @@ -2324,772 +2333,613 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, - "node_modules/@esbuild/aix-ppc64": { + "node_modules/@esbuild/darwin-arm64": { "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, "optional": true, "os": [ - "aix" + "darwin" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", - "cpu": [ - "arm" - ], + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/compat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", + "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", "dev": true, - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=18" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", - "cpu": [ - "arm" - ], + "node_modules/@eslint/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", - "cpu": [ - "ia32" - ], + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=18" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", - "cpu": [ - "loong64" - ], + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", - "cpu": [ - "mips64el" - ], + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=18" + "node": "*" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", - "cpu": [ - "ppc64" - ], + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", - "cpu": [ - "riscv64" - ], + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", - "cpu": [ - "s390x" - ], + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", - "cpu": [ - "x64" - ], + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", "dev": true, - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=18" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", - "cpu": [ - "x64" - ], + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { - "node": ">=18" + "node": ">=6.0.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", - "cpu": [ - "arm64" - ], + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, - "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "@types/mdx": "^2.0.0" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "@types/react": ">=16", + "react": ">=16" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">= 8" } }, - "node_modules/@eslint/compat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", - "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 8" } }, - "node_modules/@eslint/config-array": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", - "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">= 8" } }, - "node_modules/@eslint/config-array/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, - "dependencies": { - "ms": "2.1.2" - }, "engines": { - "node": ">=6.0" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/unts" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "node_modules/@remix-run/router": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", + "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", "engines": { - "node": "*" + "node": ">=14.0.0" } }, - "node_modules/@eslint/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@storybook/addon-actions": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.2.tgz", + "integrity": "sha512-SN4cSRt3f0qXi5te+yhMseSdQuZntA8lGlASbRmN77YQTpIaGsNiH88xFoky0s9qz531hiRfU1R0ZSMylBwSKw==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" } }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.2.tgz", + "integrity": "sha512-m/xJe7uKL+kfJx7pQcHwAeIvJ3tdLIpDGrMAVDNDJHcAxfe44cFjIInaV/1HKf3y5Awap+DZFW66ekkxuI9zzA==", "dev": true, "dependencies": { - "ms": "2.1.2" + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" }, - "engines": { - "node": ">=6.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "peerDependencies": { + "storybook": "^8.2.2" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/@storybook/addon-controls": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.2.tgz", + "integrity": "sha512-y241aOANGzT5XBADUIvALwG/xF5eC6UItzmWJaFvOzSBCq74GIA0+Hu9atyFdvFQbXOrdvPWC4jR+9iuBFRxAA==", "dev": true, - "engines": { - "node": ">=18" + "dependencies": { + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@storybook/addon-docs": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.2.tgz", + "integrity": "sha512-qk/yjAR9RpsSrKLLbeCgb6u58c8TmYqyJSnXgbAozZZNKHBWlIpvZ/hTNYud8qo0coPlxnLdjnZf32TykWGlAg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/core": "^7.24.4", + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.2.2", + "@storybook/csf-plugin": "8.2.2", + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.2", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "fs-extra": "^11.1.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", + "ts-dedent": "^2.0.0" }, - "engines": { - "node": "*" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" } }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", - "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "node_modules/@storybook/addon-docs/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=14.14" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "node_modules/@storybook/addon-essentials": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.2.tgz", + "integrity": "sha512-yN//BFMbSvNV0+Sll2hcKmgJX06TUKQDm6pZimUjkXczFtOmK7K/UdDmKjWS+qjhfJdWpxdRoEpxoHvvRmNfsA==", "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "dependencies": { + "@storybook/addon-actions": "8.2.2", + "@storybook/addon-backgrounds": "8.2.2", + "@storybook/addon-controls": "8.2.2", + "@storybook/addon-docs": "8.2.2", + "@storybook/addon-highlight": "8.2.2", + "@storybook/addon-measure": "8.2.2", + "@storybook/addon-outline": "8.2.2", + "@storybook/addon-toolbars": "8.2.2", + "@storybook/addon-viewport": "8.2.2", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@storybook/addon-highlight": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.2.tgz", + "integrity": "sha512-yDTRzzL+IJAymgY32xoZl09BGBVmPOUV2wVNGYcZkkBLvz2GSQMTfUe1/7F4jAx//+rFBu48/MQzsTC7Bk8kPw==", "dev": true, - "engines": { - "node": ">=12.22" + "dependencies": { + "@storybook/global": "^5.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "node_modules/@storybook/addon-interactions": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.2.tgz", + "integrity": "sha512-zRRuUwm/l41JtTUgjIoQTUgLT99Hsdz9cqKca/8NYo1MGBdEcKE41DH4aBIzKaOKFu7p9q00/o/X1EqYX4LMUA==", "dev": true, - "engines": { - "node": ">=18.18" + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.2.2", + "@storybook/test": "8.2.2", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@storybook/addon-links": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.2.tgz", + "integrity": "sha512-eGh7O7SgTJMtnuXC0HlRPOegu1njcJS2cnVqjbzjvjxsPSBhbHpdYMi9Q9E7al/FKuqMUOjIR9YLIlmK1AJaqA==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@storybook/addon-measure": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.2.tgz", + "integrity": "sha512-3rCo/aMltt5FrBVdr2dYlD8HlE2q9TLKGJZnwh9on4QyL6ArHbdYw0LmyHe/LrFahJ49w1XQZBMSJcAdRkkS7w==", + "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", - "dev": true, - "dependencies": { - "@types/mdx": "^2.0.0" + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@remix-run/router": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", - "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "storybook": "^8.2.2" } }, - "node_modules/@storybook/addon-actions": { + "node_modules/@storybook/addon-onboarding": { "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.2.tgz", - "integrity": "sha512-SN4cSRt3f0qXi5te+yhMseSdQuZntA8lGlASbRmN77YQTpIaGsNiH88xFoky0s9qz531hiRfU1R0ZSMylBwSKw==", + "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.2.tgz", + "integrity": "sha512-dCdE8Mt/JW6cq6dY7co35Sul/bAkUT3ixaxBrUagFUYUQ/PTYM6p4/B+45RURD5S9z8LVHH1rVgmEeScm3U78w==", "dev": true, "dependencies": { - "@storybook/global": "^5.0.0", - "@types/uuid": "^9.0.1", - "dequal": "^2.0.2", - "polished": "^4.2.2", - "uuid": "^9.0.0" + "react-confetti": "^6.1.0" }, "funding": { "type": "opencollective", @@ -3099,27 +2949,13 @@ "storybook": "^8.2.2" } }, - "node_modules/@storybook/addon-actions/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@storybook/addon-backgrounds": { + "node_modules/@storybook/addon-outline": { "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.2.tgz", - "integrity": "sha512-m/xJe7uKL+kfJx7pQcHwAeIvJ3tdLIpDGrMAVDNDJHcAxfe44cFjIInaV/1HKf3y5Awap+DZFW66ekkxuI9zzA==", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.2.tgz", + "integrity": "sha512-Y+PQtfTNO8GLX5nz+3x5AMfHNvdGvBXazJ29+Rl1ygYN1+Q9ZhRJDE1kAK0wLxb7CG14peAgdYEaQb3Rduv7HQ==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0", - "memoizerific": "^1.11.3", "ts-dedent": "^2.0.0" }, "funding": { @@ -3130,16 +2966,11 @@ "storybook": "^8.2.2" } }, - "node_modules/@storybook/addon-controls": { + "node_modules/@storybook/addon-toolbars": { "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.2.tgz", - "integrity": "sha512-y241aOANGzT5XBADUIvALwG/xF5eC6UItzmWJaFvOzSBCq74GIA0+Hu9atyFdvFQbXOrdvPWC4jR+9iuBFRxAA==", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.2.tgz", + "integrity": "sha512-JGOueOc3EPljlCl9dVSQee0aMYoqGNvN0UH+R6wYJ3bDZ+tUG/iYpsZVPUOvS8vzp3Imk5Is1kzQbQYJtzdGLg==", "dev": true, - "dependencies": { - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "ts-dedent": "^2.0.0" - }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" @@ -3148,25 +2979,13 @@ "storybook": "^8.2.2" } }, - "node_modules/@storybook/addon-docs": { + "node_modules/@storybook/addon-viewport": { "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.2.tgz", - "integrity": "sha512-qk/yjAR9RpsSrKLLbeCgb6u58c8TmYqyJSnXgbAozZZNKHBWlIpvZ/hTNYud8qo0coPlxnLdjnZf32TykWGlAg==", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.2.tgz", + "integrity": "sha512-gkZ8bsjGGP0NuevkT2iKC+szezSy+w4BrBDknf490mRU2K/B2e7TGojf/j/AtxzILMzD4IKzKUXbE/zwcqjZvA==", "dev": true, "dependencies": { - "@babel/core": "^7.24.4", - "@mdx-js/react": "^3.0.0", - "@storybook/blocks": "8.2.2", - "@storybook/csf-plugin": "8.2.2", - "@storybook/global": "^5.0.0", - "@storybook/react-dom-shim": "8.2.2", - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "fs-extra": "^11.1.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "rehype-external-links": "^3.0.0", - "rehype-slug": "^6.0.0", - "ts-dedent": "^2.0.0" + "memoizerific": "^1.11.3" }, "funding": { "type": "opencollective", @@ -3176,239 +2995,61 @@ "storybook": "^8.2.2" } }, - "node_modules/@storybook/addon-docs/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" }, "engines": { - "node": ">=14.14" + "node": ">=18" } }, - "node_modules/@storybook/addon-essentials": { + "node_modules/@storybook/blocks": { "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.2.tgz", - "integrity": "sha512-yN//BFMbSvNV0+Sll2hcKmgJX06TUKQDm6pZimUjkXczFtOmK7K/UdDmKjWS+qjhfJdWpxdRoEpxoHvvRmNfsA==", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.2.tgz", + "integrity": "sha512-av0Tryg4toDl2L/d1ABErtsAk9wvM1su6+M4wq5/Go50sk5IjGTldhbZFa9zNOohxLkZwaj0Q5xAgJ1Y+m5KrQ==", "dev": true, "dependencies": { - "@storybook/addon-actions": "8.2.2", - "@storybook/addon-backgrounds": "8.2.2", - "@storybook/addon-controls": "8.2.2", - "@storybook/addon-docs": "8.2.2", - "@storybook/addon-highlight": "8.2.2", - "@storybook/addon-measure": "8.2.2", - "@storybook/addon-outline": "8.2.2", - "@storybook/addon-toolbars": "8.2.2", - "@storybook/addon-viewport": "8.2.2", - "ts-dedent": "^2.0.0" + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.4.5", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" }, "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } } }, - "node_modules/@storybook/addon-highlight": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.2.tgz", - "integrity": "sha512-yDTRzzL+IJAymgY32xoZl09BGBVmPOUV2wVNGYcZkkBLvz2GSQMTfUe1/7F4jAx//+rFBu48/MQzsTC7Bk8kPw==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-interactions": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.2.tgz", - "integrity": "sha512-zRRuUwm/l41JtTUgjIoQTUgLT99Hsdz9cqKca/8NYo1MGBdEcKE41DH4aBIzKaOKFu7p9q00/o/X1EqYX4LMUA==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@storybook/instrumenter": "8.2.2", - "@storybook/test": "8.2.2", - "polished": "^4.2.2", - "ts-dedent": "^2.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-links": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.2.tgz", - "integrity": "sha512-eGh7O7SgTJMtnuXC0HlRPOegu1njcJS2cnVqjbzjvjxsPSBhbHpdYMi9Q9E7al/FKuqMUOjIR9YLIlmK1AJaqA==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@storybook/global": "^5.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-measure": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.2.tgz", - "integrity": "sha512-3rCo/aMltt5FrBVdr2dYlD8HlE2q9TLKGJZnwh9on4QyL6ArHbdYw0LmyHe/LrFahJ49w1XQZBMSJcAdRkkS7w==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "tiny-invariant": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-onboarding": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.2.tgz", - "integrity": "sha512-dCdE8Mt/JW6cq6dY7co35Sul/bAkUT3ixaxBrUagFUYUQ/PTYM6p4/B+45RURD5S9z8LVHH1rVgmEeScm3U78w==", - "dev": true, - "dependencies": { - "react-confetti": "^6.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-outline": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.2.tgz", - "integrity": "sha512-Y+PQtfTNO8GLX5nz+3x5AMfHNvdGvBXazJ29+Rl1ygYN1+Q9ZhRJDE1kAK0wLxb7CG14peAgdYEaQb3Rduv7HQ==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-toolbars": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.2.tgz", - "integrity": "sha512-JGOueOc3EPljlCl9dVSQee0aMYoqGNvN0UH+R6wYJ3bDZ+tUG/iYpsZVPUOvS8vzp3Imk5Is1kzQbQYJtzdGLg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-viewport": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.2.tgz", - "integrity": "sha512-gkZ8bsjGGP0NuevkT2iKC+szezSy+w4BrBDknf490mRU2K/B2e7TGojf/j/AtxzILMzD4IKzKUXbE/zwcqjZvA==", - "dev": true, - "dependencies": { - "memoizerific": "^1.11.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-webpack5-compiler-swc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", - "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", - "dependencies": { - "@swc/core": "^1.7.3", - "swc-loader": "^0.2.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@storybook/blocks": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.2.tgz", - "integrity": "sha512-av0Tryg4toDl2L/d1ABErtsAk9wvM1su6+M4wq5/Go50sk5IjGTldhbZFa9zNOohxLkZwaj0Q5xAgJ1Y+m5KrQ==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.2.5", - "@types/lodash": "^4.14.167", - "color-convert": "^2.0.1", - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "markdown-to-jsx": "^7.4.5", - "memoizerific": "^1.11.3", - "polished": "^4.2.2", - "react-colorful": "^5.1.2", - "telejson": "^7.2.0", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack5": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.3.tgz", - "integrity": "sha512-yU9rtcVpo12vD8m/nbdepyJ09K937ZnSsrvIM9XfzbxXA/+p4Cov9Rjg1VfoWyRd1ApxaztSktQlawBlb6bKEA==", + "node_modules/@storybook/builder-webpack5": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.3.tgz", + "integrity": "sha512-yU9rtcVpo12vD8m/nbdepyJ09K937ZnSsrvIM9XfzbxXA/+p4Cov9Rjg1VfoWyRd1ApxaztSktQlawBlb6bKEA==", "dev": true, "dependencies": { "@storybook/core-webpack": "8.2.3", @@ -3732,403 +3373,51 @@ "express": "^4.19.2", "process": "^0.11.10", "recast": "^0.23.5", - "util": "^0.12.4", - "ws": "^8.2.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-webpack": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", - "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", - "dev": true, - "dependencies": { - "@types/node": "^18.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.3" - } - }, - "node_modules/@storybook/core-webpack/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" + "util": "^0.12.4", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/core/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], + "node_modules/@storybook/core-webpack": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", + "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@types/node": "^18.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.3" } }, - "node_modules/@storybook/core/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], + "node_modules/@storybook/core-webpack/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "dependencies": { + "undici-types": "~5.26.4" } }, - "node_modules/@storybook/core/node_modules/@esbuild/win32-x64": { + "node_modules/@storybook/core/node_modules/@esbuild/darwin-arm64": { "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ - "win32" + "darwin" ], "engines": { "node": ">=12" @@ -4875,141 +4164,6 @@ "node": ">=10" } }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.3.tgz", - "integrity": "sha512-mun623y6rCoZ2EFIYfIRqXYRFufJOopoYSJcxYhZUrfTpAvQ1zLngjQpWCUU1krggXR2U0PQj+ls0DfXUTraNg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.3.tgz", - "integrity": "sha512-4Jz4UcIcvZNMp9qoHbBx35bo3rjt8hpYLPqnR4FFq6gkAsJIMFC56UhRZwdEQoDuYiOFMBnnrsg31Fyo6YQypA==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.3.tgz", - "integrity": "sha512-p+U/M/oqV7HC4erQ5TVWHhJU1984QD+wQBPxslAYq751bOQGm0R/mXK42GjugqjnR6yYrAiwKKbpq4iWVXNePA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.3.tgz", - "integrity": "sha512-s6VzyaJwaRGTi2mz2h6Ywxfmgpkc69IxhuMzl+sl34plH0V0RgnZDm14HoCGIKIzRk4+a2EcBV1ZLAfWmPACQg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.3.tgz", - "integrity": "sha512-IrFY48C356Z2dU2pjYg080yvMXzmSV3Lmm/Wna4cfcB1nkVLjWsuYwwRAk9CY7E19c+q8N1sMNggubAUDYoX2g==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.3.tgz", - "integrity": "sha512-qoLgxBlBnnyUEDu5vmRQqX90h9jldU1JXI96e6eh2d1gJyKRA0oSK7xXmTzorv1fGHiHulv9qiJOUG+g6uzJWg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.3.tgz", - "integrity": "sha512-OAd7jVVJ7nb0Ev80VAa1aeK+FldPeC4eZ35H4Qn6EICzIz0iqJo2T33qLKkSZiZEBKSoF4KcwrqYfkjLOp5qWg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.3.tgz", - "integrity": "sha512-31+Le1NyfSnILFV9+AhxfFOG0DK0272MNhbIlbcv4w/iqpjkhaOnNQnLsYJD1Ow7lTX1MtIZzTjOhRlzSviRWg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.3.tgz", - "integrity": "sha512-jVQPbYrwcuueI4QB0fHC29SVrkFOBcfIspYDlgSoHnEz6tmLMqUy+txZUypY/ZH/KaK0HEY74JkzgbRC1S6LFQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -6040,6 +5194,50 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -9018,6 +8216,15 @@ "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", "dev": true }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -9155,6 +8362,15 @@ "node": ">=8" } }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -9885,6 +9101,25 @@ "node": ">=4" } }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -9934,6 +9169,15 @@ "node": ">= 0.4" } }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/is-absolute-url": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", @@ -12275,6 +11519,18 @@ "node": ">= 4" } }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -12494,6 +11750,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -14341,6 +13618,60 @@ } } }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/webpack-hot-middleware": { "version": "2.26.1", "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", @@ -14352,6 +13683,20 @@ "strip-ansi": "^6.0.0" } }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", @@ -14467,6 +13812,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/HDesign/src/assets/confirm.svg b/HDesign/src/assets/confirm.svg new file mode 100644 index 000000000..7e017c7b1 --- /dev/null +++ b/HDesign/src/assets/confirm.svg @@ -0,0 +1,10 @@ +<svg width="26" height="26" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> + <g transform="translate(2, 2)"> + <path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C11.3132 20 12.6136 19.7413 13.8268 19.2388C15.0401 18.7362 16.1425 17.9997 17.0711 17.0711C17.9997 16.1425 18.7362 15.0401 19.2388 13.8268C19.7413 12.6136 20 11.3132 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 -1.95685e-08 10 0C7.34784 3.95203e-08 4.8043 1.05357 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C4.8043 18.9464 7.34784 20 10 20ZM15.2978 7.37778C15.3953 7.26627 15.4696 7.13638 15.5162 6.99574C15.5628 6.85511 15.5808 6.70657 15.5692 6.55887C15.5575 6.41117 15.5165 6.26729 15.4484 6.1357C15.3804 6.0041 15.2866 5.88745 15.1728 5.7926C15.059 5.69775 14.9274 5.62663 14.7857 5.5834C14.644 5.54018 14.495 5.52574 14.3476 5.54092C14.2003 5.5561 14.0574 5.60061 13.9275 5.67181C13.7976 5.74302 13.6832 5.83949 13.5911 5.95556L9.59333 10.7522C9.20778 11.2144 8.99111 11.4711 8.81889 11.6278L8.81222 11.6344L8.80444 11.6289C8.61778 11.4878 8.37889 11.2522 7.95445 10.8267L6.34111 9.21445C6.13155 9.01205 5.85088 8.90005 5.55956 8.90259C5.26823 8.90512 4.98954 9.02197 4.78354 9.22798C4.57753 9.43399 4.46067 9.71267 4.45814 10.004C4.45561 10.2953 4.5676 10.576 4.77 10.7856L6.38222 12.3978L6.42778 12.4433C6.79111 12.8067 7.13889 13.1556 7.46445 13.4011C7.82778 13.6767 8.30444 13.9344 8.91444 13.9078C9.52556 13.88 9.97667 13.5789 10.3144 13.2722C10.6144 12.9978 10.9311 12.6189 11.2589 12.2244L11.3 12.1756L15.2978 7.37778Z" fill="#BFFF75"/> + </g> + <defs> + <clipPath id="clip0_1042_1689"> + <rect width="24" height="24" rx="8" fill="white"/> + </clipPath> + </defs> +</svg> diff --git a/HDesign/src/assets/error.svg b/HDesign/src/assets/error.svg index 81d9689c5..0c4014ab7 100644 --- a/HDesign/src/assets/error.svg +++ b/HDesign/src/assets/error.svg @@ -1,3 +1,3 @@ -<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<svg width="26" height="26" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M13 13H11V7H13M13 17H11V15H13M12 2C10.6868 2 9.38642 2.25866 8.17317 2.7612C6.95991 3.26375 5.85752 4.00035 4.92893 4.92893C3.05357 6.8043 2 9.34784 2 12C2 14.6522 3.05357 17.1957 4.92893 19.0711C5.85752 19.9997 6.95991 20.7362 8.17317 21.2388C9.38642 21.7413 10.6868 22 12 22C14.6522 22 17.1957 20.9464 19.0711 19.0711C20.9464 17.1957 22 14.6522 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7362 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2Z" fill="#ECFF59"/> </svg> diff --git a/HDesign/src/components/Button/Button.style.ts b/HDesign/src/components/Button/Button.style.ts index 2862e9538..8ebec30c9 100644 --- a/HDesign/src/components/Button/Button.style.ts +++ b/HDesign/src/components/Button/Button.style.ts @@ -17,6 +17,7 @@ const getButtonDefaultStyle = (theme: Theme) => display: 'flex', justifyContent: 'center', lineHeight: '1', + whiteSpace: 'nowrap', '&:disabled': { backgroundColor: theme.colors.tertiary, diff --git a/HDesign/src/components/Toast/Toast.stories.tsx b/HDesign/src/components/Toast/Toast.stories.tsx index 35789224a..fd672959c 100644 --- a/HDesign/src/components/Toast/Toast.stories.tsx +++ b/HDesign/src/components/Toast/Toast.stories.tsx @@ -11,11 +11,12 @@ const meta = { // layout: 'centered', }, args: { - top: 80, + type: 'confirm', + position: 'top', + top: '80px', message: `서버 오류로 인해 인원을 설정하는데 실패했어요. 두글자면 이렇게 보여요.`, - showingTime: 1000, - alwaysShow: false, + onUndo: () => alert('되돌리기 버튼이 눌렸습니다. 실행할 로직을 전달해주세요'), }, } satisfies Meta<typeof Toast>; @@ -23,4 +24,48 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Playground: Story = {}; +export const ConfirmToast: Story = { + args: { + ...meta.args, + type: 'confirm', + top: '80px', + message: `이 첫번째 토스트 그림자 짙은거 두 개 떠서 그런거임 css 잘못한거 아닙니다. 잘못 없습니다. 스토리북이 잘못한거에요. 저희는 최선을 다했어요.. `, + }, +}; + +export const ConfirmToastWithoutUndo: Story = { + args: { + ...meta.args, + onUndo: undefined, + top: '160px', + }, +}; + +export const ErrorToast: Story = { + args: { + ...meta.args, + top: '240px', + type: 'error', + message: `님 이거 다 작성했는데, 혹시 되돌림? + 되돌릴 수도 있음 ㅇㅇ 굿`, + }, +}; + +export const ErrorToastWithoutUndo: Story = { + args: { + ...meta.args, + top: '320px', + onUndo: undefined, + type: 'error', + }, +}; + +export const NoneToast: Story = { + args: { + ...meta.args, + top: '400px', + onUndo: undefined, + type: 'none', + message: '웨디는 커비의 먹잇감인가요? 그치만 감자는 웨디한테 먹힘 쿠스쿠스 ㅋ', + }, +}; diff --git a/HDesign/src/components/Toast/Toast.style.ts b/HDesign/src/components/Toast/Toast.style.ts index ac0597675..64755d52a 100644 --- a/HDesign/src/components/Toast/Toast.style.ts +++ b/HDesign/src/components/Toast/Toast.style.ts @@ -2,20 +2,31 @@ import {css} from '@emotion/react'; import {Theme} from '@/theme/theme.type'; -export const toastStyle = (top: number, isShow: boolean, theme: Theme) => - css({ - display: isShow ? 'flex' : 'none', - alignItems: 'center', +import {ToastPosition} from './Toast.type'; + +type ToastMarginStyle = { + position?: ToastPosition; + bottom?: string; + top?: string; +}; +export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => + css({ position: 'absolute', - top: `${top}%`, - left: 0, - gap: '0.5rem', + bottom: position === 'bottom' ? `${bottom}` : 'auto', + top: position === 'top' ? `${top}` : 'auto', + left: '50%', + transform: 'translate(-50%)', + width: '100%', maxWidth: '48rem', + paddingInline: '0.5rem', + }); + +export const toastStyle = (theme: Theme) => + css({ width: '100%', - margin: '1.25rem', - padding: '0.625rem', + padding: '0.625rem 1rem', backgroundColor: theme.colors.gray, boxShadow: '0 8px 12px rgba(0, 0, 0, 0.16);', diff --git a/HDesign/src/components/Toast/Toast.tsx b/HDesign/src/components/Toast/Toast.tsx index b8a921d34..47d60c8dc 100644 --- a/HDesign/src/components/Toast/Toast.tsx +++ b/HDesign/src/components/Toast/Toast.tsx @@ -2,26 +2,71 @@ import {createPortal} from 'react-dom'; import Text from '@components/Text/Text'; +import Flex from '@components/Flex/Flex'; import ErrorIcon from '@assets/error.svg'; +import ConfirmIcon from '@assets/confirm.svg'; import {useTheme} from '@theme/HDesignProvider'; -import {toastStyle, textStyle} from './Toast.style'; -import {ToastProps} from './Toast.type'; -import useToast from './useToast'; +import Button from '../Button/Button'; -const Toast: React.FC<ToastProps> = ({top = 80, message, showingTime, alwaysShow}) => { +import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; +import {ToastProps, ToastType} from './Toast.type'; + +const renderIcon = (type: ToastType) => { + switch (type) { + case 'error': + return <ErrorIcon />; + + case 'confirm': + return <ConfirmIcon />; + + case 'none': + return null; + + default: + return null; + } +}; + +const Toast = ({ + type = 'confirm', + top = '0px', + bottom = '0px', + isClickToClose = true, + position = 'bottom', + message, + onUndo, + onClose, + ...htmlProps +}: ToastProps) => { const {theme} = useTheme(); - const {isShow} = useToast({message, showingTime, alwaysShow}); + const styleProps = {position, top, bottom}; + + const handleClickToClose = () => { + if (!isClickToClose || !onClose) return; + + onClose(); + }; return createPortal( - // TODO: (@cookie) toast를 위한 시멘틱 태그 알아보기 - <div css={toastStyle(top, isShow, theme)}> - <ErrorIcon /> - <Text size="smallBodyBold" css={textStyle(theme)}> - {message} - </Text> + <div css={toastMarginStyle({...styleProps})} {...htmlProps} onClick={handleClickToClose}> + <div css={toastStyle(theme)}> + <Flex justifyContent="spaceBetween" alignItems="center"> + <Flex alignItems="center" gap="0.5rem"> + {renderIcon(type)} + <Text size="smallBodyBold" css={textStyle(theme)}> + {message} + </Text> + </Flex> + {onUndo && ( + <Button variants="tertiary" size="small" onClick={onUndo}> + 되돌리기 + </Button> + )} + </Flex> + </div> </div>, document.body, ); diff --git a/HDesign/src/components/Toast/Toast.type.ts b/HDesign/src/components/Toast/Toast.type.ts index 4e3a13ea8..12a436c2d 100644 --- a/HDesign/src/components/Toast/Toast.type.ts +++ b/HDesign/src/components/Toast/Toast.type.ts @@ -1,16 +1,21 @@ +export type ToastPosition = 'bottom' | 'top'; +export type ToastType = 'error' | 'confirm' | 'none'; + export interface ToastStyleProps { - top?: number; + bottom?: string; + top?: string; } -export interface ToastCustomProps { - showingTime?: number; - alwaysShow?: boolean; +export interface ToastOptionProps { + position?: ToastPosition; + type?: ToastType; + onUndo?: () => void; + isClickToClose?: boolean; + onClose?: () => void; } export interface ToastRequiredProps { message: string; } -export type ToastOptionProps = ToastStyleProps & ToastCustomProps; - -export type ToastProps = React.ComponentProps<'aside'> & ToastOptionProps & ToastRequiredProps; +export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; diff --git a/HDesign/src/components/Toast/ToastProvider.stories.tsx b/HDesign/src/components/Toast/ToastProvider.stories.tsx new file mode 100644 index 000000000..32c8c6917 --- /dev/null +++ b/HDesign/src/components/Toast/ToastProvider.stories.tsx @@ -0,0 +1,46 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Button from '../Button/Button'; + +import {ToastProvider, useToast} from './ToastProvider'; + +const meta = { + title: 'Components/ToastProvider', + component: ToastProvider, + tags: ['autodocs'], + decorators: [ + Story => ( + <ToastProvider> + <Story /> + </ToastProvider> + ), + ], +} satisfies Meta<typeof ToastProvider>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + decorators: [ + () => { + const {showToast} = useToast(); + + return ( + <Button + onClick={() => + showToast({ + isAlwaysOn: true, + message: '이거자냥 (feat. 쿠키)', + type: 'confirm', + position: 'top', + }) + } + > + 토스트 열기 + </Button> + ); + }, + ], +}; diff --git a/HDesign/src/components/Toast/ToastProvider.tsx b/HDesign/src/components/Toast/ToastProvider.tsx new file mode 100644 index 000000000..9201fdc6d --- /dev/null +++ b/HDesign/src/components/Toast/ToastProvider.tsx @@ -0,0 +1,59 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, useCallback, useContext, useEffect, useState} from 'react'; + +import {ToastProps} from './Toast.type'; +import Toast from './Toast'; + +export const ToastContext = createContext<ToastContextProps | null>(null); + +interface ToastContextProps { + showToast: (args: ShowToast) => void; +} + +type ShowToast = ToastProps & { + showingTime?: number; + isAlwaysOn?: boolean; +}; + +const ToastProvider = ({children}: React.PropsWithChildren) => { + const [currentToast, setCurrentToast] = useState<ShowToast | null>(null); + + const showToast = useCallback(({showingTime = 3000, isAlwaysOn = false, ...toastProps}: ShowToast) => { + setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); + }, []); + + const closeToast = () => { + setCurrentToast(null); + }; + + useEffect(() => { + if (!currentToast) return; + + if (!currentToast.isAlwaysOn) { + const timer = setTimeout(() => { + setCurrentToast(null); + }, currentToast.showingTime); + + return () => clearTimeout(timer); + } + }, [currentToast]); + + return ( + <ToastContext.Provider value={{showToast}}> + {currentToast && <Toast onClose={closeToast} {...currentToast} />} + {children} + </ToastContext.Provider> + ); +}; + +const useToast = () => { + const context = useContext(ToastContext); + + if (!context) { + throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); + } + + return context; +}; + +export {ToastProvider, useToast}; diff --git a/HDesign/src/components/Toast/useToast.ts b/HDesign/src/components/Toast/useToast.ts deleted file mode 100644 index 570f5b5a9..000000000 --- a/HDesign/src/components/Toast/useToast.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {useState, useEffect} from 'react'; - -interface UseToastProps { - message: string; - showingTime?: number; - alwaysShow?: boolean; -} - -const useToast = ({message, showingTime = 3000, alwaysShow = false}: UseToastProps) => { - const [isShow, setIsShow] = useState(false); - - const showToast = () => { - setIsShow(true); - }; - - const untilShowingTimeAndDisappear = () => { - setTimeout(() => { - setIsShow(false); - }, showingTime); - }; - - useEffect(() => { - showToast(); - if (!alwaysShow) { - untilShowingTimeAndDisappear(); - } - }, [message]); - - return { - isShow, - }; -}; - -export default useToast; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index 9cac56e5d..f75b5f640 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -16,6 +16,8 @@ import Text from '@components/Text/Text'; import TextButton from '@components/TextButton/TextButton'; import Title from '@components/Title/Title'; import TopNav from '@components/TopNav/TopNav'; +import Toast from '@components/Toast/Toast'; +import {ToastProvider, useToast} from '@components/Toast/ToastProvider'; import {MainLayout} from '@layouts/MainLayout'; import {ContentLayout} from '@layouts/ContentLayout'; @@ -49,4 +51,7 @@ export { MainLayout, ContentLayout, HDesignProvider, + ToastProvider, + useToast, + Toast, }; From 8a1ffbb2034d8771027f7683a15d10b326cf586a Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:08:33 +0900 Subject: [PATCH 110/273] =?UTF-8?q?fix:=20client=20=EB=94=94=EB=A0=89?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20reset,=20=EC=A0=84=EC=97=AD=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20GlobalStyle=EC=9D=84=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B2=83=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#173)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: css를 global style로 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * refactor: global style app과 index에 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> --------- Co-authored-by: Pakxe <pakxe@users.noreply.github.com> --- client/package-lock.json | 1030 ++++++++++++++++++------------------- client/package.json | 4 +- client/src/App.tsx | 6 +- client/src/GlobalStyle.ts | 157 ++++++ client/src/index.css | 20 - client/src/index.tsx | 2 - client/src/reset.css | 136 ----- client/webpack.config.js | 4 - 8 files changed, 673 insertions(+), 686 deletions(-) create mode 100644 client/src/GlobalStyle.ts delete mode 100644 client/src/index.css delete mode 100644 client/src/reset.css diff --git a/client/package-lock.json b/client/package-lock.json index 91269318a..e1cd34770 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -25,7 +25,6 @@ "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", - "css-loader": "^7.1.2", "dotenv": "^16.4.5", "eslint": "^9.6.0", "eslint-import-resolver-typescript": "^3.6.1", @@ -40,7 +39,6 @@ "html-webpack-plugin": "^5.6.0", "modify-source-webpack-plugin": "^4.1.0", "prettier": "3.3.2", - "style-loader": "^4.0.0", "ts-loader": "^9.5.1", "typescript": "^5.5.3", "typescript-eslint": "^7.16.0", @@ -78,28 +76,28 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", - "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", - "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.9", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-module-transforms": "^7.24.9", - "@babel/helpers": "^7.24.8", - "@babel/parser": "^7.24.8", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.9", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -120,11 +118,11 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/@babel/generator": { - "version": "7.24.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", - "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", "dependencies": { - "@babel/types": "^7.24.9", + "@babel/types": "^7.25.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -157,11 +155,11 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", - "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", "dependencies": { - "@babel/compat-data": "^7.24.8", + "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", "browserslist": "^4.23.1", "lru-cache": "^5.1.1", @@ -172,18 +170,16 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", - "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", + "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.8", "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/traverse": "^7.25.0", "semver": "^6.3.1" }, "engines": { @@ -194,9 +190,9 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", - "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", @@ -224,40 +220,6 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", @@ -283,15 +245,14 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", - "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -320,13 +281,13 @@ } }, "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", - "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-wrap-function": "^7.24.7" + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -336,13 +297,13 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -375,17 +336,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", @@ -411,26 +361,25 @@ } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", - "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", "dependencies": { - "@babel/helper-function-name": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", - "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.8" + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -451,9 +400,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz", + "integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -462,12 +411,26 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", - "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.0.tgz", + "integrity": "sha512-dG0aApncVQwAUJa8tP1VHTnmU67BeIQvKafd3raEx315H54FfkZSz3B/TT+33ZQAjatGJA79gZqTtqL5QZUKXw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -477,11 +440,11 @@ } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", - "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -507,12 +470,12 @@ } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", - "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -792,14 +755,14 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", - "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", + "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7", - "@babel/plugin-syntax-async-generators": "^7.8.4" + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -839,11 +802,11 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", - "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -884,17 +847,15 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", - "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", + "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.0", "globals": "^11.1.0" }, "engines": { @@ -970,6 +931,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", @@ -1031,13 +1007,13 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", - "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" }, "engines": { "node": ">=6.9.0" @@ -1062,11 +1038,11 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", - "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1136,14 +1112,14 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", - "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", "dependencies": { - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" }, "engines": { "node": ">=6.9.0" @@ -1350,11 +1326,11 @@ } }, "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", - "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", + "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -1378,15 +1354,15 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", - "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/types": "^7.25.2" }, "engines": { "node": ">=6.9.0" @@ -1525,13 +1501,14 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", - "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.8", + "@babel/helper-create-class-features-plugin": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", "@babel/plugin-syntax-typescript": "^7.24.7" }, "engines": { @@ -1601,18 +1578,19 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", - "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.2.tgz", + "integrity": "sha512-Y2Vkwy3ITW4id9c6KXshVV/x5yCGK7VdJmKkzOzNsDZMojRKfSA/033rRbLqlRozmhRXCejxWHLSJOg/wUHfzw==", "dependencies": { - "@babel/compat-data": "^7.24.8", - "@babel/helper-compilation-targets": "^7.24.8", + "@babel/compat-data": "^7.25.2", + "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.0", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", @@ -1633,29 +1611,30 @@ "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.0", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.24.8", + "@babel/plugin-transform-classes": "^7.25.0", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-dotall-regex": "^7.24.7", "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", "@babel/plugin-transform-dynamic-import": "^7.24.7", "@babel/plugin-transform-exponentiation-operator": "^7.24.7", "@babel/plugin-transform-export-namespace-from": "^7.24.7", "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-member-expression-literals": "^7.24.7", "@babel/plugin-transform-modules-amd": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", "@babel/plugin-transform-modules-umd": "^7.24.7", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-new-target": "^7.24.7", @@ -1750,9 +1729,9 @@ "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" }, "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -1761,31 +1740,28 @@ } }, "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", - "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.2.tgz", + "integrity": "sha512-s4/r+a7xTnny2O6FcZzqgT6nE4/GHEdcqj4qAeglbUOh0TeglEfmNJFAd/OLoVtGd6ZhAO8GCVvCNUO5t/VJVQ==", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.8", - "@babel/types": "^7.24.8", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -1802,9 +1778,9 @@ } }, "node_modules/@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", @@ -1842,9 +1818,9 @@ } }, "node_modules/@emotion/cache": { - "version": "11.13.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.0.tgz", - "integrity": "sha512-hPV345J/tH0Cwk2wnU/3PBzORQ9HeX+kQSbwI+jslzpRCHE6fSGTohswksA/Ensr8znPzwfzKZCmAM9Lmlhp7g==", + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", @@ -2053,9 +2029,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.7.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", - "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2231,9 +2207,9 @@ } }, "node_modules/@jsonjoy.com/util": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.2.0.tgz", - "integrity": "sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", "dev": true, "engines": { "node": ">=10.0" @@ -2317,6 +2293,18 @@ "node": ">=14.0.0" } }, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "dependencies": { + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", @@ -2560,6 +2548,206 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@swc/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.3.tgz", + "integrity": "sha512-HHAlbXjWI6Kl9JmmUW1LSygT1YbblXgj2UvvDzMkTBPRzYMhW6xchxdO8HbtMPtFYRt/EQq9u1z7j4ttRSrFsA==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.3", + "@swc/core-darwin-x64": "1.7.3", + "@swc/core-linux-arm-gnueabihf": "1.7.3", + "@swc/core-linux-arm64-gnu": "1.7.3", + "@swc/core-linux-arm64-musl": "1.7.3", + "@swc/core-linux-x64-gnu": "1.7.3", + "@swc/core-linux-x64-musl": "1.7.3", + "@swc/core-win32-arm64-msvc": "1.7.3", + "@swc/core-win32-ia32-msvc": "1.7.3", + "@swc/core-win32-x64-msvc": "1.7.3" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.3.tgz", + "integrity": "sha512-CTkHa6MJdov9t41vuV2kmQIMu+Q19LrEHGIR/UiJYH06SC/sOu35ZZH8DyfLp9ZoaCn21gwgWd61ixOGQlwzTw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.3.tgz", + "integrity": "sha512-mun623y6rCoZ2EFIYfIRqXYRFufJOopoYSJcxYhZUrfTpAvQ1zLngjQpWCUU1krggXR2U0PQj+ls0DfXUTraNg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.3.tgz", + "integrity": "sha512-4Jz4UcIcvZNMp9qoHbBx35bo3rjt8hpYLPqnR4FFq6gkAsJIMFC56UhRZwdEQoDuYiOFMBnnrsg31Fyo6YQypA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.3.tgz", + "integrity": "sha512-p+U/M/oqV7HC4erQ5TVWHhJU1984QD+wQBPxslAYq751bOQGm0R/mXK42GjugqjnR6yYrAiwKKbpq4iWVXNePA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.3.tgz", + "integrity": "sha512-s6VzyaJwaRGTi2mz2h6Ywxfmgpkc69IxhuMzl+sl34plH0V0RgnZDm14HoCGIKIzRk4+a2EcBV1ZLAfWmPACQg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.3.tgz", + "integrity": "sha512-IrFY48C356Z2dU2pjYg080yvMXzmSV3Lmm/Wna4cfcB1nkVLjWsuYwwRAk9CY7E19c+q8N1sMNggubAUDYoX2g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.3.tgz", + "integrity": "sha512-qoLgxBlBnnyUEDu5vmRQqX90h9jldU1JXI96e6eh2d1gJyKRA0oSK7xXmTzorv1fGHiHulv9qiJOUG+g6uzJWg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.3.tgz", + "integrity": "sha512-OAd7jVVJ7nb0Ev80VAa1aeK+FldPeC4eZ35H4Qn6EICzIz0iqJo2T33qLKkSZiZEBKSoF4KcwrqYfkjLOp5qWg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.3.tgz", + "integrity": "sha512-31+Le1NyfSnILFV9+AhxfFOG0DK0272MNhbIlbcv4w/iqpjkhaOnNQnLsYJD1Ow7lTX1MtIZzTjOhRlzSviRWg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.3.tgz", + "integrity": "sha512-jVQPbYrwcuueI4QB0fHC29SVrkFOBcfIspYDlgSoHnEz6tmLMqUy+txZUypY/ZH/KaK0HEY74JkzgbRC1S6LFQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -2702,11 +2890,11 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", - "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.0.tgz", + "integrity": "sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.11.1" } }, "node_modules/@types/node-forge": { @@ -2806,25 +2994,25 @@ } }, "node_modules/@types/ws": { - "version": "8.5.11", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.11.tgz", - "integrity": "sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w==", + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", - "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/type-utils": "7.17.0", - "@typescript-eslint/utils": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -2848,15 +3036,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", - "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "engines": { @@ -2876,13 +3064,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", - "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0" + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2893,13 +3081,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", - "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -2920,9 +3108,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", - "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2933,13 +3121,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", - "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2973,15 +3161,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", - "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0" + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -2995,12 +3183,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", - "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3545,9 +3733,9 @@ } }, "node_modules/axe-core": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", - "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", "dev": true, "engines": { "node": ">=4" @@ -3853,9 +4041,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001643", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", - "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", + "version": "1.0.30001645", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001645.tgz", + "integrity": "sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw==", "funding": [ { "type": "opencollective", @@ -4163,53 +4351,6 @@ "node": ">= 8" } }, - "node_modules/css-loader": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", - "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.27.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-loader/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -4249,18 +4390,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -4354,9 +4483,9 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dependencies": { "ms": "2.1.2" }, @@ -4698,9 +4827,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz", - "integrity": "sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==" + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -4978,16 +5107,16 @@ } }, "node_modules/eslint": { - "version": "9.7.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.7.0.tgz", - "integrity": "sha512-FzJ9D/0nGiCGBf8UXO/IGLTgLVzIxze1zpfA8Ton2mjLovXdAPlYDv+MQDcqj3TmrhAGYfOpz9RfR+ent0AgAw==", + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.17.0", + "@eslint/config-array": "^0.17.1", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.7.0", + "@eslint/js": "9.8.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -6274,11 +6403,12 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.35", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.35.tgz", - "integrity": "sha512-JhlZgZXzYfCMV57glEOiI+YKGstGAAOhBOKGad6Mugio/vNVUmInf3/eJPEy/10SM9reizYsSCt7eoyj71ZaSA==", + "version": "0.1.45", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.45.tgz", + "integrity": "sha512-s3Xf7xRPWHfcFF4tiG470eHa1+iaBgLNrRKXaTYpmfJTO5vDV7g+zEboq0jno1zTrD0bS7QTPRE+4A5R9OlbDg==", "dependencies": { "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -6456,9 +6586,9 @@ ] }, "node_modules/html-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz", - "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.1.0.tgz", + "integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==", "dev": true, "dependencies": { "html-minifier-terser": "^7.2.0", @@ -6682,18 +6812,6 @@ "node": ">=0.10.0" } }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -7818,24 +7936,6 @@ "multicast-dns": "cli.js" } }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -8401,112 +8501,6 @@ "node": ">= 0.4" } }, - "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", - "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -9737,22 +9731,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/style-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", - "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", - "dev": true, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.27.0" - } - }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -9872,6 +9850,18 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, "node_modules/synckit": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", @@ -10284,14 +10274,14 @@ } }, "node_modules/typescript-eslint": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.17.0.tgz", - "integrity": "sha512-spQxsQvPguduCUfyUvLItvKqK3l8KJ/kqs5Pb/URtzQ5AC53Z6us32St37rpmlt2uESG23lOFpV4UErrmy4dZQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.18.0.tgz", + "integrity": "sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "7.17.0", - "@typescript-eslint/parser": "7.17.0", - "@typescript-eslint/utils": "7.17.0" + "@typescript-eslint/eslint-plugin": "7.18.0", + "@typescript-eslint/parser": "7.18.0", + "@typescript-eslint/utils": "7.18.0" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -10325,9 +10315,9 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz", + "integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -10635,13 +10625,13 @@ "dev": true }, "node_modules/webpack-dev-middleware/node_modules/memfs": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.9.3.tgz", - "integrity": "sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.0.tgz", + "integrity": "sha512-+6kz90/YQoZuHvg3rn1CGPMZfEMaU5xe7xIavZMNiom2RNesiI8S37p9O9n+PlIUnUgretjLdM6HnqpZYl3X2g==", "dev": true, "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.1.2", + "@jsonjoy.com/util": "^1.3.0", "tree-dump": "^1.0.1", "tslib": "^2.0.0" }, @@ -10881,13 +10871,13 @@ } }, "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", "dev": true, "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", @@ -10896,8 +10886,8 @@ "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" diff --git a/client/package.json b/client/package.json index cb8e9a714..804a122d6 100644 --- a/client/package.json +++ b/client/package.json @@ -20,7 +20,6 @@ "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", - "css-loader": "^7.1.2", "dotenv": "^16.4.5", "eslint": "^9.6.0", "eslint-import-resolver-typescript": "^3.6.1", @@ -35,7 +34,6 @@ "html-webpack-plugin": "^5.6.0", "modify-source-webpack-plugin": "^4.1.0", "prettier": "3.3.2", - "style-loader": "^4.0.0", "ts-loader": "^9.5.1", "typescript": "^5.5.3", "typescript-eslint": "^7.16.0", @@ -56,4 +54,4 @@ "npm": ">=10.7.0", "node": ">=20.15.1" } -} \ No newline at end of file +} diff --git a/client/src/App.tsx b/client/src/App.tsx index 46618d881..e09f98e8d 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,9 +1,13 @@ -import {HDesignProvider} from 'haengdong-design'; import {Outlet} from 'react-router-dom'; +import {HDesignProvider} from 'haengdong-design'; +import {Global} from '@emotion/react'; + +import {GlobalStyle} from './GlobalStyle'; const App: React.FC = () => { return ( <HDesignProvider> + <Global styles={GlobalStyle} /> <Outlet /> </HDesignProvider> ); diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts new file mode 100644 index 000000000..2df05e939 --- /dev/null +++ b/client/src/GlobalStyle.ts @@ -0,0 +1,157 @@ +import {css} from '@emotion/react'; + +// reset css -> index css +export const GlobalStyle = css` + html, + body, + div, + span, + applet, + object, + iframe, + h1, + h2, + h3, + h4, + h5, + h6, + p, + blockquote, + pre, + a, + abbr, + acronym, + address, + big, + cite, + code, + del, + dfn, + em, + img, + ins, + kbd, + q, + s, + samp, + small, + strike, + strong, + sub, + sup, + tt, + b, + u, + i, + center, + dl, + dt, + dd, + ol, + ul, + li, + fieldset, + form, + label, + legend, + table, + caption, + tbody, + tfoot, + thead, + tr, + th, + td, + article, + aside, + canvas, + details, + embed, + figure, + figcaption, + footer, + header, + hgroup, + menu, + nav, + output, + ruby, + section, + summary, + time, + mark, + audio, + video { + vertical-align: baseline; + margin: 0; + border: 0; + padding: 0; + font-size: 100%; + font: inherit; + } + /* HTML5 display-role reset for older browsers */ + article, + aside, + details, + figcaption, + figure, + footer, + header, + hgroup, + menu, + nav, + section { + display: block; + } + body { + line-height: 1; + } + ol, + ul { + list-style: none; + } + blockquote, + q { + quotes: none; + } + blockquote:before, + blockquote:after, + q:before, + q:after { + content: ''; + content: none; + } + table { + border-collapse: collapse; + border-spacing: 0; + } + button { + cursor: pointer; + border: none; + background-color: transparent; + } + * { + box-sizing: border-box; + } + + body { + max-width: 768px; + height: 100lvh; + margin: 0 auto; + + overflow-y: scroll; + &::-webkit-scrollbar { + display: none; + } + } + + section { + width: 100%; + } + + #root { + display: flex; + flex-direction: column; + height: 100%; + } +`; diff --git a/client/src/index.css b/client/src/index.css deleted file mode 100644 index 2f63176f6..000000000 --- a/client/src/index.css +++ /dev/null @@ -1,20 +0,0 @@ -body { - max-width: 768px; - height: 100lvh; - margin: 0 auto; - - overflow-y: scroll; - &::-webkit-scrollbar { - display: none; - } -} - -section { - width: 100%; -} - -#root { - display: flex; - flex-direction: column; - height: 100%; -} diff --git a/client/src/index.tsx b/client/src/index.tsx index b3d742c43..eeffe86f4 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -3,8 +3,6 @@ import ReactDOM from 'react-dom/client'; import {RouterProvider} from 'react-router-dom'; import router from './router'; -import './reset.css'; -import './index.css'; ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> diff --git a/client/src/reset.css b/client/src/reset.css deleted file mode 100644 index 1a7ea162d..000000000 --- a/client/src/reset.css +++ /dev/null @@ -1,136 +0,0 @@ -/* http://meyerweb.com/eric/tools/css/reset/ - v2.0 | 20110126 - License: none (public domain) -*/ - -html, -body, -div, -span, -applet, -object, -iframe, -h1, -h2, -h3, -h4, -h5, -h6, -p, -blockquote, -pre, -a, -abbr, -acronym, -address, -big, -cite, -code, -del, -dfn, -em, -img, -ins, -kbd, -q, -s, -samp, -small, -strike, -strong, -sub, -sup, -tt, -b, -u, -i, -center, -dl, -dt, -dd, -ol, -ul, -li, -fieldset, -form, -label, -legend, -table, -caption, -tbody, -tfoot, -thead, -tr, -th, -td, -article, -aside, -canvas, -details, -embed, -figure, -figcaption, -footer, -header, -hgroup, -menu, -nav, -output, -ruby, -section, -summary, -time, -mark, -audio, -video { - vertical-align: baseline; - margin: 0; - border: 0; - padding: 0; - font-size: 100%; - font: inherit; -} -/* HTML5 display-role reset for older browsers */ -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -menu, -nav, -section { - display: block; -} -body { - line-height: 1; -} -ol, -ul { - list-style: none; -} -blockquote, -q { - quotes: none; -} -blockquote:before, -blockquote:after, -q:before, -q:after { - content: ''; - content: none; -} -table { - border-collapse: collapse; - border-spacing: 0; -} -button { - cursor: pointer; - border: none; - background-color: transparent; -} -* { - box-sizing: border-box; -} diff --git a/client/webpack.config.js b/client/webpack.config.js index 9545ecf2f..2c706beec 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -38,10 +38,6 @@ export default { loader: 'ts-loader', exclude: /node_modules/, }, - { - test: /\.css$/i, - use: ['style-loader', 'css-loader'], - }, { test: /\.svg$/, use: [ From e3e4151ad815cd063e03eb0170fe693d1fba8523 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:10:13 +0900 Subject: [PATCH 111/273] =?UTF-8?q?design:=20Button=EC=9D=B4=20disabled?= =?UTF-8?q?=EC=9D=BC=20=EB=95=8C=20=EC=BB=A4=EC=84=9C=EA=B0=80=20=ED=8F=AC?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=EA=B0=80=20=EC=95=84=EB=8B=88=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#171)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HDesign/src/theme/GlobalStyle.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/HDesign/src/theme/GlobalStyle.ts b/HDesign/src/theme/GlobalStyle.ts index 0c1670b07..f1b7b699b 100644 --- a/HDesign/src/theme/GlobalStyle.ts +++ b/HDesign/src/theme/GlobalStyle.ts @@ -27,6 +27,10 @@ export const GlobalStyle = css` line-height: 0; } + button:disabled { + cursor: default; + } + /* Remove list styles (bullets/numbers) */ ol, ul, From a5663faca3a975b1bb5ce81e6e06c0584746be53 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Sun, 4 Aug 2024 16:59:45 +0900 Subject: [PATCH 112/273] =?UTF-8?q?feat:=20Input=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B4=80=EB=A0=A8=ED=95=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=88=98=EC=A0=95,=20useDynamic-*=20=ED=9B=85=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95,?= =?UTF-8?q?=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=ED=86=B5=EC=9D=BC,=20?= =?UTF-8?q?=EC=9D=98=EB=AF=B8=EB=A5=BC=20=EB=AA=85=ED=99=95=ED=95=98?= =?UTF-8?q?=EA=B2=8C=20=EB=8B=B4=EB=8F=84=EB=A1=9D=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EC=88=98=EC=A0=95=20(#143,=20#183)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * style: lint 적용 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> --- .github/workflows/frontend-pull-request.yml | 2 +- HDesign/package-lock.json | 4 +- HDesign/package.json | 2 +- .../src/components/Input/Input.stories.tsx | 31 +- HDesign/src/components/Input/Input.style.ts | 11 +- HDesign/src/components/Input/Input.tsx | 33 +- HDesign/src/components/Input/useInput.ts | 57 +++- .../components/LabelGroupInput/Element.tsx | 62 ++++ .../LabelGroupInput/Element.type.ts | 10 + .../LabelGroupInput/GroupInputContext.tsx | 32 ++ .../LabelGroupInput.stories.tsx | 73 +++++ .../LabelGroupInput/LabelGroupInput.style.ts | 37 +++ .../LabelGroupInput/LabelGroupInput.tsx | 44 +++ .../LabelGroupInput/LabelGroupInput.type.ts | 10 + .../src/components/LabelGroupInput/index.ts | 3 + .../LabelInput/LabelInput.stories.tsx | 28 +- .../components/LabelInput/LabelInput.style.ts | 13 +- .../src/components/LabelInput/LabelInput.tsx | 47 ++- .../components/LabelInput/LabelInput.type.ts | 10 +- .../components/LabelInput/useLabelInput.ts | 21 ++ HDesign/src/index.tsx | 10 +- client/package-lock.json | 310 ++++++++++++------ client/package.json | 2 +- client/src/components/Modal/Modal.style.ts | 23 -- .../AddBillActionListModalContent.style.ts} | 14 +- .../AddBillActionListModalContent.tsx | 74 +++++ .../AddMemberActionListModalContent.style.ts} | 11 +- .../AddMemberActionListModalContent.tsx | 65 ++++ .../SetActionListModal.style.ts} | 8 +- .../SetActionListModal.tsx} | 16 +- .../components/Modal/SetActionModal/index.ts | 1 + .../SetActionModalContent/SetPurchase.tsx | 60 ---- .../UpdateParticipants.tsx | 49 --- .../Modal/SetActionModalContent/index.ts | 1 - .../SetInitialMemberListModal.style.ts} | 4 +- .../SetInitialMemberListModal.tsx | 62 ++++ .../Modal/SetInitialMemberListModal/index.ts | 1 + .../SetInitialParticipants.tsx | 51 --- .../Modal/SetInitialParticipants/index.ts | 1 - client/src/components/Modal/index.ts | 4 +- client/src/constants/errorMessage.ts | 8 + client/src/constants/regExp.ts | 6 + client/src/constants/rule.ts | 7 + .../src/hooks/useDynamicAdditionalInput.tsx | 52 --- .../src/hooks/useDynamicBillActionInput.tsx | 142 ++++++++ client/src/hooks/useDynamicInput.tsx | 139 ++++++++ client/src/hooks/useDynamicInputPairs.tsx | 45 --- client/src/pages/Create/Name.tsx | 46 --- client/src/pages/Create/index.ts | 2 - .../CompleteCreateEventPage.tsx} | 4 +- .../CreateEventPage/SetEventNamePage.tsx | 67 ++++ client/src/pages/CreateEventPage/index.ts | 2 + client/src/pages/Event/Admin/index.ts | 1 - client/src/pages/Event/Home/index.ts | 1 - client/src/pages/Event/index.ts | 1 - .../AdminPage/AdminPage.style.ts} | 0 .../AdminPage/AdminPage.tsx} | 33 +- client/src/pages/EventPage/AdminPage/index.ts | 1 + .../EvenPageLayout.tsx} | 4 +- .../HomePage/HomePage.tsx} | 4 +- client/src/pages/EventPage/HomePage/index.ts | 1 + client/src/pages/EventPage/index.ts | 1 + client/src/pages/Main/index.ts | 1 - .../{Main/Main.tsx => MainPage/MainPage.tsx} | 6 +- client/src/pages/MainPage/index.ts | 1 + client/src/router.tsx | 14 +- client/src/types/serviceType.ts | 54 +++ client/src/utils/validate/type.ts | 4 + .../src/utils/validate/validateEventName.ts | 13 + .../src/utils/validate/validateMemberName.ts | 25 ++ client/src/utils/validate/validatePurchase.ts | 34 ++ 71 files changed, 1437 insertions(+), 579 deletions(-) create mode 100644 HDesign/src/components/LabelGroupInput/Element.tsx create mode 100644 HDesign/src/components/LabelGroupInput/Element.type.ts create mode 100644 HDesign/src/components/LabelGroupInput/GroupInputContext.tsx create mode 100644 HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx create mode 100644 HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts create mode 100644 HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx create mode 100644 HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts create mode 100644 HDesign/src/components/LabelGroupInput/index.ts create mode 100644 HDesign/src/components/LabelInput/useLabelInput.ts delete mode 100644 client/src/components/Modal/Modal.style.ts rename client/src/components/Modal/{SetActionModalContent/SetPurchase.style.ts => SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.style.ts} (61%) create mode 100644 client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx rename client/src/components/Modal/{SetActionModalContent/UpdateParticipants.style.ts => SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts} (60%) create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx rename client/src/components/Modal/{SetActionModalContent/SetActionModalContent.style.ts => SetActionModal/SetActionListModal.style.ts} (58%) rename client/src/components/Modal/{SetActionModalContent/SetActionModalContent.tsx => SetActionModal/SetActionListModal.tsx} (72%) create mode 100644 client/src/components/Modal/SetActionModal/index.ts delete mode 100644 client/src/components/Modal/SetActionModalContent/SetPurchase.tsx delete mode 100644 client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx delete mode 100644 client/src/components/Modal/SetActionModalContent/index.ts rename client/src/components/Modal/{SetInitialParticipants/SetInitialParticipants.style.ts => SetInitialMemberListModal/SetInitialMemberListModal.style.ts} (73%) create mode 100644 client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx create mode 100644 client/src/components/Modal/SetInitialMemberListModal/index.ts delete mode 100644 client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx delete mode 100644 client/src/components/Modal/SetInitialParticipants/index.ts create mode 100644 client/src/constants/errorMessage.ts create mode 100644 client/src/constants/regExp.ts create mode 100644 client/src/constants/rule.ts delete mode 100644 client/src/hooks/useDynamicAdditionalInput.tsx create mode 100644 client/src/hooks/useDynamicBillActionInput.tsx create mode 100644 client/src/hooks/useDynamicInput.tsx delete mode 100644 client/src/hooks/useDynamicInputPairs.tsx delete mode 100644 client/src/pages/Create/Name.tsx delete mode 100644 client/src/pages/Create/index.ts rename client/src/pages/{Create/Complete.tsx => CreateEventPage/CompleteCreateEventPage.tsx} (93%) create mode 100644 client/src/pages/CreateEventPage/SetEventNamePage.tsx create mode 100644 client/src/pages/CreateEventPage/index.ts delete mode 100644 client/src/pages/Event/Admin/index.ts delete mode 100644 client/src/pages/Event/Home/index.ts delete mode 100644 client/src/pages/Event/index.ts rename client/src/pages/{Event/Admin/Admin.style.ts => EventPage/AdminPage/AdminPage.style.ts} (100%) rename client/src/pages/{Event/Admin/Admin.tsx => EventPage/AdminPage/AdminPage.tsx} (78%) create mode 100644 client/src/pages/EventPage/AdminPage/index.ts rename client/src/pages/{Event/EventLayout.tsx => EventPage/EvenPageLayout.tsx} (88%) rename client/src/pages/{Event/Home/Home.tsx => EventPage/HomePage/HomePage.tsx} (95%) create mode 100644 client/src/pages/EventPage/HomePage/index.ts create mode 100644 client/src/pages/EventPage/index.ts delete mode 100644 client/src/pages/Main/index.ts rename client/src/pages/{Main/Main.tsx => MainPage/MainPage.tsx} (70%) create mode 100644 client/src/pages/MainPage/index.ts create mode 100644 client/src/types/serviceType.ts create mode 100644 client/src/utils/validate/type.ts create mode 100644 client/src/utils/validate/validateEventName.ts create mode 100644 client/src/utils/validate/validateMemberName.ts create mode 100644 client/src/utils/validate/validatePurchase.ts diff --git a/.github/workflows/frontend-pull-request.yml b/.github/workflows/frontend-pull-request.yml index c9efc26cc..238a9a0d1 100644 --- a/.github/workflows/frontend-pull-request.yml +++ b/.github/workflows/frontend-pull-request.yml @@ -9,7 +9,7 @@ on: jobs: test: - runs-on: ubuntu-latest log + runs-on: ubuntu-latest defaults: run: diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 58d306b1a..bbf0d12a9 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.36", + "version": "0.1.52", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.36", + "version": "0.1.52", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index a10d83b7b..f1bc9c8e7 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.36", + "version": "0.1.52", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/Input/Input.stories.tsx b/HDesign/src/components/Input/Input.stories.tsx index 0f5187cb3..97365fa9d 100644 --- a/HDesign/src/components/Input/Input.stories.tsx +++ b/HDesign/src/components/Input/Input.stories.tsx @@ -1,26 +1,20 @@ import type {Meta, StoryObj} from '@storybook/react'; +import React, {useEffect, useState} from 'react'; + import Input from '@components/Input/Input'; const meta = { title: 'Components/Input', component: Input, tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, argTypes: { - value: { - description: '', - control: {type: 'text'}, - }, inputType: { // TODO: (@cookie) 스토리북 라디오버튼 보이도록 설정해야 함 control: {type: 'radio'}, }, }, args: { - disabled: false, placeholder: 'placeholder', }, } satisfies Meta<typeof Input>; @@ -29,4 +23,23 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Playground: Story = {}; +export const Playground: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [isError, setIsError] = useState(false); + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + if (event.target.value.length < 4) { + setValue(event.target.value); + setIsError(false); + } else { + event.target.value = value; + setIsError(true); + } + }; + const handleBlur = () => { + console.log('blur'); + }; + + return <Input value={value} onChange={e => handleChange(e)} isError={isError} onBlur={handleBlur} {...args} />; + }, +}; diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts index 285908bab..cb7471afc 100644 --- a/HDesign/src/components/Input/Input.style.ts +++ b/HDesign/src/components/Input/Input.style.ts @@ -4,7 +4,7 @@ import {Theme} from '@theme/theme.type'; import {InputType} from './Input.type'; -const inputBoxBackgroundColorByInputType = (theme: Theme, inputType: InputType = 'input') => { +const getBackgroundColorStyle = (theme: Theme, inputType: InputType = 'input') => { switch (inputType) { case 'input': return theme.colors.lightGrayContainer; @@ -17,6 +17,9 @@ const inputBoxBackgroundColorByInputType = (theme: Theme, inputType: InputType = } }; +const getBorderStyle = (isFocus: boolean, theme: Theme, isError?: boolean) => + isError ? `0 0 0 1px ${theme.colors.error} inset` : isFocus ? `0 0 0 1px ${theme.colors.primary} inset` : 'none'; + export const inputBoxStyle = ( theme: Theme, inputType: InputType = 'input', @@ -26,13 +29,13 @@ export const inputBoxStyle = ( css({ display: 'flex', justifyContent: 'space-between', - + gap: '1rem', padding: '0.75rem 1rem', borderRadius: '1rem', - backgroundColor: inputBoxBackgroundColorByInputType(theme, inputType), + backgroundColor: getBackgroundColorStyle(theme, inputType), boxSizing: 'border-box', - outline: isFocus ? `1px solid ${theme.colors.primary}` : isError ? `1px solid ${theme.colors.error}` : 'none', + boxShadow: getBorderStyle(isFocus, theme, isError), }); export const inputStyle = (theme: Theme) => diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx index 81f0f1c93..cebdfb5a7 100644 --- a/HDesign/src/components/Input/Input.tsx +++ b/HDesign/src/components/Input/Input.tsx @@ -1,23 +1,28 @@ /** @jsxImportSource @emotion/react */ -import React, {forwardRef, useImperativeHandle, useRef, useState} from 'react'; +import React, {forwardRef, useImperativeHandle, useRef} from 'react'; -import IconButton from '@components/IconButton/IconButton'; -import {InputProps} from '@components/Input/Input.type'; -import {inputBoxStyle, inputStyle} from '@components/Input/Input.style'; -import {useInput} from '@components/Input/useInput'; +import {useTheme} from '@/theme/HDesignProvider'; -import {useTheme} from '@theme/HDesignProvider'; +import IconButton from '../IconButton/IconButton'; + +import {useInput} from './useInput'; +import {InputProps} from './Input.type'; +import {inputBoxStyle, inputStyle} from './Input.style'; export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( - {value: propsValue, onChange, inputType, isError, ...htmlProps}: InputProps, + {value: propsValue, onChange, onFocus, onBlur, inputType, isError, placeholder, ...htmlProps}: InputProps, ref, ) { const {theme} = useTheme(); - const inputRef = useRef<HTMLInputElement>(null); - useImperativeHandle(ref, () => inputRef.current!); - - const {value, hasFocus, handleChange, handleClickDelete, toggleFocus} = useInput({propsValue, onChange, inputRef}); + const inputRef = useRef<HTMLInputElement>(null); + const {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown} = useInput({ + propsValue, + onChange, + onBlur, + onFocus, + inputRef, + }); return ( <div css={inputBoxStyle(theme, inputType, hasFocus, isError)}> @@ -26,8 +31,10 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro ref={inputRef} value={value} onChange={handleChange} - onFocus={toggleFocus} - onBlur={toggleFocus} + onBlur={handleBlur} + onFocus={handleFocus} + placeholder={inputRef.current === document.activeElement ? '' : placeholder} + onKeyDown={handleKeyDown} {...htmlProps} /> {value && hasFocus && <IconButton iconType="inputDelete" onClick={handleClickDelete} />} diff --git a/HDesign/src/components/Input/useInput.ts b/HDesign/src/components/Input/useInput.ts index 5b37d275a..46a195032 100644 --- a/HDesign/src/components/Input/useInput.ts +++ b/HDesign/src/components/Input/useInput.ts @@ -3,39 +3,66 @@ import {RefObject, useEffect, useState} from 'react'; interface UseInputProps<T> { propsValue: T; onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void; + onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void; + onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void; inputRef: RefObject<HTMLInputElement>; + autoFocus?: boolean; } -export const useInput = <T>({propsValue, onChange, inputRef}: UseInputProps<T>) => { - const [value, setValue] = useState(propsValue || ''); - const [hasFocus, setHasFocus] = useState(false); +export const useInput = <T>({propsValue, onChange, onBlur, onFocus, inputRef, autoFocus}: UseInputProps<T>) => { + const [value, setValue] = useState<T>(propsValue); + const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); useEffect(() => { - setValue(propsValue || ''); - }, [propsValue]); + setHasFocus(inputRef.current === document.activeElement); + }, []); - const handleClickDelete = () => { - setValue(''); - - if (inputRef.current) { - inputRef.current.focus(); - } + useEffect(() => { + setValue(propsValue); + }, [value]); + const handleClickDelete = (event: React.MouseEvent) => { + event.preventDefault(); + setValue('' as T); if (onChange) { onChange({target: {value: ''}} as React.ChangeEvent<HTMLInputElement>); } + if (inputRef.current) { + inputRef.current.focus(); + } }; const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { - setValue(e.target.value); + setValue(e.target.value as T); if (onChange) { onChange(e); } }; - const toggleFocus = () => { - setHasFocus(!hasFocus); + const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => { + setHasFocus(false); + if (onBlur) { + onBlur(e); + } + }; + + const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => { + setHasFocus(true); + if (onFocus) { + onFocus(e); + } + }; + + const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.nativeEvent.isComposing) return; + + if (event.key === 'Enter' || event.key === 'Escape') { + setHasFocus(false); + if (inputRef.current) { + inputRef.current.blur(); + } + } }; - return {value, hasFocus, handleChange, handleClickDelete, toggleFocus}; + return {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown}; }; diff --git a/HDesign/src/components/LabelGroupInput/Element.tsx b/HDesign/src/components/LabelGroupInput/Element.tsx new file mode 100644 index 000000000..1043aa313 --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/Element.tsx @@ -0,0 +1,62 @@ +/** @jsxImportSource @emotion/react */ + +import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; + +import Input from '../Input/Input'; + +import {ElementProps} from './Element.type'; +import {useGroupInputContext} from './GroupInputContext'; + +const Element: React.FC<ElementProps> = forwardRef<HTMLInputElement, ElementProps>(function Element( + {elementKey, value: propsValue, onChange, onBlur, onFocus, isError, ...htmlProps}: ElementProps, + + ref, +) { + useImperativeHandle(ref, () => inputRef.current!); + const inputRef = useRef<HTMLInputElement>(null); + const {setHasAnyFocus, values, setValues, hasAnyErrors, setHasAnyErrors} = useGroupInputContext(); + + useEffect(() => { + setValues({...values, [elementKey]: `${propsValue}`}); + }, [propsValue]); + + const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { + const newValue = e.target.value; + setValues({...values, [elementKey]: newValue}); + if (onChange) { + onChange(e); + } + }; + + useEffect(() => { + setHasAnyErrors({...hasAnyErrors, [elementKey]: isError ?? false}); + }, [isError]); + + const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => { + setHasAnyFocus(false); + if (onBlur) { + onBlur(e); + } + }; + + const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => { + setHasAnyFocus(true); + if (onFocus) { + onFocus(e); + } + }; + + return ( + <Input + ref={inputRef} + isError={isError} + value={propsValue} + onChange={handleChange} + onBlur={handleBlur} + onFocus={handleFocus} + {...htmlProps} + /> + ); +}); + +export default Element; diff --git a/HDesign/src/components/LabelGroupInput/Element.type.ts b/HDesign/src/components/LabelGroupInput/Element.type.ts new file mode 100644 index 000000000..2ec2ef9ed --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/Element.type.ts @@ -0,0 +1,10 @@ +export interface ElementStyleProps {} + +export interface ElementCustomProps { + elementKey: string; + isError?: boolean; +} + +export type ElementOptionProps = ElementStyleProps & ElementCustomProps; + +export type ElementProps = React.ComponentProps<'input'> & ElementOptionProps; diff --git a/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx b/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx new file mode 100644 index 000000000..a564ef94f --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx @@ -0,0 +1,32 @@ +import React, {createContext, PropsWithChildren, useContext, useState} from 'react'; + +interface GroupInputContextProps { + hasAnyFocus: boolean; + setHasAnyFocus: React.Dispatch<React.SetStateAction<boolean>>; + values: {[key: string]: string}; + setValues: React.Dispatch<React.SetStateAction<{[key: string]: string}>>; + hasAnyErrors: {[key: string]: boolean}; + setHasAnyErrors: React.Dispatch<React.SetStateAction<{[key: string]: boolean}>>; +} + +const GroupInputContext = createContext<GroupInputContextProps | undefined>(undefined); + +export const useGroupInputContext = () => { + const context = useContext(GroupInputContext); + if (!context) { + throw new Error('useGroupInputContext must be used within an GroupInputProvider'); + } + return context; +}; + +export const GroupInputProvider: React.FC<PropsWithChildren> = ({children}: React.PropsWithChildren) => { + const [hasAnyFocus, setHasAnyFocus] = useState(false); + const [values, setValues] = useState<{[key: string]: string}>({}); + const [hasAnyErrors, setHasAnyErrors] = useState<{[key: string]: boolean}>({}); + + return ( + <GroupInputContext.Provider value={{hasAnyFocus, setHasAnyFocus, values, setValues, hasAnyErrors, setHasAnyErrors}}> + {children} + </GroupInputContext.Provider> + ); +}; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx b/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx new file mode 100644 index 000000000..b3f48b452 --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx @@ -0,0 +1,73 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useState} from 'react'; + +import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; + +const meta = { + title: 'Components/LabelGroupInput', + component: LabelGroupInput, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + labelText: { + description: 'label에 들어갈 텍스트를 작성', + control: {type: 'text'}, + }, + errorText: { + description: 'error에 들어갈 텍스트를 작성', + control: {type: 'text'}, + }, + }, + args: { + labelText: '지출내역 / 금액', + errorText: 'error가 발생했을 때 나타납니다!', + }, +} satisfies Meta<typeof LabelGroupInput>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + const [name, setName] = useState(''); + const [price, setPrice] = useState(''); + const [isError, setIsError] = useState(false); + const handleChangeName = (event: React.ChangeEvent<HTMLInputElement>) => { + if (event.target.value.length < 4) { + setName(event.target.value); + setIsError(false); + } else { + event.target.value = name; + setIsError(true); + } + }; + const handleChangePrice = (event: React.ChangeEvent<HTMLInputElement>) => { + setPrice(event.target.value); + }; + return ( + <LabelGroupInput {...args}> + <LabelGroupInput.Element + elementKey="name" + placeholder="지출내역" + value={name} + onChange={e => handleChangeName(e)} + onBlur={() => console.log('!!!')} + isError={isError} + /> + <LabelGroupInput.Element + value={price} + onChange={handleChangePrice} + elementKey="price" + placeholder="금액" + onBlur={() => console.log('!!!')} + isError={false} + /> + </LabelGroupInput> + ); + }, +}; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts b/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts new file mode 100644 index 000000000..99075fe1d --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts @@ -0,0 +1,37 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@/theme/theme.type'; + +export const labelInputStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '0.375rem', +}); + +export const labelGroupStyle = css({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%', + + paddingInline: '0.5rem', + marginBottom: '0.375rem', +}); + +export const inputGroupStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', +}); + +export const labelTextStyle = (theme: Theme) => + css({ + height: '1.125rem', + color: theme.colors.gray, + }); + +export const errorTextStyle = (theme: Theme) => + css({ + height: '1.125rem', + color: theme.colors.onErrorContainer, + }); diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx b/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx new file mode 100644 index 000000000..e115bc71a --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx @@ -0,0 +1,44 @@ +/** @jsxImportSource @emotion/react */ + +import Text from '@components/Text/Text'; +import {useTheme} from '@/theme/HDesignProvider'; + +import Flex from '../Flex/Flex'; + +import {LabelGroupInputProps} from './LabelGroupInput.type'; +import {errorTextStyle, labelTextStyle} from './LabelGroupInput.style'; +import Element from './Element'; +import {GroupInputProvider, useGroupInputContext} from './GroupInputContext'; + +const LabelGroupInput: React.FC<LabelGroupInputProps> = ({labelText, errorText, children}: LabelGroupInputProps) => { + const {theme} = useTheme(); + const {hasAnyFocus, values, hasAnyErrors} = useGroupInputContext(); + + return ( + <Flex flexDirection="column" gap="0.375rem"> + <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> + <Text size="caption" css={labelTextStyle(theme)}> + {(hasAnyFocus || !Object.values(values).every(value => value === '')) && labelText} + </Text> + {errorText && ( + <Text size="caption" css={errorTextStyle(theme)}> + {!Object.values(hasAnyErrors).every(error => !error) && errorText} + </Text> + )} + </Flex> + <Flex flexDirection="column" gap="0.5rem"> + {children} + </Flex> + </Flex> + ); +}; + +const LabelGroupInputContainer = (props: LabelGroupInputProps) => ( + <GroupInputProvider> + <LabelGroupInput {...props} /> + </GroupInputProvider> +); + +LabelGroupInputContainer.Element = Element; + +export default LabelGroupInputContainer; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts b/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts new file mode 100644 index 000000000..cfa938457 --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts @@ -0,0 +1,10 @@ +export interface LabelGroupInputStyleProps {} + +export interface LabelGroupInputCustomProps { + labelText: string; + errorText?: string; +} + +export type LabelGroupInputOptionProps = LabelGroupInputStyleProps & LabelGroupInputCustomProps; + +export type LabelGroupInputProps = React.ComponentProps<'input'> & LabelGroupInputOptionProps; diff --git a/HDesign/src/components/LabelGroupInput/index.ts b/HDesign/src/components/LabelGroupInput/index.ts new file mode 100644 index 000000000..c31f35eaf --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/index.ts @@ -0,0 +1,3 @@ +import LabelGroupInputContainer from './LabelGroupInput'; + +export {LabelGroupInputContainer as LabelGroupInput}; diff --git a/HDesign/src/components/LabelInput/LabelInput.stories.tsx b/HDesign/src/components/LabelInput/LabelInput.stories.tsx index 63ebcea37..853c0260a 100644 --- a/HDesign/src/components/LabelInput/LabelInput.stories.tsx +++ b/HDesign/src/components/LabelInput/LabelInput.stories.tsx @@ -1,8 +1,9 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; +import {useEffect, useState} from 'react'; + import LabelInput from '@components/LabelInput/LabelInput'; -import Input from '@components/Input/Input'; const meta = { title: 'Components/LabelInput', @@ -16,15 +17,19 @@ const meta = { description: 'label에 들어갈 텍스트를 작성', control: {type: 'text'}, }, + isError: { + description: '', + control: {type: 'boolean'}, + }, errorText: { description: 'error에 들어갈 텍스트를 작성', control: {type: 'text'}, }, }, args: { - labelText: 'label 내용', + // value: '', + labelText: '이름', errorText: 'error가 발생했을 때 나타납니다!', - children: <Input placeholder="labelInput 테스트를 위한 Input" />, }, } satisfies Meta<typeof LabelInput>; @@ -32,4 +37,19 @@ export default meta; type Story = StoryObj<typeof meta>; -export const Playground: Story = {}; +export const Playground: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [isError, setIsError] = useState(false); + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + if (event.target.value.length < 4) { + setValue(event.target.value); + setIsError(false); + } else { + event.target.value = value; + setIsError(true); + } + }; + return <LabelInput value={value} onChange={e => handleChange(e)} isError={isError} {...args} />; + }, +}; diff --git a/HDesign/src/components/LabelInput/LabelInput.style.ts b/HDesign/src/components/LabelInput/LabelInput.style.ts index 208d6e56c..5d5eaed8f 100644 --- a/HDesign/src/components/LabelInput/LabelInput.style.ts +++ b/HDesign/src/components/LabelInput/LabelInput.style.ts @@ -2,23 +2,14 @@ import {css} from '@emotion/react'; import {Theme} from '@/theme/theme.type'; -export const labelGroupStyle = () => - css({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - width: '100%', - - paddingInline: '0.5rem', - marginBottom: '0.375rem', - }); - export const labelTextStyle = (theme: Theme) => css({ + height: '1.125rem', color: theme.colors.gray, }); export const errorTextStyle = (theme: Theme) => css({ + height: '1.125rem', color: theme.colors.onErrorContainer, }); diff --git a/HDesign/src/components/LabelInput/LabelInput.tsx b/HDesign/src/components/LabelInput/LabelInput.tsx index 97cc9bcd1..b7759b361 100644 --- a/HDesign/src/components/LabelInput/LabelInput.tsx +++ b/HDesign/src/components/LabelInput/LabelInput.tsx @@ -1,30 +1,41 @@ /** @jsxImportSource @emotion/react */ +import {forwardRef, useImperativeHandle, useRef} from 'react'; + import Text from '@components/Text/Text'; import {useTheme} from '@/theme/HDesignProvider'; +import Input from '../Input/Input'; +import Flex from '../Flex/Flex'; + +import {errorTextStyle, labelTextStyle} from './LabelInput.style'; +import {useLabelInput} from './useLabelInput'; import {LabelInputProps} from './LabelInput.type'; -import {errorTextStyle, labelGroupStyle, labelTextStyle} from './LabelInput.style'; -const LabelInput = ({labelText, errorText, children}: LabelInputProps) => { +const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, LabelInputProps>(function LabelInput( + {labelText, errorText, isError, ...htmlProps}: LabelInputProps, + ref, +) { + useImperativeHandle(ref, () => inputRef.current!); const {theme} = useTheme(); + const inputRef = useRef<HTMLInputElement>(null); + const {hasFocus} = useLabelInput({inputRef}); + return ( - <> - <div css={labelGroupStyle}> - <label> - <Text size="caption" css={labelTextStyle(theme)}> - {labelText} - </Text> - </label> - {errorText && ( - <Text size="caption" css={errorTextStyle(theme)}> - {errorText} - </Text> - )} - </div> - {children} - </> + <Flex flexDirection="column" gap="0.375rem"> + <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> + <Text size="caption" css={labelTextStyle(theme)}> + {(hasFocus || htmlProps.value) && labelText} + </Text> + <Text size="caption" css={errorTextStyle(theme)}> + {isError && errorText} + </Text> + </Flex> + <Flex flexDirection="column" gap="0.5rem"> + <Input ref={inputRef} isError={isError} placeholder={labelText} {...htmlProps} /> + </Flex> + </Flex> ); -}; +}); export default LabelInput; diff --git a/HDesign/src/components/LabelInput/LabelInput.type.ts b/HDesign/src/components/LabelInput/LabelInput.type.ts index 539a10da1..ae0d0c5f6 100644 --- a/HDesign/src/components/LabelInput/LabelInput.type.ts +++ b/HDesign/src/components/LabelInput/LabelInput.type.ts @@ -1,13 +1,11 @@ -import {InputProps} from '../Input/Input.type'; - export interface LabelInputStyleProps {} -export interface ButtonCustomProps { +export interface LabelInputCustomProps { labelText: string; errorText?: string; - children?: React.ReactElement<InputProps>[] | React.ReactElement<InputProps>; + isError?: boolean; } -export type LabelInputOptionProps = LabelInputStyleProps & ButtonCustomProps; +export type LabelInputOptionProps = LabelInputCustomProps & LabelInputCustomProps; -export type LabelInputProps = React.ComponentProps<'div'> & LabelInputOptionProps; +export type LabelInputProps = React.ComponentProps<'input'> & LabelInputOptionProps; diff --git a/HDesign/src/components/LabelInput/useLabelInput.ts b/HDesign/src/components/LabelInput/useLabelInput.ts new file mode 100644 index 000000000..ed64fd8bc --- /dev/null +++ b/HDesign/src/components/LabelInput/useLabelInput.ts @@ -0,0 +1,21 @@ +import {RefObject, useEffect, useState} from 'react'; + +interface UseLabelInput<T> { + inputRef: RefObject<HTMLInputElement>; +} + +export const useLabelInput = <T>({inputRef}: UseLabelInput<T>) => { + const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); + + useEffect(() => { + inputRef.current?.addEventListener('focus', () => setHasFocus(true)); + inputRef.current?.addEventListener('blur', () => setHasFocus(false)); + + return () => { + inputRef.current?.removeEventListener('focus', () => setHasFocus(true)); + inputRef.current?.removeEventListener('blur', () => setHasFocus(false)); + }; + }, []); + + return {hasFocus}; +}; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index f75b5f640..f6449f0bb 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -8,6 +8,8 @@ import Flex from '@components/Flex/Flex'; import IconButton from '@components/IconButton/IconButton'; import InOutItem from '@components/InOutItem/InOutItem'; import Input from '@components/Input/Input'; +import LabelInput from '@components/LabelInput/LabelInput'; +import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; import Search from '@components/Search/Search'; import StepItem from '@components/StepItem/StepItem'; import Switch from '@components/Switch/Switch'; @@ -15,8 +17,8 @@ import Tabs from '@/components/Tabs/Tabs'; import Text from '@components/Text/Text'; import TextButton from '@components/TextButton/TextButton'; import Title from '@components/Title/Title'; -import TopNav from '@components/TopNav/TopNav'; import Toast from '@components/Toast/Toast'; +import TopNav from '@components/TopNav/TopNav'; import {ToastProvider, useToast} from '@components/Toast/ToastProvider'; import {MainLayout} from '@layouts/MainLayout'; @@ -39,6 +41,8 @@ export { IconButton, InOutItem, Input, + LabelInput, + LabelGroupInput, Search, StepItem, Switch, @@ -50,8 +54,8 @@ export { TopNav, MainLayout, ContentLayout, - HDesignProvider, + Toast, ToastProvider, useToast, - Toast, + HDesignProvider, }; diff --git a/client/package-lock.json b/client/package-lock.json index e1cd34770..d35cb264b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.35", + "haengdong-design": "^0.1.51", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -400,9 +400,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz", - "integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", + "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "dependencies": { + "@babel/types": "^7.25.2" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -411,12 +414,12 @@ } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.0.tgz", - "integrity": "sha512-dG0aApncVQwAUJa8tP1VHTnmU67BeIQvKafd3raEx315H54FfkZSz3B/TT+33ZQAjatGJA79gZqTtqL5QZUKXw==", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", - "@babel/traverse": "^7.25.0" + "@babel/traverse": "^7.25.3" }, "engines": { "node": ">=6.9.0" @@ -1578,15 +1581,15 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.2.tgz", - "integrity": "sha512-Y2Vkwy3ITW4id9c6KXshVV/x5yCGK7VdJmKkzOzNsDZMojRKfSA/033rRbLqlRozmhRXCejxWHLSJOg/wUHfzw==", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", + "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.0", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", @@ -1753,13 +1756,13 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.2.tgz", - "integrity": "sha512-s4/r+a7xTnny2O6FcZzqgT6nE4/GHEdcqj4qAeglbUOh0TeglEfmNJFAd/OLoVtGd6ZhAO8GCVvCNUO5t/VJVQ==", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", + "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.0", + "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/types": "^7.25.2", "debug": "^4.3.1", @@ -2286,9 +2289,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.18.0.tgz", - "integrity": "sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw==", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", "engines": { "node": ">=14.0.0" } @@ -2549,9 +2552,9 @@ } }, "node_modules/@swc/core": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.3.tgz", - "integrity": "sha512-HHAlbXjWI6Kl9JmmUW1LSygT1YbblXgj2UvvDzMkTBPRzYMhW6xchxdO8HbtMPtFYRt/EQq9u1z7j4ttRSrFsA==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.5.tgz", + "integrity": "sha512-qKK0/Ta4qvxs/ok3XyYVPT7OBenwRn1sSINf1cKQTBHPqr7U/uB4k2GTl6JgEs8H4PiJrMTNWfMLTucIoVSfAg==", "hasInstallScript": true, "dependencies": { "@swc/counter": "^0.1.3", @@ -2565,16 +2568,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.3", - "@swc/core-darwin-x64": "1.7.3", - "@swc/core-linux-arm-gnueabihf": "1.7.3", - "@swc/core-linux-arm64-gnu": "1.7.3", - "@swc/core-linux-arm64-musl": "1.7.3", - "@swc/core-linux-x64-gnu": "1.7.3", - "@swc/core-linux-x64-musl": "1.7.3", - "@swc/core-win32-arm64-msvc": "1.7.3", - "@swc/core-win32-ia32-msvc": "1.7.3", - "@swc/core-win32-x64-msvc": "1.7.3" + "@swc/core-darwin-arm64": "1.7.5", + "@swc/core-darwin-x64": "1.7.5", + "@swc/core-linux-arm-gnueabihf": "1.7.5", + "@swc/core-linux-arm64-gnu": "1.7.5", + "@swc/core-linux-arm64-musl": "1.7.5", + "@swc/core-linux-x64-gnu": "1.7.5", + "@swc/core-linux-x64-musl": "1.7.5", + "@swc/core-win32-arm64-msvc": "1.7.5", + "@swc/core-win32-ia32-msvc": "1.7.5", + "@swc/core-win32-x64-msvc": "1.7.5" }, "peerDependencies": { "@swc/helpers": "*" @@ -2586,9 +2589,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.3.tgz", - "integrity": "sha512-CTkHa6MJdov9t41vuV2kmQIMu+Q19LrEHGIR/UiJYH06SC/sOu35ZZH8DyfLp9ZoaCn21gwgWd61ixOGQlwzTw==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.5.tgz", + "integrity": "sha512-Y+bvW9C4/u26DskMbtQKT4FU6QQenaDYkKDi028vDIKAa7v1NZqYG9wmhD/Ih7n5EUy2uJ5I5EWD7WaoLzT6PA==", "cpu": [ "arm64" ], @@ -2601,9 +2604,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.3.tgz", - "integrity": "sha512-mun623y6rCoZ2EFIYfIRqXYRFufJOopoYSJcxYhZUrfTpAvQ1zLngjQpWCUU1krggXR2U0PQj+ls0DfXUTraNg==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.5.tgz", + "integrity": "sha512-AuIbDlcaAhYS6mtF4UqvXgrLeAfXZbVf4pgtgShPbutF80VbCQiIB55zOFz5aZdCpsBVuCWcBq0zLneK+VQKkQ==", "cpu": [ "x64" ], @@ -2616,9 +2619,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.3.tgz", - "integrity": "sha512-4Jz4UcIcvZNMp9qoHbBx35bo3rjt8hpYLPqnR4FFq6gkAsJIMFC56UhRZwdEQoDuYiOFMBnnrsg31Fyo6YQypA==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.5.tgz", + "integrity": "sha512-99uBPHITRqgGwCXAjHY94VaV3Z40+D2NQNgR1t6xQpO8ZnevI6YSzX6GVZfBnV7+7oisiGkrVEwfIRRa+1s8FA==", "cpu": [ "arm" ], @@ -2631,9 +2634,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.3.tgz", - "integrity": "sha512-p+U/M/oqV7HC4erQ5TVWHhJU1984QD+wQBPxslAYq751bOQGm0R/mXK42GjugqjnR6yYrAiwKKbpq4iWVXNePA==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.5.tgz", + "integrity": "sha512-xHL3Erlz+OGGCG4h6K2HWiR56H5UYMuBWWPbbUufi2bJpfhuKQy/X3vWffwL8ZVfJmCUwr4/G91GHcm32uYzRg==", "cpu": [ "arm64" ], @@ -2646,9 +2649,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.3.tgz", - "integrity": "sha512-s6VzyaJwaRGTi2mz2h6Ywxfmgpkc69IxhuMzl+sl34plH0V0RgnZDm14HoCGIKIzRk4+a2EcBV1ZLAfWmPACQg==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.5.tgz", + "integrity": "sha512-5ArGdqvFMszNHdi4a67vopeYq8d1K+FuTWDrblHrAvZFhAyv+GQz2PnKqYOgl0sWmQxsNPfNwBFtxACpUO3Jzg==", "cpu": [ "arm64" ], @@ -2661,9 +2664,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.3.tgz", - "integrity": "sha512-IrFY48C356Z2dU2pjYg080yvMXzmSV3Lmm/Wna4cfcB1nkVLjWsuYwwRAk9CY7E19c+q8N1sMNggubAUDYoX2g==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.5.tgz", + "integrity": "sha512-mSVVV/PFzCGtI1nVQQyx34NwCMgSurF6ZX/me8pUAX054vsE/pSFL66xN+kQOe/1Z/LOd4UmXFkZ/EzOSnYcSg==", "cpu": [ "x64" ], @@ -2676,9 +2679,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.3.tgz", - "integrity": "sha512-qoLgxBlBnnyUEDu5vmRQqX90h9jldU1JXI96e6eh2d1gJyKRA0oSK7xXmTzorv1fGHiHulv9qiJOUG+g6uzJWg==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.5.tgz", + "integrity": "sha512-09hY3ZKMUORXVunESKS9yuP78+gQbr759GKHo8wyCdtAx8lCZdEjfI5NtC7/1VqwfeE32/U6u+5MBTVhZTt0AA==", "cpu": [ "x64" ], @@ -2691,9 +2694,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.3.tgz", - "integrity": "sha512-OAd7jVVJ7nb0Ev80VAa1aeK+FldPeC4eZ35H4Qn6EICzIz0iqJo2T33qLKkSZiZEBKSoF4KcwrqYfkjLOp5qWg==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.5.tgz", + "integrity": "sha512-B/UDtPI3RlYRFW42xQxOpl6kI/9LtkD7No+XeRIKQTPe15EP2o+rUlv7CmKljVBXgJ8KmaQbZlaEh1YP+QZEEQ==", "cpu": [ "arm64" ], @@ -2706,9 +2709,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.3.tgz", - "integrity": "sha512-31+Le1NyfSnILFV9+AhxfFOG0DK0272MNhbIlbcv4w/iqpjkhaOnNQnLsYJD1Ow7lTX1MtIZzTjOhRlzSviRWg==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.5.tgz", + "integrity": "sha512-BgLesVGmIY6Nub/sURqtSRvWYcbCE/ACfuZB3bZHVKD6nsZJJuOpdB8oC41fZPyc8yZUzL3XTBIifkT2RP+w9w==", "cpu": [ "ia32" ], @@ -2721,9 +2724,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.3.tgz", - "integrity": "sha512-jVQPbYrwcuueI4QB0fHC29SVrkFOBcfIspYDlgSoHnEz6tmLMqUy+txZUypY/ZH/KaK0HEY74JkzgbRC1S6LFQ==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.5.tgz", + "integrity": "sha512-CnF557tidLfQRPczcqDJ8x+LBQYsFa0Ra6w2+YU1iFUboaI2jJVuqt3vEChu80y6JiRIBAaaV2L/GawDJh1dIQ==", "cpu": [ "x64" ], @@ -2890,11 +2893,11 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.0.tgz", - "integrity": "sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", "dependencies": { - "undici-types": "~6.11.1" + "undici-types": "~6.13.0" } }, "node_modules/@types/node-forge": { @@ -3933,9 +3936,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "funding": [ { "type": "opencollective", @@ -3951,9 +3954,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { @@ -4041,9 +4044,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001645", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001645.tgz", - "integrity": "sha512-GFtY2+qt91kzyMk6j48dJcwJVq5uTkk71XxE3RtScx7XWRLsO7bU44LOFkOZYR8w9YMS0UhPSYpN/6rAMImmLw==", + "version": "1.0.30001646", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001646.tgz", + "integrity": "sha512-dRg00gudiBDDTmUhClSdv3hqRfpbOnU28IpI1T6PBTLWa+kOj0681C8uML3PifYfREuBrVjDGhL3adYpBT6spw==", "funding": [ { "type": "opencollective", @@ -6332,9 +6335,9 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/globals": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", - "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, "engines": { "node": ">=18" @@ -6403,9 +6406,9 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.45", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.45.tgz", - "integrity": "sha512-s3Xf7xRPWHfcFF4tiG470eHa1+iaBgLNrRKXaTYpmfJTO5vDV7g+zEboq0jno1zTrD0bS7QTPRE+4A5R9OlbDg==", + "version": "0.1.52", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.52.tgz", + "integrity": "sha512-BLbPvCm/CnuixH9kLbqPC2l7GLJQfxhjf/hRCTpfadUybSiMkYA1HOSXCBT4QY4CP5PsfzZC0L7llRCoDSNAyQ==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", @@ -8501,6 +8504,112 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8699,11 +8808,11 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-router": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.25.1.tgz", - "integrity": "sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.0.tgz", + "integrity": "sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==", "dependencies": { - "@remix-run/router": "1.18.0" + "@remix-run/router": "1.19.0" }, "engines": { "node": ">=14.0.0" @@ -8713,12 +8822,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.25.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.25.1.tgz", - "integrity": "sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ==", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.0.tgz", + "integrity": "sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==", "dependencies": { - "@remix-run/router": "1.18.0", - "react-router": "6.25.1" + "@remix-run/router": "1.19.0", + "react-router": "6.26.0" }, "engines": { "node": ">=14.0.0" @@ -8980,9 +9089,9 @@ } }, "node_modules/rimraf": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.9.tgz", - "integrity": "sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA==", + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dev": true, "dependencies": { "glob": "^10.3.7" @@ -8990,9 +9099,6 @@ "bin": { "rimraf": "dist/esm/bin.mjs" }, - "engines": { - "node": "14 >=14.20 || 16 >=16.20 || >=18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -10315,9 +10421,9 @@ } }, "node_modules/undici-types": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz", - "integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==" + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -10625,9 +10731,9 @@ "dev": true }, "node_modules/webpack-dev-middleware/node_modules/memfs": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.0.tgz", - "integrity": "sha512-+6kz90/YQoZuHvg3rn1CGPMZfEMaU5xe7xIavZMNiom2RNesiI8S37p9O9n+PlIUnUgretjLdM6HnqpZYl3X2g==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", + "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", "dev": true, "dependencies": { "@jsonjoy.com/json-pack": "^1.0.3", diff --git a/client/package.json b/client/package.json index 804a122d6..49de616ce 100644 --- a/client/package.json +++ b/client/package.json @@ -45,7 +45,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.35", + "haengdong-design": "^0.1.51", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/components/Modal/Modal.style.ts b/client/src/components/Modal/Modal.style.ts deleted file mode 100644 index 727d0482f..000000000 --- a/client/src/components/Modal/Modal.style.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {css} from '@emotion/react'; - -export const modalBodyStyle = css` - z-index: 100; - background-color: white; - position: fixed; - bottom: 0; - left: 0; - right: 0; - padding: 20px; - border-radius: 20px 20px 0 0; - box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); -`; - -export const modalBackdropStyle = css` - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.5); - z-index: 99; -`; diff --git a/client/src/components/Modal/SetActionModalContent/SetPurchase.style.ts b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.style.ts similarity index 61% rename from client/src/components/Modal/SetActionModalContent/SetPurchase.style.ts rename to client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.style.ts index cc852da28..80c770362 100644 --- a/client/src/components/Modal/SetActionModalContent/SetPurchase.style.ts +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.style.ts @@ -1,11 +1,11 @@ import {css} from '@emotion/react'; -export const setPurchaseStyle = () => +const container = () => css({ height: '100%', }); -export const setPurchaseInputContainerStyle = () => +const inputContainer = () => css({ display: 'flex', height: '100%', @@ -15,9 +15,17 @@ export const setPurchaseInputContainerStyle = () => paddingBottom: '14rem', }); -export const setPurchaseInputStyle = () => +export const input = () => css({ display: 'flex', flexDirection: 'column', gap: '0.5rem', }); + +const addBillActionListStyle = { + container, + inputContainer, + input, +}; + +export default addBillActionListStyle; diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx new file mode 100644 index 000000000..873fe8118 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -0,0 +1,74 @@ +import {FixedButton, LabelGroupInput} from 'haengdong-design'; + +import {useStepList} from '@hooks/useStepList/useStepList'; +import validatePurchase from '@utils/validate/validatePurchase'; + +import useDynamicBillActionInput from '@hooks/useDynamicBillActionInput'; + +import style from './AddBillActionListModalContent.style'; + +interface SetPurchaseProps { + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setOrder: React.Dispatch<React.SetStateAction<number>>; +} + +const AddBillActionListModalContent = ({setOpenBottomSheet, setOrder}: SetPurchaseProps) => { + const { + inputPairList, + inputRefList, + handleInputChange, + getFilledInputPairList, + deleteEmptyInputPairElementOnBlur, + focusNextInputOnEnter, + } = useDynamicBillActionInput(validatePurchase); + const {addBill} = useStepList(); + + const handleSetPurchaseSubmit = () => { + setOrder(prev => prev + 1); + + // TODO: (@weadie) 요청 실패시 오류 핸들 필요 + addBill(getFilledInputPairList().map(({title, price}) => ({title, price: Number(price)}))); // TODO: (@weadie) DTO같은게 다이내믹에 필요할까? + setOpenBottomSheet(false); + }; + + return ( + <div css={style.container}> + <div css={style.inputContainer}> + <LabelGroupInput labelText="지출내역 / 금액"> + {inputPairList.map(({index, title, price}) => ( + <div key={index} css={style.input}> + <LabelGroupInput.Element + elementKey={`${index}`} + type="text" + value={title} + onChange={e => handleInputChange(index, 'title', e)} + onKeyDown={e => focusNextInputOnEnter(e, index, 'title')} + onBlur={() => deleteEmptyInputPairElementOnBlur()} // TODO: (@weadie) 이 블러프롭이 내부적으로 index를 넘기고 있기 때문에 화살표 함수로 써야만하내요.. + placeholder="지출 내역" + ref={el => (inputRefList.current[index * 2] = el)} + /> + <LabelGroupInput.Element + elementKey={`${index}`} + type="number" + value={price} + onChange={e => handleInputChange(index, 'price', e)} + onKeyDown={e => focusNextInputOnEnter(e, index, 'price')} + onBlur={() => deleteEmptyInputPairElementOnBlur()} + placeholder="금액" + ref={el => (inputRefList.current[index * 2 + 1] = el)} + /> + </div> + ))} + </LabelGroupInput> + </div> + <FixedButton + // disabled={!(inputPairs.length - 1)} + variants={'primary'} + children={'추가하기'} + onClick={handleSetPurchaseSubmit} + /> + </div> + ); +}; + +export default AddBillActionListModalContent; diff --git a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.style.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts similarity index 60% rename from client/src/components/Modal/SetActionModalContent/UpdateParticipants.style.ts rename to client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts index 087e25a85..6162d55b5 100644 --- a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.style.ts +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -export const updateParticipantsStyle = () => +const container = () => css({ display: 'flex', flexDirection: 'column', @@ -8,7 +8,7 @@ export const updateParticipantsStyle = () => height: '100%', }); -export const updateParticipantsInputStyle = () => +const inputGroup = () => css({ display: 'flex', flexDirection: 'column', @@ -16,3 +16,10 @@ export const updateParticipantsInputStyle = () => overflow: 'auto', paddingBottom: '14rem', }); + +const addMemberActionListModalContentStyle = { + container, + inputGroup, +}; + +export default addMemberActionListModalContentStyle; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx new file mode 100644 index 000000000..59894493c --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -0,0 +1,65 @@ +import {FixedButton, LabelGroupInput} from 'haengdong-design'; + +import {useStepList} from '@hooks/useStepList/useStepList'; +import validateMemberName from '@utils/validate/validateMemberName'; +import {MemberType} from 'types/serviceType'; + +import useDynamicInput from '@hooks/useDynamicInput'; + +import style from './AddMemberActionListModalContent.style'; + +interface UpdateMembersProps { + inOutAction: MemberType; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; +} + +const AddMemberActionListModalContent = ({inOutAction, setOpenBottomSheet}: UpdateMembersProps) => { + const { + inputList, + inputRefList, + handleInputChange, + deleteEmptyInputElementOnBlur, + getFilledInputList, + errorMessage, + canSubmit, + focusNextInputOnEnter, + } = useDynamicInput(validateMemberName); + + const {updateMemberList} = useStepList(); + + const handleUpdateMemberListSubmit = () => { + updateMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); + setOpenBottomSheet(false); + }; + + return ( + <div css={style.container}> + <div css={style.inputGroup}> + {/* TODO: (@soha) Search로 변경하기 */} + <LabelGroupInput labelText="이름" errorText={errorMessage}> + {inputList.map(({value, index}) => ( + <LabelGroupInput.Element + key={`${index}`} + elementKey={`${index}`} + type="text" + value={`${value}`} + ref={el => (inputRefList.current[index] = el)} + onChange={e => handleInputChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + placeholder="이름" + /> + ))} + </LabelGroupInput> + </div> + <FixedButton + disabled={!canSubmit} + variants={'primary'} + children={`${inputList.length - 1}명 ${inOutAction === 'OUT' ? '탈주' : '늦참'}`} + onClick={handleUpdateMemberListSubmit} + /> + </div> + ); +}; + +export default AddMemberActionListModalContent; diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.ts b/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts similarity index 58% rename from client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.ts rename to client/src/components/Modal/SetActionModal/SetActionListModal.style.ts index 560f672d5..ca6703309 100644 --- a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.style.ts +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -export const setActionModalContentStyle = css({ +export const container = css({ display: 'flex', flexDirection: 'column', width: '100%', @@ -9,8 +9,12 @@ export const setActionModalContentStyle = css({ gap: '1.5rem', }); -export const setActionModalContentSwitchContainerStyle = css({ +export const switchContainer = css({ display: 'flex', width: '100%', justifyContent: 'space-between', }); + +const setActionListModalStyle = {container, switchContainer}; + +export default setActionListModalStyle; diff --git a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx similarity index 72% rename from client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx rename to client/src/components/Modal/SetActionModal/SetActionListModal.tsx index b3ccd64c9..f33597334 100644 --- a/client/src/components/Modal/SetActionModalContent/SetActionModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -1,9 +1,9 @@ import {useState} from 'react'; import {BottomSheet, Switch} from 'haengdong-design'; -import SetPurchase from './SetPurchase'; -import UpdateParticipants from './UpdateParticipants'; -import {setActionModalContentStyle, setActionModalContentSwitchContainerStyle} from './SetActionModalContent.style'; +import SetPurchase from './AddBillActionListModalContent/AddBillActionListModalContent'; +import AddMemberActionListModalContent from './AddMemberActionListModalContent/AddMemberActionListModalContent'; +import style from './SetActionListModal.style'; export type ActionType = '지출' | '인원'; @@ -13,7 +13,7 @@ interface SetActionModalContentProps { setOrder: React.Dispatch<React.SetStateAction<number>>; } -const SetActionModalContent = ({openBottomSheet, setOpenBottomSheet, setOrder}: SetActionModalContentProps) => { +const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: SetActionModalContentProps) => { const [action, setAction] = useState<ActionType>('지출'); const [inOutAction, setInOutAction] = useState<InOutType>('탈주'); @@ -27,8 +27,8 @@ const SetActionModalContent = ({openBottomSheet, setOpenBottomSheet, setOrder}: return ( <BottomSheet isOpened={openBottomSheet} onChangeClose={() => setOpenBottomSheet(false)}> - <div css={setActionModalContentStyle}> - <div css={setActionModalContentSwitchContainerStyle}> + <div css={style.container}> + <div css={style.switchContainer}> <Switch value={action} onChange={handleActionTypeChange} values={['지출', '인원']} /> {action === '인원' && ( <Switch values={['늦참', '탈주']} value={inOutAction} onChange={handleParticipantTypeChange} /> @@ -37,7 +37,7 @@ const SetActionModalContent = ({openBottomSheet, setOpenBottomSheet, setOrder}: {action === '지출' && <SetPurchase setOpenBottomSheet={setOpenBottomSheet} setOrder={setOrder} />} {action === '인원' && ( - <UpdateParticipants + <AddMemberActionListModalContent inOutAction={inOutAction === '탈주' ? 'OUT' : 'IN'} setOpenBottomSheet={setOpenBottomSheet} /> @@ -47,4 +47,4 @@ const SetActionModalContent = ({openBottomSheet, setOpenBottomSheet, setOrder}: ); }; -export default SetActionModalContent; +export default SetActionListModal; diff --git a/client/src/components/Modal/SetActionModal/index.ts b/client/src/components/Modal/SetActionModal/index.ts new file mode 100644 index 000000000..f689cb596 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/index.ts @@ -0,0 +1 @@ +export {default as SetActionListModal} from './SetActionListModal'; diff --git a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx b/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx deleted file mode 100644 index a83a697a7..000000000 --- a/client/src/components/Modal/SetActionModalContent/SetPurchase.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import {Input, FixedButton} from 'haengdong-design'; - -import {useStepList} from '@hooks/useStepList/useStepList'; - -import useDynamicInputPairs from '@hooks/useDynamicInputPairs'; - -import {setPurchaseInputStyle, setPurchaseStyle, setPurchaseInputContainerStyle} from './SetPurchase.style'; - -interface SetPurchaseProps { - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; - setOrder: React.Dispatch<React.SetStateAction<number>>; -} - -const SetPurchase = ({setOpenBottomSheet, setOrder}: SetPurchaseProps) => { - const {inputPairs, inputRefs, handleInputChange, handleInputBlur, getNonEmptyInputPairs} = useDynamicInputPairs(); - const {addBill} = useStepList(); - - const handleSetPurchaseSubmit = () => { - setOrder(prev => prev + 1); - - // TODO: (@weadie) 요청 실패시 오류 핸들 필요 - addBill(getNonEmptyInputPairs()); - setOpenBottomSheet(false); - }; - - return ( - <div css={setPurchaseStyle}> - <div css={setPurchaseInputContainerStyle}> - {inputPairs.map((pair, index) => ( - <div key={index} css={setPurchaseInputStyle}> - <Input - type="text" - value={pair.title} - onChange={e => handleInputChange(index, 'title', e.target.value)} - onBlur={() => handleInputBlur(index)} - placeholder="지출 내역" - ref={el => (inputRefs.current[index * 2] = el)} - /> - <Input - type="number" - value={pair.price} - onChange={e => handleInputChange(index, 'price', e.target.value)} - onBlur={() => handleInputBlur(index)} - placeholder="금액" - ref={el => (inputRefs.current[index * 2 + 1] = el)} - /> - </div> - ))} - </div> - <FixedButton - disabled={!(inputPairs.length - 1)} - variants={'primary'} - children={'추가하기'} - onClick={handleSetPurchaseSubmit} - /> - </div> - ); -}; - -export default SetPurchase; diff --git a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx b/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx deleted file mode 100644 index 5adc3cd43..000000000 --- a/client/src/components/Modal/SetActionModalContent/UpdateParticipants.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import {Input, FixedButton} from 'haengdong-design'; - -import {useStepList} from '@hooks/useStepList/useStepList'; - -import useDynamicInput from '@hooks/useDynamicAdditionalInput'; - -import {updateParticipantsInputStyle, updateParticipantsStyle} from './UpdateParticipants.style'; - -interface UpdateParticipantsProps { - inOutAction: MemberType; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -} - -const UpdateParticipants = ({inOutAction, setOpenBottomSheet}: UpdateParticipantsProps) => { - const {inputs, inputRefs, handleInputChange, handleInputBlur, getNonEmptyInputs} = useDynamicInput(); - const {updateMemberList} = useStepList(); - - const handleUpdateParticipantsSubmit = () => { - updateMemberList({memberNameList: getNonEmptyInputs(), type: inOutAction}); - setOpenBottomSheet(false); - }; - - return ( - <div css={updateParticipantsStyle}> - <div css={updateParticipantsInputStyle}> - {/* TODO: (@soha) Search로 변경하기 */} - {inputs.map((name, index) => ( - <Input - key={index} - placeholder="이름" - value={name} - type="text" - ref={el => (inputRefs.current[index] = el)} - onChange={e => handleInputChange(index, e.target.value)} - onBlur={() => handleInputBlur(index)} - /> - ))} - </div> - <FixedButton - disabled={!(inputs.length - 1)} - variants={'primary'} - children={`${inputs.length - 1}명 ${inOutAction === 'OUT' ? '탈주' : '늦참'}`} - onClick={handleUpdateParticipantsSubmit} - /> - </div> - ); -}; - -export default UpdateParticipants; diff --git a/client/src/components/Modal/SetActionModalContent/index.ts b/client/src/components/Modal/SetActionModalContent/index.ts deleted file mode 100644 index c7514135c..000000000 --- a/client/src/components/Modal/SetActionModalContent/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as SetActionModalContent} from './SetActionModalContent'; diff --git a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts similarity index 73% rename from client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts rename to client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts index f0f5bf996..ed835682c 100644 --- a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.style.ts +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -export const setInitialParticipantsStyle = () => +export const setInitialMemberListModalStyle = () => css({ display: 'flex', flexDirection: 'column', @@ -10,7 +10,7 @@ export const setInitialParticipantsStyle = () => padding: '0 1.5rem', }); -export const setInitialParticipantsInputGroupStyle = () => +export const setInitialMemberListModalInputGroupStyle = () => css({ display: 'flex', flexDirection: 'column', diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx new file mode 100644 index 000000000..4546e0540 --- /dev/null +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -0,0 +1,62 @@ +import {Text, BottomSheet, FixedButton, LabelGroupInput} from 'haengdong-design'; + +import {useStepList} from '@hooks/useStepList/useStepList'; +import validateMemberName from '@utils/validate/validateMemberName'; + +import useDynamicInput from '@hooks/useDynamicInput'; + +import { + setInitialMemberListModalInputGroupStyle, + setInitialMemberListModalStyle, +} from './SetInitialMemberListModal.style'; + +interface SetInitialMemberListProps { + openBottomSheet: boolean; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; +} + +const SetInitialMemberListModal = ({openBottomSheet, setOpenBottomSheet}: SetInitialMemberListProps) => { + const { + inputList, + inputRefList, + handleInputChange, + deleteEmptyInputElementOnBlur, + getFilledInputList, + errorMessage, + canSubmit, + focusNextInputOnEnter, + } = useDynamicInput(validateMemberName); + const {updateMemberList} = useStepList(); + + const handleSubmit = () => { + updateMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); + setOpenBottomSheet(false); + }; + + return ( + <BottomSheet isOpened={openBottomSheet} onChangeClose={() => setOpenBottomSheet(false)}> + <div css={setInitialMemberListModalStyle}> + <Text size="bodyBold">초기 인원 설정하기</Text> + <div css={setInitialMemberListModalInputGroupStyle}> + <LabelGroupInput labelText="이름" errorText={errorMessage}> + {inputList.map(({value, index}) => ( + <LabelGroupInput.Element + key={`${index}`} + elementKey={`${index}`} + type="text" + value={value} + ref={el => (inputRefList.current[index] = el)} + onChange={e => handleInputChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + /> + ))} + </LabelGroupInput> + </div> + </div> + <FixedButton disabled={!canSubmit} variants={'primary'} onClick={handleSubmit} children={'인원 설정 완료'} /> + </BottomSheet> + ); +}; + +export default SetInitialMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/index.ts b/client/src/components/Modal/SetInitialMemberListModal/index.ts new file mode 100644 index 000000000..18098e4f6 --- /dev/null +++ b/client/src/components/Modal/SetInitialMemberListModal/index.ts @@ -0,0 +1 @@ +export {default as SetInitialMemberListModal} from './SetInitialMemberListModal'; diff --git a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx b/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx deleted file mode 100644 index e5dda7c96..000000000 --- a/client/src/components/Modal/SetInitialParticipants/SetInitialParticipants.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import {Text, Input, BottomSheet, FixedButton} from 'haengdong-design'; - -import {useStepList} from '@hooks/useStepList/useStepList'; - -import useDynamicInput from '@hooks/useDynamicAdditionalInput'; - -import {setInitialParticipantsInputGroupStyle, setInitialParticipantsStyle} from './SetInitialParticipants.style'; - -interface SetInitialParticipantsProps { - openBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -} - -const SetInitialParticipants = ({openBottomSheet, setOpenBottomSheet}: SetInitialParticipantsProps) => { - const {inputs, inputRefs, handleInputChange, handleInputBlur, getNonEmptyInputs} = useDynamicInput(); - const {updateMemberList} = useStepList(); - - const handleSubmit = () => { - updateMemberList({memberNameList: getNonEmptyInputs(), type: 'IN'}); - setOpenBottomSheet(false); - }; - - return ( - <BottomSheet isOpened={openBottomSheet} onChangeClose={() => setOpenBottomSheet(false)}> - <div css={setInitialParticipantsStyle}> - <Text size="bodyBold">초기 인원 설정하기</Text> - <div css={setInitialParticipantsInputGroupStyle}> - {inputs.map((participant, index) => ( - <Input - key={index} - placeholder="이름" - type="text" - value={participant} - ref={el => (inputRefs.current[index] = el)} - onChange={e => handleInputChange(index, e.target.value)} - onBlur={() => handleInputBlur(index)} - /> - ))} - </div> - </div> - <FixedButton - disabled={!(inputs.length - 1)} - variants={'primary'} - onClick={handleSubmit} - children={'인원 설정 완료'} - /> - </BottomSheet> - ); -}; - -export default SetInitialParticipants; diff --git a/client/src/components/Modal/SetInitialParticipants/index.ts b/client/src/components/Modal/SetInitialParticipants/index.ts deleted file mode 100644 index c41b6a206..000000000 --- a/client/src/components/Modal/SetInitialParticipants/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as SetInitialParticipants} from './SetInitialParticipants'; diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts index e5d5264cd..36ccd8b2e 100644 --- a/client/src/components/Modal/index.ts +++ b/client/src/components/Modal/index.ts @@ -1,2 +1,2 @@ -export {default as SetInitialParticipants} from './SetInitialParticipants/SetInitialParticipants'; -export {default as SetActionModalContent} from './SetActionModalContent/SetActionModalContent'; +export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; +export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts new file mode 100644 index 000000000..e37220f7f --- /dev/null +++ b/client/src/constants/errorMessage.ts @@ -0,0 +1,8 @@ +const ERROR_MESSAGE = { + eventName: '행사 이름은 30자 이하만 가능해요', + memberName: '참여자 이름은 8자 이하의 한글, 영어만 가능해요', + purchasePrice: '10,000,000원 이하의 숫자만 입력이 가능해요', + purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', +}; + +export default ERROR_MESSAGE; diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts new file mode 100644 index 000000000..674be7ba2 --- /dev/null +++ b/client/src/constants/regExp.ts @@ -0,0 +1,6 @@ +const REGEXP = { + memberName: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s]*$/, + purchaseTitle: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s]*$/, +}; + +export default REGEXP; diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts new file mode 100644 index 000000000..0001cb73a --- /dev/null +++ b/client/src/constants/rule.ts @@ -0,0 +1,7 @@ +const RULE = { + maxEventNameLength: 30, + maxMemberNameLength: 8, + maxPrice: 10000000, +}; + +export default RULE; diff --git a/client/src/hooks/useDynamicAdditionalInput.tsx b/client/src/hooks/useDynamicAdditionalInput.tsx deleted file mode 100644 index 6bd592254..000000000 --- a/client/src/hooks/useDynamicAdditionalInput.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import {useEffect, useRef, useState} from 'react'; - -const useDynamicInput = () => { - const [inputs, setInputs] = useState<string[]>(['']); - const inputRefs = useRef<(HTMLInputElement | null)[]>([]); - - // TODO: (@soha) 입력이 완료되고 중간에 값을 모두 지웠을 경우 Input이 없애지도록 수정하기 - const handleInputChange = (index: number, value: string) => { - const newInputs = [...inputs]; - newInputs[index] = value; - setInputs(newInputs); - }; - - const handleInputBlur = (index: number) => { - if (inputs[index].trim() === '') { - setInputs(prev => { - const newInputs = [...prev]; - newInputs[index] = ''; - return newInputs; - }); - } else if (inputs[index].trim() !== '' && index === inputs.length - 1) { - setInputs(prev => { - const newInputs = [...prev, '']; - newInputs[index] = inputs[index].trim(); - return newInputs; - }); - } - }; - - const getNonEmptyInputs = () => { - return inputs.filter(input => input.trim() !== ''); - }; - - useEffect(() => { - if (inputRefs.current.length > 0) { - const lastInput = inputRefs.current[inputRefs.current.length - 1]; - if (lastInput) { - lastInput.scrollIntoView({behavior: 'smooth', block: 'center'}); - } - } - }, [inputs]); - - return { - inputs, - inputRefs, - handleInputChange, - handleInputBlur, - getNonEmptyInputs, - }; -}; - -export default useDynamicInput; diff --git a/client/src/hooks/useDynamicBillActionInput.tsx b/client/src/hooks/useDynamicBillActionInput.tsx new file mode 100644 index 000000000..f81e0b114 --- /dev/null +++ b/client/src/hooks/useDynamicBillActionInput.tsx @@ -0,0 +1,142 @@ +import {useEffect, useRef, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; +import {Bill} from 'types/serviceType'; + +type InputPair = Omit<Bill, 'price'> & { + price: string; + index: number; +}; + +type BillInputType = 'title' | 'price'; + +// TODO: (@weadie) 지나치게 도메인에 묶여있는 인풋. 절대 다른 페어인풋으로 재사용할 수 없다. +const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateResult) => { + const [inputPairList, setInputPairList] = useState<InputPair[]>([{title: '', price: '', index: 0}]); + const inputRefList = useRef<(HTMLInputElement | null)[]>([]); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + + useEffect(() => { + if (inputRefList.current.length > 0) { + const lastInputPair = inputRefList.current.slice(-2); + lastInputPair.forEach(ref => ref?.scrollIntoView({behavior: 'smooth', block: 'center'})); + } + }, [inputPairList]); + + const handleInputChange = (index: number, field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { + const {value} = event.target; + const targetInputPair = findInputPairByIndex(index); + const {isValid: isValidInput, errorMessage: validationResultMessage} = validateFunc({ + ...targetInputPair, + price: 0, // price가 input에서 0을 초기값으로 갖지않도록 타입을 수정했기 때문에 0을 명시적으로 넘겨줍니다. + [field]: value, + }); + + const {title, price} = targetInputPair; + + // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수로 분리 + if (isLastInputPairFilled({index, field, value})) { + setErrorMessage(''); + setInputPairList(prevInputPairList => { + const updatedInputPairList = [...prevInputPairList]; + const targetInputPair = findInputPairByIndex(index, updatedInputPairList); + + targetInputPair[field] = value; + + // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 + const newIndex = updatedInputPairList[updatedInputPairList.length - 1].index + 1; + const finalInputs = [...updatedInputPairList, {index: newIndex, title: '', price: ''}]; + + return finalInputs; + }); + } else if (isValidInput || value.length === 0) { + setErrorMessage(''); + setInputPairList(prevInputPairList => { + const updatedInputPairList = [...prevInputPairList]; + const targetInputPair = findInputPairByIndex(index, updatedInputPairList); + + targetInputPair[field] = value; + + return updatedInputPairList; + }); + } else { + const targetInput = findInputPairByIndex(index); + + event.target.value = targetInput[field]; + + setErrorMessage(validationResultMessage ?? ''); + } + + handleCanSubmit(); + }; + + const deleteEmptyInputPairElementOnBlur = () => { + // 이름, 금액 2개중 최소 하나 이상 값을 가지고 있는 inputPair 배열 + const filledMinInputPairList = inputPairList.filter(({title, price}) => title !== '' || price !== ''); + + // 0쌍, 1쌍 input이 값이 있는 상태에서 두 쌍의 값을 모두 x버튼으로 제거해도 입력 쌍이 2개 남아있는 문제를 위해 조건문을 추가했습니다. + if (filledMinInputPairList.length === 0 && inputPairList.length > 1) { + setInputPairList([{index: 0, title: '', price: ''}]); + return; + } + + if (filledMinInputPairList.length === 0) return; + + if (filledMinInputPairList.length !== inputPairList.length) { + // 이름, 금액 2개중 하나라도 값이 있다면 지우지 않습니다. + setInputPairList(prevInputPairList => { + const filledInputPairList = prevInputPairList.filter(({title, price}) => title !== '' || price !== ''); + + const newIndex = filledInputPairList[filledInputPairList.length - 1].index + 1; + return [...filledInputPairList, {index: newIndex, title: '', price: ''}]; + }); + } + }; + + const handleCanSubmit = () => { + setCanSubmit(inputPairList.length > 0 && getFilledInputPairList().length > 0); + }; + + const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number, field: BillInputType) => { + if (e.nativeEvent.isComposing) return; + + if (e.key === 'Enter') { + // 2개(제목, 가격)를 쌍으로 index를 관리하고 있으므로 input element 정확히 특정하기 위한 개별 input element key 값을 계산합니다. + const exactInputIndex = index * 2 + (field === 'title' ? 0 : 1); + + inputRefList.current[exactInputIndex + 1]?.focus(); + } + }; + + // 아래부터는 이 훅에서 재사용되는 함수입니다. + + // list 인자를 넘겨주면 그 인자로 찾고, 없다면 InputPairList state를 사용합니다. + const findInputPairByIndex = (index: number, list?: InputPair[]) => { + return (list ?? inputPairList).filter(input => input.index === index)[0]; + }; + + // list 인자를 넘겨주면 그 인자로 찾고, 없다면 InputPairList state를 사용합니다. + const getFilledInputPairList = (list?: InputPair[]) => { + return (list ?? inputPairList).filter(({title, price}) => title !== '' && price !== ''); + }; + + const isLastInputPairFilled = ({index, value}: {index: number; field: BillInputType; value: string}) => { + const lastInputIndex = inputPairList[inputPairList.length - 1].index; + + return value !== '' && index === lastInputIndex; + }; + + return { + inputPairList, + getFilledInputPairList, + inputRefList, + handleInputChange, + deleteEmptyInputPairElementOnBlur, + errorMessage, + canSubmit, + focusNextInputOnEnter, + }; +}; + +export default useDynamicBillActionInput; diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx new file mode 100644 index 000000000..8588c2c40 --- /dev/null +++ b/client/src/hooks/useDynamicInput.tsx @@ -0,0 +1,139 @@ +import {useEffect, useRef, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; + +type InputValue = { + value: string; + index: number; +}; + +const useDynamicInput = (validateFunc: (name: string) => ValidateResult) => { + const [inputList, setInputList] = useState<InputValue[]>([{value: '', index: 0}]); + const inputRefList = useRef<(HTMLInputElement | null)[]>([]); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + + useEffect(() => { + if (inputRefList.current.length <= 0) return; + + const lastInput = inputRefList.current[inputRefList.current.length - 1]; + + if (lastInput) { + lastInput.scrollIntoView({behavior: 'smooth', block: 'center'}); + } + }, [inputList]); + + const handleInputChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { + const {value} = event.target; + const {isValid: isValidInput, errorMessage: validationResultMessage} = validateFunc(value); + + // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수 분리필요 + if (isLastInputFilled(index, value)) { + // 마지막 인풋이 한 자라도 채워진다면 새로운 인풋을 생성해 간편한 다음 입력을 유도합니다. + + setErrorMessage(''); + setInputList(prevInputs => { + const updatedInputList = [...prevInputs]; + const targetInput = findInputByIndex(index, updatedInputList); + + targetInput.value = value; + + // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 + const newIndex = updatedInputList[updatedInputList.length - 1].index + 1; + + return [...updatedInputList, {index: newIndex, value: ''}]; + }); + } else if (isValidInput || value.length === 0) { + // 인풋이 비어있다면 새로운 인풋을 생성하지 않습니다. + + setErrorMessage(''); + setInputList(prevInputs => { + const updatedInputList = [...prevInputs]; + const targetInput = findInputByIndex(index, updatedInputList); + + targetInput.value = value; + + return updatedInputList; + }); + } else { + // 유효성 검사에 실패한 입력입니다. 이전 입력으로 복구하고 에러 메세지를 세팅합니다. + + // index에 해당하는 아이템을 찾습니다. + const targetInput = findInputByIndex(index); + + // 오류가 난 값말고 기존의 값을 사용합니다. + event.target.value = targetInput.value; + + setErrorMessage(validationResultMessage ?? ''); + } + + handleCanSubmit(); + }; + + // 현재까지 입력된 값들로 submit을 할 수 있는지 여부를 핸들합니다. + const handleCanSubmit = () => { + setCanSubmit(inputList.length > 0 && getFilledInputList().length > 0); + }; + + const deleteEmptyInputElementOnBlur = () => { + // 0, 1번 input이 값이 있는 상태에서 두 input의 값을 모두 x버튼으로 제거해도 input이 2개 남아있는 문제를 위해 조건문을 추가했습니다. + if (getFilledInputList().length === 0 && inputList.length > 1) { + setInputList([{index: 0, value: ''}]); + return; + } + + // *표시 조건문은 처음에 input을 클릭했다가 블러시켰을 때 filledInputList가 아예 없어 .index에 접근할 때 오류가 납니다. 이를 위한 얼리리턴을 두었습니다. + if (getFilledInputList().length === 0) return; + + // * + if (getFilledInputList().length !== inputList.length) { + setInputList(inputList => { + const filledInputList = getFilledInputList(inputList); + + // 새 입력의 인덱스를 inputs 길이를 기준으로 설정 + const newIndex = filledInputList[filledInputList.length - 1].index + 1; + + return [...filledInputList, {index: newIndex, value: ''}]; + }); + } + }; + + const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => { + if (e.nativeEvent.isComposing) return; + + if (e.key === 'Enter') { + inputRefList.current[index + 1]?.focus(); + } + }; + // 아래부터는 이 훅에서 재사용되는 함수입니다. + + // list 인자를 넘겨주면 그 인자로 찾고, 없다면 inputList state를 사용합니다. + const findInputByIndex = (index: number, list?: InputValue[]) => { + return (list ?? inputList).filter(input => input.index === index)[0]; + }; + + // list 인자를 넘겨주면 그 인자로 찾고, 없다면 inputList state를 사용합니다. + const getFilledInputList = (list?: InputValue[]) => { + return (list ?? inputList).filter(({value}) => value !== ''); + }; + + const isLastInputFilled = (index: number, value: string) => { + const lastInputIndex = inputList[inputList.length - 1].index; + + return value !== '' && index === lastInputIndex; + }; + + return { + inputList, + inputRefList, + handleInputChange, + deleteEmptyInputElementOnBlur, + errorMessage, + getFilledInputList, + focusNextInputOnEnter, + canSubmit, + // TODO: (@weadie) 네이밍 수정 + }; +}; + +export default useDynamicInput; diff --git a/client/src/hooks/useDynamicInputPairs.tsx b/client/src/hooks/useDynamicInputPairs.tsx deleted file mode 100644 index b6f86b000..000000000 --- a/client/src/hooks/useDynamicInputPairs.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import {useEffect, useRef, useState} from 'react'; - -const useDynamicInputPairs = () => { - const [inputPairs, setInputPairs] = useState<Bill[]>([{title: '', price: 0}]); - const inputRefs = useRef<(HTMLInputElement | null)[]>([]); - - const handleInputChange = (index: number, field: 'title' | 'price', value: string) => { - const newInputPairs = [...inputPairs]; - newInputPairs[index] = { - ...newInputPairs[index], - [field]: field === 'price' ? parseFloat(value) : value, - }; - setInputPairs(newInputPairs); - }; - - const handleInputBlur = (index: number) => { - const currentPair = inputPairs[index]; - if (currentPair.title.trim() === '' && currentPair.price === 0) { - setInputPairs(prev => prev.filter((_, i) => i !== index)); - } else if (currentPair.title.trim() !== '' && currentPair.price !== 0 && index === inputPairs.length - 1) { - setInputPairs(prev => [...prev, {title: '', price: 0}]); - } - }; - - const getNonEmptyInputPairs = () => { - return inputPairs.filter(currentPair => currentPair.title.trim() !== '' && currentPair.price !== 0); - }; - - useEffect(() => { - if (inputRefs.current.length > 0) { - const lastInputPair = inputRefs.current.slice(-2); - lastInputPair.forEach(ref => ref?.scrollIntoView({behavior: 'smooth', block: 'center'})); - } - }, [inputPairs]); - - return { - inputPairs, - getNonEmptyInputPairs, - inputRefs, - handleInputChange, - handleInputBlur, - }; -}; - -export default useDynamicInputPairs; diff --git a/client/src/pages/Create/Name.tsx b/client/src/pages/Create/Name.tsx deleted file mode 100644 index c16870430..000000000 --- a/client/src/pages/Create/Name.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import {useState} from 'react'; -import {useNavigate} from 'react-router-dom'; -import {FixedButton, Input, MainLayout, Title, TopNav, Back} from 'haengdong-design'; - -import {requestCreateNewEvent} from '@apis/request/event'; - -import {ROUTER_URLS} from '@constants/routerUrls'; - -const CreateEvent = () => { - const [eventName, setEventName] = useState(''); - const navigate = useNavigate(); - - const submitEventName = async (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - - const response = await requestCreateNewEvent({eventName}); - - if (response) { - const {eventId} = response; - navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`); - } else { - // TODO: (@weadie) - alert('오류님'); - } - }; - - return ( - <MainLayout> - <TopNav> - <Back /> - </TopNav> - <Title title="행사 이름 입력" description="시작할 행사 이름을 입력해 주세요." /> - <form onSubmit={submitEventName} style={{padding: '0 1rem'}}> - <Input - value={eventName} - onChange={event => setEventName(event.target.value)} - onBlur={() => setEventName(eventName.trim())} - placeholder="ex) 행동대장 야유회" - /> - <FixedButton disabled={!eventName.length}>행동 개시!</FixedButton> - </form> - </MainLayout> - ); -}; - -export default CreateEvent; diff --git a/client/src/pages/Create/index.ts b/client/src/pages/Create/index.ts deleted file mode 100644 index 5ce37a93e..000000000 --- a/client/src/pages/Create/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {default as CreateNamePage} from './Name'; -export {default as CreateCompletePage} from './Complete'; diff --git a/client/src/pages/Create/Complete.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx similarity index 93% rename from client/src/pages/Create/Complete.tsx rename to client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 786979607..0f30c1f04 100644 --- a/client/src/pages/Create/Complete.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -4,7 +4,7 @@ import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; import {ROUTER_URLS} from '@constants/routerUrls'; -const CompleteCreateEvent = () => { +const CompleteCreateEventPage = () => { const [url, setUrl] = useState(''); const navigate = useNavigate(); const location = useLocation(); @@ -35,4 +35,4 @@ const CompleteCreateEvent = () => { ); }; -export default CompleteCreateEvent; +export default CompleteCreateEventPage; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx new file mode 100644 index 000000000..4da51dd98 --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -0,0 +1,67 @@ +import {useState} from 'react'; +import {useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, LabelInput, Input, Title, TopNav, Back} from 'haengdong-design'; + +import {requestCreateNewEvent} from '@apis/request/event'; +import validateEventName from '@utils/validate/validateEventName'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const SetEventNamePage = () => { + const [eventName, setEventName] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const navigate = useNavigate(); + + const submitEventName = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + const response = await requestCreateNewEvent({eventName}); + + if (response) { + const {eventId} = response; + navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`); + } else { + // TODO: (@weadie) + alert('오류님'); + } + }; + + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + const validation = validateEventName(newValue); + + setCanSubmit(newValue.length !== 0); + + if (validation.isValid) { + setEventName(newValue); + setErrorMessage(''); + } else { + event.target.value = eventName; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + return ( + <MainLayout> + <TopNav> + <Back /> + </TopNav> + <Title title="행사 이름 입력" description="시작할 행사 이름을 입력해 주세요." /> + <form onSubmit={submitEventName} style={{padding: '0 1rem'}}> + <LabelInput + labelText="행사 이름" + errorText={errorMessage} + value={eventName} + type="text" + placeholder="행사 이름" + onChange={e => handleChange(e)} + isError={!!errorMessage} + autoFocus + ></LabelInput> + <FixedButton disabled={!canSubmit}>행동 개시!</FixedButton> + </form> + </MainLayout> + ); +}; + +export default SetEventNamePage; diff --git a/client/src/pages/CreateEventPage/index.ts b/client/src/pages/CreateEventPage/index.ts new file mode 100644 index 000000000..9b66c3ba5 --- /dev/null +++ b/client/src/pages/CreateEventPage/index.ts @@ -0,0 +1,2 @@ +export {default as SetEventNamePage} from './SetEventNamePage'; +export {default as CompleteCreateEventPage} from './CompleteCreateEventPage'; diff --git a/client/src/pages/Event/Admin/index.ts b/client/src/pages/Event/Admin/index.ts deleted file mode 100644 index 9799a7485..000000000 --- a/client/src/pages/Event/Admin/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as AdminPage} from './Admin'; diff --git a/client/src/pages/Event/Home/index.ts b/client/src/pages/Event/Home/index.ts deleted file mode 100644 index 75e27b8a3..000000000 --- a/client/src/pages/Event/Home/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as HomePage} from './Home'; diff --git a/client/src/pages/Event/index.ts b/client/src/pages/Event/index.ts deleted file mode 100644 index af2aa805d..000000000 --- a/client/src/pages/Event/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as EventPage} from './EventLayout'; diff --git a/client/src/pages/Event/Admin/Admin.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts similarity index 100% rename from client/src/pages/Event/Admin/Admin.style.ts rename to client/src/pages/EventPage/AdminPage/AdminPage.style.ts diff --git a/client/src/pages/Event/Admin/Admin.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx similarity index 78% rename from client/src/pages/Event/Admin/Admin.tsx rename to client/src/pages/EventPage/AdminPage/AdminPage.tsx index bda03da55..2c4ccd5a9 100644 --- a/client/src/pages/Event/Admin/Admin.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -6,35 +6,30 @@ import {useStepList} from '@hooks/useStepList/useStepList'; import {requestGetEventName} from '@apis/request/event'; import useEventId from '@hooks/useEventId/useEventId'; -import {SetActionModalContent, SetInitialParticipants} from '@components/Modal'; +import {SetActionListModal, SetInitialMemberListModal} from '@components/Modal'; -import {ReceiptStyle} from './Admin.style'; +import {ReceiptStyle} from './AdminPage.style'; -export type PurchaseInformation = { - title: string; - price: number; -}; - -export type ParticipantType = { - name: string; - type: InOutType; -}; - -interface ModalRenderingProps { +interface ModalBasedOnMemberCountProps { memberNameList: string[]; openBottomSheet: boolean; setOrder: React.Dispatch<React.SetStateAction<number>>; setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; } -const ModalRendering = ({memberNameList, openBottomSheet, setOrder, setOpenBottomSheet}: ModalRenderingProps) => { +const ModalBasedOnMemberCount = ({ + memberNameList, + openBottomSheet, + setOrder, + setOpenBottomSheet, +}: ModalBasedOnMemberCountProps) => { switch (memberNameList.length) { case 0: - return <SetInitialParticipants setOpenBottomSheet={setOpenBottomSheet} openBottomSheet={openBottomSheet} />; + return <SetInitialMemberListModal setOpenBottomSheet={setOpenBottomSheet} openBottomSheet={openBottomSheet} />; default: return ( - <SetActionModalContent + <SetActionListModal setOrder={setOrder} setOpenBottomSheet={setOpenBottomSheet} openBottomSheet={openBottomSheet} @@ -43,7 +38,7 @@ const ModalRendering = ({memberNameList, openBottomSheet, setOrder, setOpenBotto } }; -const Admin = () => { +const AdminPage = () => { const [openBottomSheet, setOpenBottomSheet] = useState(false); const [order, setOrder] = useState<number>(1); @@ -82,7 +77,7 @@ const Admin = () => { onClick={() => setOpenBottomSheet(prev => !prev)} /> {openBottomSheet && ( - <ModalRendering + <ModalBasedOnMemberCount memberNameList={memberNameList} setOrder={setOrder} setOpenBottomSheet={setOpenBottomSheet} @@ -94,4 +89,4 @@ const Admin = () => { ); }; -export default Admin; +export default AdminPage; diff --git a/client/src/pages/EventPage/AdminPage/index.ts b/client/src/pages/EventPage/AdminPage/index.ts new file mode 100644 index 000000000..b80c0bb2f --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/index.ts @@ -0,0 +1 @@ +export {default as AdminPage} from './AdminPage'; diff --git a/client/src/pages/Event/EventLayout.tsx b/client/src/pages/EventPage/EvenPageLayout.tsx similarity index 88% rename from client/src/pages/Event/EventLayout.tsx rename to client/src/pages/EventPage/EvenPageLayout.tsx index 2b2b439de..3f68b4ba1 100644 --- a/client/src/pages/Event/EventLayout.tsx +++ b/client/src/pages/EventPage/EvenPageLayout.tsx @@ -5,7 +5,7 @@ import StepListProvider from '@hooks/useStepList/useStepList'; import useNavSwitch from '@hooks/useNavSwitch'; -const EventLayout = () => { +const EventPageLayout = () => { const {nav, paths, onChange} = useNavSwitch(); return ( @@ -20,4 +20,4 @@ const EventLayout = () => { ); }; -export default EventLayout; +export default EventPageLayout; diff --git a/client/src/pages/Event/Home/Home.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx similarity index 95% rename from client/src/pages/Event/Home/Home.tsx rename to client/src/pages/EventPage/HomePage/HomePage.tsx index 8ff195cb8..19227d404 100644 --- a/client/src/pages/Event/Home/Home.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -7,7 +7,7 @@ import {useStepList} from '@hooks/useStepList/useStepList'; import useEventId from '@hooks/useEventId/useEventId'; import {requestGetEventName} from '@apis/request/event'; -const HomeContent = () => { +const HomePage = () => { const {getTotalPrice} = useStepList(); const {eventId} = useEventId(); @@ -37,4 +37,4 @@ const HomeContent = () => { ); }; -export default HomeContent; +export default HomePage; diff --git a/client/src/pages/EventPage/HomePage/index.ts b/client/src/pages/EventPage/HomePage/index.ts new file mode 100644 index 000000000..aa0bf2b3f --- /dev/null +++ b/client/src/pages/EventPage/HomePage/index.ts @@ -0,0 +1 @@ +export {default as HomePage} from './HomePage'; diff --git a/client/src/pages/EventPage/index.ts b/client/src/pages/EventPage/index.ts new file mode 100644 index 000000000..c560632da --- /dev/null +++ b/client/src/pages/EventPage/index.ts @@ -0,0 +1 @@ +export {default as EventPage} from './EvenPageLayout'; diff --git a/client/src/pages/Main/index.ts b/client/src/pages/Main/index.ts deleted file mode 100644 index c3cce532e..000000000 --- a/client/src/pages/Main/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as MainPage} from './Main'; diff --git a/client/src/pages/Main/Main.tsx b/client/src/pages/MainPage/MainPage.tsx similarity index 70% rename from client/src/pages/Main/Main.tsx rename to client/src/pages/MainPage/MainPage.tsx index 2a032b5cf..b216e50c6 100644 --- a/client/src/pages/Main/Main.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -3,13 +3,11 @@ import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; import {ROUTER_URLS} from '@constants/routerUrls'; -const Main = () => { +const MainPage = () => { const navigate = useNavigate(); return ( <MainLayout> - {/* <TopNav navType="back" /> */} - <Title title="행동대장" description="랜딩페이지입니다. 뿌뿌 잠깐만 테스트해볼게요.." /> <TopNav children={<></>} /> <Title title="행동대장" description="랜딩페이지입니다." /> <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateName)}>행사 생성하기</FixedButton> @@ -17,4 +15,4 @@ const Main = () => { ); }; -export default Main; +export default MainPage; diff --git a/client/src/pages/MainPage/index.ts b/client/src/pages/MainPage/index.ts new file mode 100644 index 000000000..017fff307 --- /dev/null +++ b/client/src/pages/MainPage/index.ts @@ -0,0 +1 @@ +export {default as MainPage} from './MainPage'; diff --git a/client/src/router.tsx b/client/src/router.tsx index 70f7a1e71..75777310a 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -1,11 +1,11 @@ import {createBrowserRouter} from 'react-router-dom'; -import {AdminPage} from '@pages/Event/Admin'; -import {HomePage} from '@pages/Event/Home'; +import {AdminPage} from '@pages/EventPage/AdminPage'; +import {HomePage} from '@pages/EventPage/HomePage'; -import {MainPage} from '@pages/Main'; -import {CreateNamePage, CreateCompletePage} from '@pages/Create'; -import {EventPage} from '@pages/Event'; +import {CompleteCreateEventPage, SetEventNamePage} from '@pages/CreateEventPage'; +import {MainPage} from '@pages/MainPage'; +import {EventPage} from '@pages/EventPage'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -23,11 +23,11 @@ const router = createBrowserRouter([ }, { path: ROUTER_URLS.eventCreateName, - element: <CreateNamePage />, + element: <SetEventNamePage />, }, { path: ROUTER_URLS.eventCreateComplete, - element: <CreateCompletePage />, + element: <CompleteCreateEventPage />, }, { path: ROUTER_URLS.event, diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts new file mode 100644 index 000000000..9b6fbe06f --- /dev/null +++ b/client/src/types/serviceType.ts @@ -0,0 +1,54 @@ +export type MemberType = 'IN' | 'OUT'; + +export type InOutType = '늦참' | '탈주'; + +export type MemberReport = { + name: string; + price: number; +}; + +export type Bill = { + title: string; + price: number; +}; + +type StepBase = { + members: string[]; +}; + +export type MemberStep = StepBase & { + type: MemberType; + stepName: null; + actions: MemberAction[]; +}; + +export type BillStep = StepBase & { + type: 'BILL'; + stepName: string; + actions: BillAction[]; +}; + +// TODO: (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. +export type StepList = { + steps: (MemberStep | BillStep)[]; +}; + +export type Action = { + actionId: number; + name: string; + price: number | null; + sequence: number; +}; + +export type BillAction = Omit<Action, 'price'> & { + price: number; +}; + +export type MemberAction = Omit<Action, 'price'> & { + price: null; +}; + +export type Member = { + name: string; + status: MemberType; +}; diff --git a/client/src/utils/validate/type.ts b/client/src/utils/validate/type.ts new file mode 100644 index 000000000..1c994c1f8 --- /dev/null +++ b/client/src/utils/validate/type.ts @@ -0,0 +1,4 @@ +export interface ValidateResult { + isValid: boolean; + errorMessage?: string; +} diff --git a/client/src/utils/validate/validateEventName.ts b/client/src/utils/validate/validateEventName.ts new file mode 100644 index 000000000..b390f12b9 --- /dev/null +++ b/client/src/utils/validate/validateEventName.ts @@ -0,0 +1,13 @@ +import ERROR_MESSAGE from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateEventName = (name: string): ValidateResult => { + if (name.length > RULE.maxEventNameLength) { + return {isValid: false, errorMessage: ERROR_MESSAGE.eventName}; + } + return {isValid: true}; +}; + +export default validateEventName; diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts new file mode 100644 index 000000000..0e7483358 --- /dev/null +++ b/client/src/utils/validate/validateMemberName.ts @@ -0,0 +1,25 @@ +import REGEXP from '@constants/regExp'; +import ERROR_MESSAGE from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateMemberName = (name: string): ValidateResult => { + const validateOnlyString = () => { + if (!REGEXP.memberName.test(name)) return false; + return true; + }; + + const validateLength = () => { + if (name.length > RULE.maxMemberNameLength || name.length < 1) return false; + return true; + }; + + if (validateOnlyString() && validateLength()) { + return {isValid: true}; + } + + return {isValid: false, errorMessage: ERROR_MESSAGE.memberName}; +}; + +export default validateMemberName; diff --git a/client/src/utils/validate/validatePurchase.ts b/client/src/utils/validate/validatePurchase.ts new file mode 100644 index 000000000..026cfb496 --- /dev/null +++ b/client/src/utils/validate/validatePurchase.ts @@ -0,0 +1,34 @@ +import ERROR_MESSAGE from '@constants/errorMessage'; +import RULE from '@constants/rule'; +import REGEXP from '@constants/regExp'; + +import {ValidateResult} from './type'; + +const validatePurchase = (inputPair: Bill): ValidateResult => { + const {title, price} = inputPair; + let errorMessage; + + const validatePrice = () => { + if (price > RULE.maxPrice) { + errorMessage = ERROR_MESSAGE.purchasePrice; + return false; + } + return true; + }; + + const validateTitle = () => { + if (REGEXP.purchaseTitle.test(title)) { + errorMessage = ERROR_MESSAGE.purchaseTitle; + return false; + } + return true; + }; + + if (validatePrice() && validateTitle()) { + return {isValid: true}; + } + + return {isValid: true, errorMessage: ''}; +}; + +export default validatePurchase; From 94d1404dee39ea7324a317cd37a86674795599eb Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:21:16 +0900 Subject: [PATCH 113/273] =?UTF-8?q?feat:=20=EB=B3=80=EA=B2=BD=EB=90=9C=20A?= =?UTF-8?q?PI=20endpoint=EB=A1=9C=20=EC=88=98=EC=A0=95=20(#196)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --- client/package-lock.json | 114 +----------------- client/package.json | 2 +- client/src/apis/request/bill.ts | 34 +++++- client/src/apis/request/event.ts | 8 +- client/src/apis/request/member.ts | 23 ++-- client/src/apis/request/report.ts | 6 +- client/src/apis/request/stepList.ts | 2 +- .../useSearchMemberReportList.tsx | 4 +- client/src/hooks/useStepList/useStepList.tsx | 12 +- .../CreateEventPage/SetEventNamePage.tsx | 4 +- 10 files changed, 68 insertions(+), 141 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index d35cb264b..2b1894624 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.51", + "haengdong-design": "^0.1.53", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -6406,9 +6406,9 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.52", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.52.tgz", - "integrity": "sha512-BLbPvCm/CnuixH9kLbqPC2l7GLJQfxhjf/hRCTpfadUybSiMkYA1HOSXCBT4QY4CP5PsfzZC0L7llRCoDSNAyQ==", + "version": "0.1.53", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.53.tgz", + "integrity": "sha512-CtaoUUdE6iTcTceAzKxZyn8LjJvMjrlYiQhxXC7RC36G1Jxc0OcU2WlAv/6yT8mfFKc1yUOi5H1omTXWjCD5gA==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", @@ -8504,112 +8504,6 @@ "node": ">= 0.4" } }, - "node_modules/postcss": { - "version": "8.4.40", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", - "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", - "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", diff --git a/client/package.json b/client/package.json index 49de616ce..833053883 100644 --- a/client/package.json +++ b/client/package.json @@ -45,7 +45,7 @@ "@emotion/react": "^11.11.4", "@types/dotenv-webpack": "^7.0.7", "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.51", + "haengdong-design": "^0.1.53", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index c07fd758a..6e5a0f3ab 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -1,18 +1,44 @@ import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestPost} from '@apis/fetcher'; +import {requestPost, requestDelete, requestPut} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -type RequestAddBillList = { +type RequestPostBillList = { billList: Bill[]; }; -export const requestAddBillList = async ({eventId, billList}: WithEventId<RequestAddBillList>) => { +export const requestPostBillList = async ({eventId, billList}: WithEventId<RequestPostBillList>) => { await requestPost({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/actions/bills`, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions`, body: { actions: billList, }, }); }; + +type RequestDeleteBillAction = { + actionId: number; +}; + +export const requestDeleteBillAction = async ({eventId, actionId}: WithEventId<RequestDeleteBillAction>) => { + await requestDelete({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, + }); +}; + +type RequestPutBillAction = Bill & { + actionId: number; +}; + +export const requestPutBillAction = async ({eventId, actionId, title, price}: WithEventId<RequestPutBillAction>) => { + await requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, + body: { + title, + price, + }, + }); +}; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index 5822267b9..fc4708bf7 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -2,17 +2,17 @@ import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet, requestPost} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -type RequestCreateNewEvent = { +type RequestPostNewEvent = { eventName: string; }; -type ResponseCreateNewEvent = { +type ResponsePostNewEvent = { eventId: string; }; -export const requestCreateNewEvent = async ({eventName}: RequestCreateNewEvent) => { +export const requestPostNewEvent = async ({eventName}: RequestPostNewEvent) => { // TODO: (@weadie) 뼈대만 둔 것. header값을 꺼내오는 로직이 필요하다. 또는 바디에 달라고 부탁할 수 있다. - return requestPost<ResponseCreateNewEvent>({ + return requestPost<ResponsePostNewEvent>({ endpoint: TEMP_PREFIX, body: {eventName}, }); diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index d23563f34..2ae3c384a 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -1,24 +1,31 @@ import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestPost} from '@apis/fetcher'; +import {requestPost, requestDelete} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -type RequestUpdateMemberList = { +type RequestPostMemberList = { memberNameList: string[]; type: MemberType; }; -export const requestUpdateMemberList = async ({ - eventId, - type, - memberNameList, -}: WithEventId<RequestUpdateMemberList>) => { +export const requestPostMemberList = async ({eventId, type, memberNameList}: WithEventId<RequestPostMemberList>) => { await requestPost({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/actions/members`, + endpoint: `${TEMP_PREFIX}/${eventId}/member-actions`, body: { members: memberNameList, status: type, }, }); }; + +type RequestDeleteMemberAction = { + actionId: number; +}; + +export const requestDeleteMemberAction = async ({eventId, actionId}: WithEventId<RequestDeleteMemberAction>) => { + await requestDelete({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/member-actions/${actionId}`, + }); +}; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts index faa6c9185..7450f0978 100644 --- a/client/src/apis/request/report.ts +++ b/client/src/apis/request/report.ts @@ -3,12 +3,12 @@ import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -type ResponseMemberReportList = { +type ResponseGetMemberReportList = { reports: MemberReport[]; }; -export const requestMemberReportList = async ({eventId}: WithEventId) => { - const {reports} = await requestGet<ResponseMemberReportList>({ +export const requestGetMemberReportList = async ({eventId}: WithEventId) => { + const {reports} = await requestGet<ResponseGetMemberReportList>({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/actions/reports`, }); diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts index e09cb67fd..7abb80f59 100644 --- a/client/src/apis/request/stepList.ts +++ b/client/src/apis/request/stepList.ts @@ -4,7 +4,7 @@ import {requestGet} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; // TODO: (@weadie) 현재 토큰을 어떻게 관리할지.. 계속 사용되는데 -export const requestStepList = async ({eventId}: WithEventId) => { +export const requestGetStepList = async ({eventId}: WithEventId) => { // TODO: (@weadie) response가 어떻게 오는지 안나와서 data로만 써뒀어요. const {steps} = await requestGet<StepList>({ baseUrl: BASE_URL.HD, diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx index 02c07b80a..84718891e 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -1,6 +1,6 @@ import {useEffect, useState} from 'react'; -import {requestMemberReportList} from '@apis/request/report'; +import {requestGetMemberReportList} from '@apis/request/report'; import useEventId from '@hooks/useEventId/useEventId'; type UseSearchMemberReportListParams = { @@ -18,7 +18,7 @@ const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { // TODO: (@weadie) eventId에 의존하는 두 개의 훅에 대한 리펙토링 필요 if (eventId === '') return; - const memberReportListData = await requestMemberReportList({eventId}); + const memberReportListData = await requestGetMemberReportList({eventId}); setMemberReportList(memberReportListData); }; diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx index 52d2a78d6..e42732e05 100644 --- a/client/src/hooks/useStepList/useStepList.tsx +++ b/client/src/hooks/useStepList/useStepList.tsx @@ -1,9 +1,9 @@ import {PropsWithChildren, createContext, useContext, useEffect, useState} from 'react'; import useEventId from '@hooks/useEventId/useEventId'; -import {requestAddBillList} from '@apis/request/bill'; -import {requestUpdateMemberList} from '@apis/request/member'; -import {requestStepList} from '@apis/request/stepList'; +import {requestPostBillList} from '@apis/request/bill'; +import {requestPostMemberList} from '@apis/request/member'; +import {requestGetStepList} from '@apis/request/stepList'; import {BillAction, BillStep, MemberStep} from './type.ts'; @@ -32,7 +32,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { }, [eventId]); const refreshStepList = async () => { - const stepList = await requestStepList({eventId}); + const stepList = await requestGetStepList({eventId}); if (stepList.length !== 0) { setNameMemberList(stepList[stepList.length - 1].members); @@ -43,7 +43,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { const updateMemberList = async ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => { try { - await requestUpdateMemberList({eventId, type, memberNameList}); + await requestPostMemberList({eventId, type, memberNameList}); // TODO: (@weadie) 클라이언트 단에서 멤버 목록을 관리하기 위한 로직. 개선이 필요하다. if (type === 'IN') setNameMemberList(prev => [...prev, ...memberNameList]); @@ -57,7 +57,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { const addBill = async (billList: Bill[]) => { // TODO: (@weadie) 에러 처리 - await requestAddBillList({eventId, billList}); + await requestPostBillList({eventId, billList}); refreshStepList(); }; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index 4da51dd98..360db3f17 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -2,7 +2,7 @@ import {useState} from 'react'; import {useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Input, Title, TopNav, Back} from 'haengdong-design'; -import {requestCreateNewEvent} from '@apis/request/event'; +import {requestPostNewEvent} from '@apis/request/event'; import validateEventName from '@utils/validate/validateEventName'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -16,7 +16,7 @@ const SetEventNamePage = () => { const submitEventName = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); - const response = await requestCreateNewEvent({eventName}); + const response = await requestPostNewEvent({eventName}); if (response) { const {eventId} = response; From e55f7b6104e6d719c8ee16a22dc3976352f399bc Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:55:15 +0900 Subject: [PATCH 114/273] =?UTF-8?q?feat:=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20hover,=20mouse,=20transition=20an?= =?UTF-8?q?imation=20(#198)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 --- .github/workflows/design-pull-request.yml | 1 - HDesign/.storybook/main.ts | 5 +- HDesign/package-lock.json | 378 +++++++----------- HDesign/package.json | 3 +- .../src/components/BillItem/BillItem.style.ts | 2 +- .../BottomSheet/BottomSheet.stories.tsx | 20 +- .../BottomSheet/BottomSheet.style.ts | 25 +- .../components/BottomSheet/BottomSheet.tsx | 48 ++- .../BottomSheet/BottomSheet.type.ts | 5 +- .../components/BottomSheet/useBottomSheet.ts | 75 +++- HDesign/src/components/Button/Button.style.ts | 61 ++- .../DragHandleItem/DragHandleItem.style.ts | 5 +- .../DragHandleItem/DragHandleItem.tsx | 5 +- .../ExpenseList/ExpenseList.style.ts | 2 +- .../FixedButton/FixedButton.style.ts | 71 +++- HDesign/src/components/Flex/Flex.style.ts | 2 +- HDesign/src/components/Flex/Flex.tsx | 5 +- HDesign/src/components/Flex/Flex.type.ts | 2 +- .../src/components/IconButton/IconButton.tsx | 2 +- .../components/InOutItem/InOutItem.style.ts | 2 +- .../src/components/Input/Input.stories.tsx | 1 + HDesign/src/components/Input/Input.style.ts | 3 + HDesign/src/components/Input/Input.tsx | 21 +- HDesign/src/components/Input/useInput.ts | 2 +- .../components/LabelGroupInput/Element.tsx | 7 +- .../LabelGroupInput/GroupInputContext.tsx | 8 +- .../LabelGroupInput.stories.tsx | 2 + .../LabelGroupInput/LabelGroupInput.style.ts | 36 +- .../LabelGroupInput/LabelGroupInput.tsx | 16 +- .../LabelInput/LabelInput.stories.tsx | 1 + .../components/LabelInput/LabelInput.style.ts | 16 +- .../src/components/LabelInput/LabelInput.tsx | 12 +- .../components/LabelInput/LabelInput.type.ts | 1 + .../components/LabelInput/useLabelInput.ts | 7 +- HDesign/src/components/Search/Search.style.ts | 2 +- .../src/components/StepItem/StepItem.style.ts | 2 +- HDesign/src/components/StepItem/StepItem.tsx | 2 +- HDesign/src/components/Tabs/Tabs.stories.tsx | 2 +- HDesign/src/components/Tabs/Tabs.style.ts | 2 +- .../components/TextButton/TextButton.style.ts | 2 +- .../src/components/TextButton/TextButton.tsx | 2 +- HDesign/src/components/Toast/Toast.style.ts | 2 +- HDesign/src/index.tsx | 2 +- .../strictPropsWithChildren.ts | 0 .../changeCamelCaseToKebabCase.ts | 0 HDesign/src/utils/colors.ts | 88 ++++ HDesign/tsconfig.json | 6 +- 47 files changed, 562 insertions(+), 402 deletions(-) rename HDesign/src/{types => type}/strictPropsWithChildren.ts (100%) rename HDesign/src/utils/{ return str.replace(/([a-z])([A-Z]) => }/changeCamelCaseToKebabCase.ts (100%) create mode 100644 HDesign/src/utils/colors.ts diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml index 3c88c82b1..af168a976 100644 --- a/.github/workflows/design-pull-request.yml +++ b/.github/workflows/design-pull-request.yml @@ -1,5 +1,4 @@ name: Storybook Deployment -run-name: ${{ github.actor }}의 스토리북 배포 on: pull_request: diff --git a/HDesign/.storybook/main.ts b/HDesign/.storybook/main.ts index 0a8a9a7c4..a1fa61591 100644 --- a/HDesign/.storybook/main.ts +++ b/HDesign/.storybook/main.ts @@ -20,11 +20,12 @@ const config: StorybookConfig = { if (config.resolve) { config.resolve.alias = { ...config.resolve.alias, - '@': path.resolve(__dirname, '../src'), '@components': path.resolve(__dirname, '../src/components'), - '@assets': path.resolve(__dirname, '../src/assets'), '@token': path.resolve(__dirname, '../src/token'), + '@type': path.resolve(__dirname, '../src/type'), '@theme': path.resolve(__dirname, '../src/theme'), + '@assets': path.resolve(__dirname, '../src/assets'), + '@utils': path.resolve(__dirname, '../src/utils'), }; } diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index bbf0d12a9..dae3e34ff 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.52", + "version": "0.1.55", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.52", + "version": "0.1.55", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", @@ -28,6 +28,7 @@ "@storybook/react": "^8.2.2", "@storybook/react-webpack5": "^8.2.3", "@storybook/test": "^8.2.2", + "@swc/core": "^1.7.6", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", @@ -2202,15 +2203,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", @@ -4113,9 +4105,9 @@ } }, "node_modules/@swc/core": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.3.tgz", - "integrity": "sha512-HHAlbXjWI6Kl9JmmUW1LSygT1YbblXgj2UvvDzMkTBPRzYMhW6xchxdO8HbtMPtFYRt/EQq9u1z7j4ttRSrFsA==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.6.tgz", + "integrity": "sha512-FZxyao9eQks1MRmUshgsZTmlg/HB2oXK5fghkoWJm/1CU2q2kaJlVDll2as5j+rmWiwkp0Gidlq8wlXcEEAO+g==", "hasInstallScript": true, "dependencies": { "@swc/counter": "^0.1.3", @@ -4129,16 +4121,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.3", - "@swc/core-darwin-x64": "1.7.3", - "@swc/core-linux-arm-gnueabihf": "1.7.3", - "@swc/core-linux-arm64-gnu": "1.7.3", - "@swc/core-linux-arm64-musl": "1.7.3", - "@swc/core-linux-x64-gnu": "1.7.3", - "@swc/core-linux-x64-musl": "1.7.3", - "@swc/core-win32-arm64-msvc": "1.7.3", - "@swc/core-win32-ia32-msvc": "1.7.3", - "@swc/core-win32-x64-msvc": "1.7.3" + "@swc/core-darwin-arm64": "1.7.6", + "@swc/core-darwin-x64": "1.7.6", + "@swc/core-linux-arm-gnueabihf": "1.7.6", + "@swc/core-linux-arm64-gnu": "1.7.6", + "@swc/core-linux-arm64-musl": "1.7.6", + "@swc/core-linux-x64-gnu": "1.7.6", + "@swc/core-linux-x64-musl": "1.7.6", + "@swc/core-win32-arm64-msvc": "1.7.6", + "@swc/core-win32-ia32-msvc": "1.7.6", + "@swc/core-win32-x64-msvc": "1.7.6" }, "peerDependencies": { "@swc/helpers": "*" @@ -4150,9 +4142,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.3.tgz", - "integrity": "sha512-CTkHa6MJdov9t41vuV2kmQIMu+Q19LrEHGIR/UiJYH06SC/sOu35ZZH8DyfLp9ZoaCn21gwgWd61ixOGQlwzTw==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.6.tgz", + "integrity": "sha512-6lYHey84ZzsdtC7UuPheM4Rm0Inzxm6Sb8U6dmKc4eCx8JL0LfWG4LC5RsdsrTxnjTsbriWlnhZBffh8ijUHIQ==", "cpu": [ "arm64" ], @@ -4164,6 +4156,141 @@ "node": ">=10" } }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.6.tgz", + "integrity": "sha512-Fyl+8aH9O5rpx4O7r2KnsPpoi32iWoKOYKiipeTbGjQ/E95tNPxbmsz4yqE8Ovldcga60IPJ5OKQA3HWRiuzdw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.6.tgz", + "integrity": "sha512-2WxYTqFaOx48GKC2cbO1/IntA+w+kfCFy436Ij7qRqqtV/WAvTM9TC1OmiFbqq436rSot52qYmX8fkwdB5UcLQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.6.tgz", + "integrity": "sha512-TBEGMSe0LhvPe4S7E68c7VzgT3OMu4VTmBLS7B2aHv4v8uZO92Khpp7L0WqgYU1y5eMjk+XLDLi4kokiNHv/Hg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.6.tgz", + "integrity": "sha512-QI8QGL0HGT42tj7F1A+YAzhGkJjUcvvTfI1e2m704W0Enl2/UIK9v5D1zvQzYwusRyKuaQfbeBRYDh0NcLOGLg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.6.tgz", + "integrity": "sha512-61AYVzhjuNQAVIKKWOJu3H0/pFD28RYJGxnGg3YMhvRLRyuWNyY5Nyyj2WkKcz/ON+g38Arlz00NT1LDIViRLg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.6.tgz", + "integrity": "sha512-hQFznpfLK8XajfAAN9Cjs0w/aVmO7iu9VZvInyrTCRcPqxV5O+rvrhRxKvC1LRMZXr5M6JRSRtepp5w+TK4kAw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.6.tgz", + "integrity": "sha512-Aqsd9afykVMuekzjm4X4TDqwxmG4CrzoOSFe0hZrn9SMio72l5eAPnMtYoe5LsIqtjV8MNprLfXaNbjHjTegmA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.6.tgz", + "integrity": "sha512-9h0hYnOeRVNeQgHQTvD1Im67faNSSzBZ7Adtxyu9urNLfBTJilMllFd2QuGHlKW5+uaT6ZH7ZWDb+c/enx7Lcg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.6.tgz", + "integrity": "sha512-izeoB8glCSe6IIDQmrVm6bvR9muk9TeKgmtY7b6l1BwL4BFnTUk4dMmpbntT90bEVQn3JPCaPtUG4HfL8VuyuA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -5194,50 +5321,6 @@ "@xtuc/long": "4.2.2" } }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", - "dev": true, - "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -8216,15 +8299,6 @@ "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", "dev": true }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "engines": { - "node": ">= 4.9.1" - } - }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -8362,15 +8436,6 @@ "node": ">=8" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -9101,25 +9166,6 @@ "node": ">=4" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -9169,15 +9215,6 @@ "node": ">= 0.4" } }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/is-absolute-url": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", @@ -11519,18 +11556,6 @@ "node": ">= 4" } }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -11750,27 +11775,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -13618,60 +13622,6 @@ } } }, - "node_modules/webpack-cli": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", - "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", - "dev": true, - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^2.1.1", - "@webpack-cli/info": "^2.0.2", - "@webpack-cli/serve": "^2.0.5", - "colorette": "^2.0.14", - "commander": "^10.0.1", - "cross-spawn": "^7.0.3", - "envinfo": "^7.7.3", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true, - "engines": { - "node": ">=14" - } - }, "node_modules/webpack-hot-middleware": { "version": "2.26.1", "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", @@ -13683,20 +13633,6 @@ "strip-ansi": "^6.0.0" } }, - "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", @@ -13812,12 +13748,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/HDesign/package.json b/HDesign/package.json index f1bc9c8e7..90ad0d4d1 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.52", + "version": "0.1.55", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", @@ -31,6 +31,7 @@ "@storybook/react": "^8.2.2", "@storybook/react-webpack5": "^8.2.3", "@storybook/test": "^8.2.2", + "@swc/core": "^1.7.6", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", diff --git a/HDesign/src/components/BillItem/BillItem.style.ts b/HDesign/src/components/BillItem/BillItem.style.ts index 54531e095..3e3f3398a 100644 --- a/HDesign/src/components/BillItem/BillItem.style.ts +++ b/HDesign/src/components/BillItem/BillItem.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; export const textStyle = (theme: Theme) => css({ diff --git a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx b/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx index 48288fb6c..67d4cdb37 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx +++ b/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx @@ -13,17 +13,7 @@ const meta = { parameters: { // layout: 'centered', }, - argTypes: { - fixedButtonProps: { - description: '', - control: {type: 'object'}, - }, - }, - args: { - fixedButtonProps: { - variants: 'primary', - }, - }, + argTypes: {}, } satisfies Meta<typeof BottomSheet>; export default meta; @@ -31,18 +21,12 @@ export default meta; type Story = StoryObj<typeof meta>; export const Playground: Story = { - args: { - fixedButtonProps: { - variants: 'primary', - children: '하단 고정 버튼', - }, - }, render: ({...args}) => { const [isOpened, setIsOpened] = useState(false); return ( <> <Button variants="tertiary" children="show modal" onClick={() => setIsOpened(true)} /> - <BottomSheet {...args} isOpened={isOpened} onChangeClose={() => setIsOpened(false)} /> + <BottomSheet {...args} isOpened={isOpened} onClose={() => setIsOpened(false)} /> </> ); }, diff --git a/HDesign/src/components/BottomSheet/BottomSheet.style.ts b/HDesign/src/components/BottomSheet/BottomSheet.style.ts index 4968206f1..2a6506d7e 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.style.ts +++ b/HDesign/src/components/BottomSheet/BottomSheet.style.ts @@ -2,7 +2,12 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; -export const dimmedLayerStyle = (theme: Theme) => +export const display = (visible: boolean) => + css({ + visibility: visible ? 'visible' : 'hidden', + }); + +export const dimmedLayerStyle = (theme: Theme, isOpened: boolean) => css({ // TODO: (@todari) zindex foundation position: 'fixed', @@ -11,10 +16,13 @@ export const dimmedLayerStyle = (theme: Theme) => width: '100vw', height: '100vh', backgroundColor: theme.colors.black, - opacity: '0.48', + opacity: isOpened ? '0.48' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', }); -export const bottomSheetContainerStyle = (theme: Theme) => +export const bottomSheetContainerStyle = (theme: Theme, isOpened: boolean, isDragging: boolean, translateY: number) => css({ position: 'fixed', display: 'flex', @@ -27,12 +35,21 @@ export const bottomSheetContainerStyle = (theme: Theme) => height: '80%', borderRadius: '1.5rem 1.5rem 0 0', backgroundColor: theme.colors.white, + + transform: isOpened ? `translateY(${translateY}px)` : 'translateY(100%)', + transition: isDragging ? 'none' : 'transform 0.2s ease-in-out', }); +export const indicatorContainerStyle = css({ + display: 'flex', + justifyContent: 'center', + padding: '0.5rem 0', + width: '100%', +}); + export const indicatorStyle = (theme: Theme) => css({ display: 'flex', - margin: '0.5rem 0', width: '5rem', height: '0.25rem', borderRadius: '0.125rem', diff --git a/HDesign/src/components/BottomSheet/BottomSheet.tsx b/HDesign/src/components/BottomSheet/BottomSheet.tsx index d0f286cc8..f920a0fdb 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.tsx +++ b/HDesign/src/components/BottomSheet/BottomSheet.tsx @@ -1,5 +1,6 @@ /** @jsxImportSource @emotion/react */ import {createPortal} from 'react-dom'; +import {useEffect, useRef, useState} from 'react'; import {BottomSheetProps} from '@components/BottomSheet/BottomSheet.type'; import FixedButton from '@components/FixedButton/FixedButton'; @@ -7,31 +8,48 @@ import FixedButton from '@components/FixedButton/FixedButton'; import {useTheme} from '@theme/HDesignProvider'; import {useBottomSheet} from './useBottomSheet'; -import {bottomSheetContainerStyle, dimmedLayerStyle, indicatorStyle} from './BottomSheet.style'; +import { + bottomSheetContainerStyle, + dimmedLayerStyle, + display, + indicatorContainerStyle, + indicatorStyle, +} from './BottomSheet.style'; const BottomSheet: React.FC<BottomSheetProps> = ({ isOpened = false, children, - fixedButtonProps, + onChangeClose, + onChangeOpen, ...props }: BottomSheetProps) => { const {theme} = useTheme(); - const {opened, handleClose} = useBottomSheet({isOpened, ...props}); + const {opened, visible, handleClose, handleDragStart, handleDrag, handleDragEnd, isDragging, translateY} = + useBottomSheet({ + isOpened, + onChangeClose, + onChangeOpen, + }); // TODO: (@todari) : children 길이 길 때 overflow button에 안가리는 영역 처리 return createPortal( - <> - {opened && ( - <> - <div css={dimmedLayerStyle(theme)} onClick={handleClose} /> - <div css={bottomSheetContainerStyle(theme)}> - <div css={indicatorStyle(theme)} /> - {children} - {fixedButtonProps && <FixedButton {...fixedButtonProps} />} - </div> - </> - )} - </>, + <div css={display(visible)}> + <div css={dimmedLayerStyle(theme, opened)} onClick={handleClose} /> + <div css={bottomSheetContainerStyle(theme, opened, isDragging, translateY)}> + <div + css={indicatorContainerStyle} + onMouseDown={handleDragStart} + onMouseMove={handleDrag} + onMouseUp={handleDragEnd} + onTouchStart={handleDragStart} + onTouchMove={handleDrag} + onTouchEnd={handleDragEnd} + > + <div css={indicatorStyle(theme)} /> + </div> + {children} + </div> + </div>, document.body, ); }; diff --git a/HDesign/src/components/BottomSheet/BottomSheet.type.ts b/HDesign/src/components/BottomSheet/BottomSheet.type.ts index 312fe3c29..8b350aef1 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.type.ts +++ b/HDesign/src/components/BottomSheet/BottomSheet.type.ts @@ -12,9 +12,8 @@ export interface BottomSheetStyleProps { export interface BottomSheetCustomProps { isOpened?: boolean; - onChangeOpen?: () => void; - onChangeClose?: () => void; - fixedButtonProps?: FixedButtonProps; + onOpen?: () => void; + onClose?: () => void; } export type BottomSheetOptionProps = BottomSheetStyleProps & BottomSheetCustomProps; diff --git a/HDesign/src/components/BottomSheet/useBottomSheet.ts b/HDesign/src/components/BottomSheet/useBottomSheet.ts index ca2274e19..3e2564550 100644 --- a/HDesign/src/components/BottomSheet/useBottomSheet.ts +++ b/HDesign/src/components/BottomSheet/useBottomSheet.ts @@ -1,13 +1,28 @@ -import {useCallback, useEffect, useState} from 'react'; +import {useCallback, useEffect, useRef, useState} from 'react'; interface UseBottomSheetProps { isOpened: boolean; - onChangeClose?: () => void; - onChangeOpen?: () => void; + onClose?: () => void; + onOpen?: () => void; } -export const useBottomSheet = ({isOpened, onChangeClose, onChangeOpen}: UseBottomSheetProps) => { - const [opened, setOpened] = useState(false); +export const useBottomSheet = ({isOpened, onClose, onOpen}: UseBottomSheetProps) => { + const [opened, setOpened] = useState(isOpened); + const [visible, setVisible] = useState(isOpened); + + const [isDragging, setIsDragging] = useState(false); + const [translateY, setTranslateY] = useState(0); + const startY = useRef(0); + + useEffect(() => { + if (opened) { + setVisible(true); + } else { + const timer = setTimeout(() => setVisible(false), 200); + + return () => clearTimeout(timer); + } + }, [opened]); useEffect(() => { setOpened(isOpened); @@ -16,31 +31,51 @@ export const useBottomSheet = ({isOpened, onChangeClose, onChangeOpen}: UseBotto } else { handleOpen(); } + + document.body.style.overflow = 'hidden'; + document.body.addEventListener('keydown', handleKeyDownEsc); + + return () => { + document.body.style.overflow = 'scroll'; + document.body.removeEventListener('keydown', handleKeyDownEsc); + }; }, [isOpened]); const handleClose = useCallback(() => { setOpened(false); - if (onChangeClose) { - onChangeClose(); + if (onClose) { + onClose(); } - }, []); + }, [onClose]); const handleOpen = useCallback(() => { setOpened(true); - if (onChangeOpen) { - onChangeOpen(); + if (onOpen) { + onOpen(); } - }, []); + }, [onOpen]); - useEffect(() => { - document.body.style.overflow = 'hidden'; - document.body.addEventListener('keydown', handleKeyDownEsc); + const handleDragStart = (e: React.TouchEvent | React.MouseEvent) => { + setIsDragging(true); + startY.current = 'touches' in e ? e.touches[0].clientY : e.clientY; + }; - return () => { - document.body.style.overflow = 'scroll'; - document.body.removeEventListener('keydown', handleKeyDownEsc); - }; - }, [isOpened]); + const handleDrag = (e: React.TouchEvent | React.MouseEvent) => { + if (!isDragging) return; + const currentY = 'touches' in e ? e.touches[0].clientY : e.clientY; + const deltaY = currentY - startY.current; + setTranslateY(Math.max(deltaY, 0)); + }; + + const threshold = window.screen.height / 10; + + const handleDragEnd = () => { + setIsDragging(false); + if (translateY > threshold) { + handleClose(); + } + setTranslateY(0); + }; const handleKeyDownEsc = (e: KeyboardEvent) => { if (e.key === 'Escape' && isOpened) { @@ -48,5 +83,5 @@ export const useBottomSheet = ({isOpened, onChangeClose, onChangeOpen}: UseBotto } }; - return {opened, handleClose}; + return {opened, visible, handleClose, handleDragStart, handleDrag, handleDragEnd, isDragging, translateY}; }; diff --git a/HDesign/src/components/Button/Button.style.ts b/HDesign/src/components/Button/Button.style.ts index 8ebec30c9..e8d68d635 100644 --- a/HDesign/src/components/Button/Button.style.ts +++ b/HDesign/src/components/Button/Button.style.ts @@ -1,5 +1,7 @@ import {css} from '@emotion/react'; +import {setDarker, setEmphasize, setLighter} from '@utils/colors'; + import {Theme} from '../../theme/theme.type'; import {ButtonStyleProps, ButtonSize, ButtonVariants} from './Button.type'; @@ -17,11 +19,26 @@ const getButtonDefaultStyle = (theme: Theme) => display: 'flex', justifyContent: 'center', lineHeight: '1', + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', whiteSpace: 'nowrap', '&:disabled': { backgroundColor: theme.colors.tertiary, color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + +const getHoverAndActiveBackground = (color: string) => + css({ + ':not(:disabled)': { + '&:hover': { + backgroundColor: setLighter(color, 0.15), + }, + '&:active': { + backgroundColor: setDarker(color, 0.15), + }, }, }); @@ -55,22 +72,34 @@ const getButtonSizeStyle = (size: ButtonSize) => { const getButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => { const style = { - primary: css({ - backgroundColor: theme.colors.primary, - color: theme.colors.onPrimary, - }), - secondary: css({ - backgroundColor: theme.colors.secondary, - color: theme.colors.onSecondary, - }), - tertiary: css({ - backgroundColor: theme.colors.tertiary, - color: theme.colors.onTertiary, - }), - destructive: css({ - backgroundColor: theme.colors.error, - color: theme.colors.onPrimary, - }), + primary: [ + css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.primary), + ], + secondary: [ + css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + getHoverAndActiveBackground(theme.colors.secondary), + ], + tertiary: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + destructive: [ + css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.error), + ], }; return style[variants]; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts index 972050619..22a1e195a 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts @@ -1,7 +1,8 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; -import {ColorKeys} from '@/token/colors'; +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgroundColor: ColorKeys) => css({ diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx index 9c92a6c8f..a58c6d663 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx @@ -1,11 +1,12 @@ /** @jsxImportSource @emotion/react */ import React from 'react'; -import {StrictPropsWithChildren} from '@/types/strictPropsWithChildren'; -import {COLORS, ColorKeys} from '@/token/colors'; +import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; import {useTheme} from '@theme/HDesignProvider'; +import {COLORS, ColorKeys} from '@token/colors'; + import IconButton from '../IconButton/IconButton'; import {dragHandleItemStyle, prefixStyle} from './DragHandleItem.style'; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.style.ts b/HDesign/src/components/ExpenseList/ExpenseList.style.ts index 58c8ba7f5..dd05c067f 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.style.ts +++ b/HDesign/src/components/ExpenseList/ExpenseList.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; export const expenseItemStyle = () => css({ diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/HDesign/src/components/FixedButton/FixedButton.style.ts index 5c3e69d77..b4d94038c 100644 --- a/HDesign/src/components/FixedButton/FixedButton.style.ts +++ b/HDesign/src/components/FixedButton/FixedButton.style.ts @@ -5,6 +5,8 @@ import {FixedButtonStyleProps} from '@components/FixedButton/FixedButton.type'; import {Theme} from '@theme/theme.type'; +import {setDarker, setLighter} from '@utils/colors'; + export const fixedButtonContainerStyle = (theme: Theme) => css({ display: 'flex', @@ -23,7 +25,19 @@ export const buttonContainerStyle = css({ width: '100%', }); -export const deleteButtonStyle = (theme: Theme) => +const getHoverAndActiveBackground = (color: string) => + css({ + ':not(:disabled)': { + '&:hover': { + backgroundColor: setLighter(color, 0.15), + }, + '&:active': { + backgroundColor: setDarker(color, 0.15), + }, + }, + }); + +export const deleteButtonStyle = (theme: Theme) => [ css({ display: 'flex', justifyContent: 'center', @@ -36,7 +50,12 @@ export const deleteButtonStyle = (theme: Theme) => fontSize: '1.25rem', fontWeight: '700', lineHeight: '1', - }); + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }), + getHoverAndActiveBackground(theme.colors.error), +]; export const fixedButtonStyle = (props: Required<FixedButtonStyleProps>) => { return [getFixedButtonDefaultStyle(props.theme), getFixedButtonVariantsStyle(props.variants, props.theme)]; @@ -55,30 +74,46 @@ const getFixedButtonDefaultStyle = (theme: Theme) => fontWeight: '700', lineHeight: '1', + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + '&:disabled': { backgroundColor: theme.colors.tertiary, color: theme.colors.onPrimary, + cursor: 'default', }, }); const getFixedButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => { const style = { - primary: css({ - backgroundColor: theme.colors.primary, - color: theme.colors.onPrimary, - }), - secondary: css({ - backgroundColor: theme.colors.secondary, - color: theme.colors.onSecondary, - }), - tertiary: css({ - backgroundColor: theme.colors.tertiary, - color: theme.colors.onTertiary, - }), - destructive: css({ - backgroundColor: theme.colors.error, - color: theme.colors.onPrimary, - }), + primary: [ + css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.primary), + ], + secondary: [ + css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + getHoverAndActiveBackground(theme.colors.secondary), + ], + tertiary: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + destructive: [ + css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.error), + ], }; return style[variants]; diff --git a/HDesign/src/components/Flex/Flex.style.ts b/HDesign/src/components/Flex/Flex.style.ts index c86f1b64d..7d2e526a7 100644 --- a/HDesign/src/components/Flex/Flex.style.ts +++ b/HDesign/src/components/Flex/Flex.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {changeCamelCaseToKebabCase} from '@/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase'; +import {changeCamelCaseToKebabCase} from '@utils/changeCamelCaseToKebabCase'; import {FlexDirectionStrictType, FlexProps} from './Flex.type'; diff --git a/HDesign/src/components/Flex/Flex.tsx b/HDesign/src/components/Flex/Flex.tsx index 57a5e7332..26ce953f7 100644 --- a/HDesign/src/components/Flex/Flex.tsx +++ b/HDesign/src/components/Flex/Flex.tsx @@ -1,8 +1,9 @@ /** @jsxImportSource @emotion/react */ import {css} from '@emotion/react'; -import {StrictPropsWithChildren} from '@/types/strictPropsWithChildren'; -import {useTheme} from '@/theme/HDesignProvider'; +import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; + +import {useTheme} from '@theme/HDesignProvider'; import {FlexProps} from './Flex.type'; import {flexStyle} from './Flex.style'; diff --git a/HDesign/src/components/Flex/Flex.type.ts b/HDesign/src/components/Flex/Flex.type.ts index 75467e97e..22db11365 100644 --- a/HDesign/src/components/Flex/Flex.type.ts +++ b/HDesign/src/components/Flex/Flex.type.ts @@ -1,4 +1,4 @@ -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; export type FlexDirectionType = 'row' | 'column' | 'rowReverse' | 'columnReverse'; export type FlexDirectionStrictType = 'row' | 'column' | 'row-reverse' | 'column-reverse'; diff --git a/HDesign/src/components/IconButton/IconButton.tsx b/HDesign/src/components/IconButton/IconButton.tsx index 66d4c34b8..f457fbb62 100644 --- a/HDesign/src/components/IconButton/IconButton.tsx +++ b/HDesign/src/components/IconButton/IconButton.tsx @@ -2,7 +2,7 @@ import {forwardRef} from 'react'; import {IconButtonProps} from '@components/IconButton/IconButton.type'; -import {InputDelete, Plus, Buljusa} from '@/assets'; +import {InputDelete, Plus, Buljusa} from '@assets'; const ICON = { inputDelete: <InputDelete />, diff --git a/HDesign/src/components/InOutItem/InOutItem.style.ts b/HDesign/src/components/InOutItem/InOutItem.style.ts index b3f8eee46..41cd9f97a 100644 --- a/HDesign/src/components/InOutItem/InOutItem.style.ts +++ b/HDesign/src/components/InOutItem/InOutItem.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; export const inOutItemStyle = (theme: Theme) => css({ diff --git a/HDesign/src/components/Input/Input.stories.tsx b/HDesign/src/components/Input/Input.stories.tsx index 97365fa9d..31a226771 100644 --- a/HDesign/src/components/Input/Input.stories.tsx +++ b/HDesign/src/components/Input/Input.stories.tsx @@ -16,6 +16,7 @@ const meta = { }, args: { placeholder: 'placeholder', + autoFocus: true, }, } satisfies Meta<typeof Input>; diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts index cb7471afc..a9ddff89d 100644 --- a/HDesign/src/components/Input/Input.style.ts +++ b/HDesign/src/components/Input/Input.style.ts @@ -34,6 +34,9 @@ export const inputBoxStyle = ( borderRadius: '1rem', backgroundColor: getBackgroundColorStyle(theme, inputType), + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + boxSizing: 'border-box', boxShadow: getBorderStyle(isFocus, theme, isError), }); diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx index cebdfb5a7..410c0a618 100644 --- a/HDesign/src/components/Input/Input.tsx +++ b/HDesign/src/components/Input/Input.tsx @@ -1,20 +1,19 @@ /** @jsxImportSource @emotion/react */ import React, {forwardRef, useImperativeHandle, useRef} from 'react'; -import {useTheme} from '@/theme/HDesignProvider'; +import IconButton from '@components/IconButton/IconButton'; +import {InputProps} from '@components/Input/Input.type'; +import {inputBoxStyle, inputStyle} from '@components/Input/Input.style'; +import {useInput} from '@components/Input/useInput'; -import IconButton from '../IconButton/IconButton'; - -import {useInput} from './useInput'; -import {InputProps} from './Input.type'; -import {inputBoxStyle, inputStyle} from './Input.style'; +import {useTheme} from '@theme/HDesignProvider'; export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( - {value: propsValue, onChange, onFocus, onBlur, inputType, isError, placeholder, ...htmlProps}: InputProps, + {value: propsValue, onChange, onFocus, onBlur, inputType, isError, placeholder, autoFocus, ...htmlProps}: InputProps, ref, ) { - const {theme} = useTheme(); useImperativeHandle(ref, () => inputRef.current!); + const {theme} = useTheme(); const inputRef = useRef<HTMLInputElement>(null); const {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown} = useInput({ propsValue, @@ -22,6 +21,7 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro onBlur, onFocus, inputRef, + autoFocus, }); return ( @@ -33,11 +33,12 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro onChange={handleChange} onBlur={handleBlur} onFocus={handleFocus} - placeholder={inputRef.current === document.activeElement ? '' : placeholder} + placeholder={value ? '' : placeholder} onKeyDown={handleKeyDown} + autoFocus={autoFocus} {...htmlProps} /> - {value && hasFocus && <IconButton iconType="inputDelete" onClick={handleClickDelete} />} + {value && hasFocus && <IconButton tabIndex={-1} iconType="inputDelete" onMouseDown={handleClickDelete} />} </div> ); }); diff --git a/HDesign/src/components/Input/useInput.ts b/HDesign/src/components/Input/useInput.ts index 46a195032..0ff7206c4 100644 --- a/HDesign/src/components/Input/useInput.ts +++ b/HDesign/src/components/Input/useInput.ts @@ -9,7 +9,7 @@ interface UseInputProps<T> { autoFocus?: boolean; } -export const useInput = <T>({propsValue, onChange, onBlur, onFocus, inputRef, autoFocus}: UseInputProps<T>) => { +export const useInput = <T>({propsValue, onChange, onBlur, onFocus, inputRef}: UseInputProps<T>) => { const [value, setValue] = useState<T>(propsValue); const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); diff --git a/HDesign/src/components/LabelGroupInput/Element.tsx b/HDesign/src/components/LabelGroupInput/Element.tsx index 1043aa313..5ffd852bd 100644 --- a/HDesign/src/components/LabelGroupInput/Element.tsx +++ b/HDesign/src/components/LabelGroupInput/Element.tsx @@ -8,13 +8,13 @@ import {ElementProps} from './Element.type'; import {useGroupInputContext} from './GroupInputContext'; const Element: React.FC<ElementProps> = forwardRef<HTMLInputElement, ElementProps>(function Element( - {elementKey, value: propsValue, onChange, onBlur, onFocus, isError, ...htmlProps}: ElementProps, + {elementKey, value: propsValue, onChange, onBlur, onFocus, isError, autoFocus, ...htmlProps}: ElementProps, ref, ) { useImperativeHandle(ref, () => inputRef.current!); const inputRef = useRef<HTMLInputElement>(null); - const {setHasAnyFocus, values, setValues, hasAnyErrors, setHasAnyErrors} = useGroupInputContext(); + const {setHasAnyFocus, values, setValues, errors, setErrors} = useGroupInputContext(); useEffect(() => { setValues({...values, [elementKey]: `${propsValue}`}); @@ -29,7 +29,7 @@ const Element: React.FC<ElementProps> = forwardRef<HTMLInputElement, ElementProp }; useEffect(() => { - setHasAnyErrors({...hasAnyErrors, [elementKey]: isError ?? false}); + setErrors({...errors, [elementKey]: isError ?? false}); }, [isError]); const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => { @@ -54,6 +54,7 @@ const Element: React.FC<ElementProps> = forwardRef<HTMLInputElement, ElementProp onChange={handleChange} onBlur={handleBlur} onFocus={handleFocus} + autoFocus={autoFocus} {...htmlProps} /> ); diff --git a/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx b/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx index a564ef94f..142183e6b 100644 --- a/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx +++ b/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx @@ -5,8 +5,8 @@ interface GroupInputContextProps { setHasAnyFocus: React.Dispatch<React.SetStateAction<boolean>>; values: {[key: string]: string}; setValues: React.Dispatch<React.SetStateAction<{[key: string]: string}>>; - hasAnyErrors: {[key: string]: boolean}; - setHasAnyErrors: React.Dispatch<React.SetStateAction<{[key: string]: boolean}>>; + errors: {[key: string]: boolean}; + setErrors: React.Dispatch<React.SetStateAction<{[key: string]: boolean}>>; } const GroupInputContext = createContext<GroupInputContextProps | undefined>(undefined); @@ -22,10 +22,10 @@ export const useGroupInputContext = () => { export const GroupInputProvider: React.FC<PropsWithChildren> = ({children}: React.PropsWithChildren) => { const [hasAnyFocus, setHasAnyFocus] = useState(false); const [values, setValues] = useState<{[key: string]: string}>({}); - const [hasAnyErrors, setHasAnyErrors] = useState<{[key: string]: boolean}>({}); + const [errors, setErrors] = useState<{[key: string]: boolean}>({}); return ( - <GroupInputContext.Provider value={{hasAnyFocus, setHasAnyFocus, values, setValues, hasAnyErrors, setHasAnyErrors}}> + <GroupInputContext.Provider value={{hasAnyFocus, setHasAnyFocus, values, setValues, errors, setErrors}}> {children} </GroupInputContext.Provider> ); diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx b/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx index b3f48b452..4eec9634f 100644 --- a/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx @@ -58,6 +58,7 @@ export const Playground: Story = { onChange={e => handleChangeName(e)} onBlur={() => console.log('!!!')} isError={isError} + autoFocus /> <LabelGroupInput.Element value={price} @@ -66,6 +67,7 @@ export const Playground: Story = { placeholder="금액" onBlur={() => console.log('!!!')} isError={false} + autoFocus /> </LabelGroupInput> ); diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts b/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts index 99075fe1d..8339ef4a4 100644 --- a/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts @@ -2,36 +2,24 @@ import {css} from '@emotion/react'; import {Theme} from '@/theme/theme.type'; -export const labelInputStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '0.375rem', -}); - -export const labelGroupStyle = css({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - width: '100%', - - paddingInline: '0.5rem', - marginBottom: '0.375rem', -}); - -export const inputGroupStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '0.5rem', -}); - -export const labelTextStyle = (theme: Theme) => +export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => css({ height: '1.125rem', color: theme.colors.gray, + + opacity: hasFocus || hasValue ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', }); -export const errorTextStyle = (theme: Theme) => +export const errorTextStyle = (theme: Theme, isError: boolean) => css({ height: '1.125rem', color: theme.colors.onErrorContainer, + + opacity: isError ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', }); diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx b/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx index e115bc71a..33d1d447d 100644 --- a/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx @@ -1,7 +1,8 @@ /** @jsxImportSource @emotion/react */ import Text from '@components/Text/Text'; -import {useTheme} from '@/theme/HDesignProvider'; + +import {useTheme} from '@theme/HDesignProvider'; import Flex from '../Flex/Flex'; @@ -12,17 +13,20 @@ import {GroupInputProvider, useGroupInputContext} from './GroupInputContext'; const LabelGroupInput: React.FC<LabelGroupInputProps> = ({labelText, errorText, children}: LabelGroupInputProps) => { const {theme} = useTheme(); - const {hasAnyFocus, values, hasAnyErrors} = useGroupInputContext(); + const {hasAnyFocus, values, errors} = useGroupInputContext(); + + const hasAnyValue = !Object.values(values).every(value => value === ''); + const hasAnyError = !Object.values(errors).every(error => !error); return ( <Flex flexDirection="column" gap="0.375rem"> <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> - <Text size="caption" css={labelTextStyle(theme)}> - {(hasAnyFocus || !Object.values(values).every(value => value === '')) && labelText} + <Text size="caption" css={labelTextStyle(theme, hasAnyFocus, hasAnyValue)}> + {labelText} </Text> {errorText && ( - <Text size="caption" css={errorTextStyle(theme)}> - {!Object.values(hasAnyErrors).every(error => !error) && errorText} + <Text size="caption" css={errorTextStyle(theme, hasAnyError)}> + {errorText} </Text> )} </Flex> diff --git a/HDesign/src/components/LabelInput/LabelInput.stories.tsx b/HDesign/src/components/LabelInput/LabelInput.stories.tsx index 853c0260a..a272037a4 100644 --- a/HDesign/src/components/LabelInput/LabelInput.stories.tsx +++ b/HDesign/src/components/LabelInput/LabelInput.stories.tsx @@ -30,6 +30,7 @@ const meta = { // value: '', labelText: '이름', errorText: 'error가 발생했을 때 나타납니다!', + autoFocus: true, }, } satisfies Meta<typeof LabelInput>; diff --git a/HDesign/src/components/LabelInput/LabelInput.style.ts b/HDesign/src/components/LabelInput/LabelInput.style.ts index 5d5eaed8f..df64636e9 100644 --- a/HDesign/src/components/LabelInput/LabelInput.style.ts +++ b/HDesign/src/components/LabelInput/LabelInput.style.ts @@ -1,15 +1,25 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; -export const labelTextStyle = (theme: Theme) => +export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => css({ height: '1.125rem', color: theme.colors.gray, + + opacity: hasFocus || hasValue ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', }); -export const errorTextStyle = (theme: Theme) => +export const errorTextStyle = (theme: Theme, isError: boolean) => css({ height: '1.125rem', color: theme.colors.onErrorContainer, + + opacity: isError ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', }); diff --git a/HDesign/src/components/LabelInput/LabelInput.tsx b/HDesign/src/components/LabelInput/LabelInput.tsx index b7759b361..f9dd3b71a 100644 --- a/HDesign/src/components/LabelInput/LabelInput.tsx +++ b/HDesign/src/components/LabelInput/LabelInput.tsx @@ -3,7 +3,8 @@ import {forwardRef, useImperativeHandle, useRef} from 'react'; import Text from '@components/Text/Text'; -import {useTheme} from '@/theme/HDesignProvider'; + +import {useTheme} from '@theme/HDesignProvider'; import Input from '../Input/Input'; import Flex from '../Flex/Flex'; @@ -17,6 +18,7 @@ const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, Label ref, ) { useImperativeHandle(ref, () => inputRef.current!); + const {theme} = useTheme(); const inputRef = useRef<HTMLInputElement>(null); const {hasFocus} = useLabelInput({inputRef}); @@ -24,11 +26,11 @@ const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, Label return ( <Flex flexDirection="column" gap="0.375rem"> <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> - <Text size="caption" css={labelTextStyle(theme)}> - {(hasFocus || htmlProps.value) && labelText} + <Text size="caption" css={labelTextStyle(theme, hasFocus, !!htmlProps.value)}> + {labelText} </Text> - <Text size="caption" css={errorTextStyle(theme)}> - {isError && errorText} + <Text size="caption" css={errorTextStyle(theme, isError ?? false)}> + {errorText} </Text> </Flex> <Flex flexDirection="column" gap="0.5rem"> diff --git a/HDesign/src/components/LabelInput/LabelInput.type.ts b/HDesign/src/components/LabelInput/LabelInput.type.ts index ae0d0c5f6..ec24b3a30 100644 --- a/HDesign/src/components/LabelInput/LabelInput.type.ts +++ b/HDesign/src/components/LabelInput/LabelInput.type.ts @@ -4,6 +4,7 @@ export interface LabelInputCustomProps { labelText: string; errorText?: string; isError?: boolean; + autoFocus: boolean; } export type LabelInputOptionProps = LabelInputCustomProps & LabelInputCustomProps; diff --git a/HDesign/src/components/LabelInput/useLabelInput.ts b/HDesign/src/components/LabelInput/useLabelInput.ts index ed64fd8bc..e967c5f89 100644 --- a/HDesign/src/components/LabelInput/useLabelInput.ts +++ b/HDesign/src/components/LabelInput/useLabelInput.ts @@ -2,11 +2,16 @@ import {RefObject, useEffect, useState} from 'react'; interface UseLabelInput<T> { inputRef: RefObject<HTMLInputElement>; + autoFocus?: boolean; } -export const useLabelInput = <T>({inputRef}: UseLabelInput<T>) => { +export const useLabelInput = <T>({inputRef, autoFocus}: UseLabelInput<T>) => { const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); + useEffect(() => { + setHasFocus(inputRef.current === document.activeElement); + }, []); + useEffect(() => { inputRef.current?.addEventListener('focus', () => setHasFocus(true)); inputRef.current?.addEventListener('blur', () => setHasFocus(false)); diff --git a/HDesign/src/components/Search/Search.style.ts b/HDesign/src/components/Search/Search.style.ts index 230cf3e8e..0c5203aed 100644 --- a/HDesign/src/components/Search/Search.style.ts +++ b/HDesign/src/components/Search/Search.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; export const searchStyle = css({ position: 'relative', diff --git a/HDesign/src/components/StepItem/StepItem.style.ts b/HDesign/src/components/StepItem/StepItem.style.ts index 0258b47a4..c4752b560 100644 --- a/HDesign/src/components/StepItem/StepItem.style.ts +++ b/HDesign/src/components/StepItem/StepItem.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; export const stepItemStyle = (theme: Theme) => css({ diff --git a/HDesign/src/components/StepItem/StepItem.tsx b/HDesign/src/components/StepItem/StepItem.tsx index 52e79d863..3d7eaf69d 100644 --- a/HDesign/src/components/StepItem/StepItem.tsx +++ b/HDesign/src/components/StepItem/StepItem.tsx @@ -1,5 +1,5 @@ /** @jsxImportSource @emotion/react */ -import {useTheme} from '@/theme/HDesignProvider'; +import {useTheme} from '@theme/HDesignProvider'; import Text from '../Text/Text'; import BillItem from '../BillItem/BillItem'; diff --git a/HDesign/src/components/Tabs/Tabs.stories.tsx b/HDesign/src/components/Tabs/Tabs.stories.tsx index 6d03a7406..a40e60b07 100644 --- a/HDesign/src/components/Tabs/Tabs.stories.tsx +++ b/HDesign/src/components/Tabs/Tabs.stories.tsx @@ -2,7 +2,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import React from 'react'; -import Tabs from '@/components/Tabs/Tabs'; +import Tabs from '@components/Tabs/Tabs'; import Tab from './Tab'; diff --git a/HDesign/src/components/Tabs/Tabs.style.ts b/HDesign/src/components/Tabs/Tabs.style.ts index a4a12f630..99a514547 100644 --- a/HDesign/src/components/Tabs/Tabs.style.ts +++ b/HDesign/src/components/Tabs/Tabs.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; export const tabListStyle = (theme: Theme) => css({ diff --git a/HDesign/src/components/TextButton/TextButton.style.ts b/HDesign/src/components/TextButton/TextButton.style.ts index 6777b1eed..c9ec31a4e 100644 --- a/HDesign/src/components/TextButton/TextButton.style.ts +++ b/HDesign/src/components/TextButton/TextButton.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; import {TextColor} from './TextButton.type'; diff --git a/HDesign/src/components/TextButton/TextButton.tsx b/HDesign/src/components/TextButton/TextButton.tsx index 9d857c38d..c211f05e4 100644 --- a/HDesign/src/components/TextButton/TextButton.tsx +++ b/HDesign/src/components/TextButton/TextButton.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import {forwardRef} from 'react'; -import {useTheme} from '@/theme/HDesignProvider'; +import {useTheme} from '@theme/HDesignProvider'; import Text from '../Text/Text'; diff --git a/HDesign/src/components/Toast/Toast.style.ts b/HDesign/src/components/Toast/Toast.style.ts index 64755d52a..0496bc722 100644 --- a/HDesign/src/components/Toast/Toast.style.ts +++ b/HDesign/src/components/Toast/Toast.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; import {ToastPosition} from './Toast.type'; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index f6449f0bb..f63e55edf 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -13,7 +13,7 @@ import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; import Search from '@components/Search/Search'; import StepItem from '@components/StepItem/StepItem'; import Switch from '@components/Switch/Switch'; -import Tabs from '@/components/Tabs/Tabs'; +import Tabs from '@components/Tabs/Tabs'; import Text from '@components/Text/Text'; import TextButton from '@components/TextButton/TextButton'; import Title from '@components/Title/Title'; diff --git a/HDesign/src/types/strictPropsWithChildren.ts b/HDesign/src/type/strictPropsWithChildren.ts similarity index 100% rename from HDesign/src/types/strictPropsWithChildren.ts rename to HDesign/src/type/strictPropsWithChildren.ts diff --git a/HDesign/src/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase.ts b/HDesign/src/utils/changeCamelCaseToKebabCase.ts similarity index 100% rename from HDesign/src/utils/ return str.replace(/([a-z])([A-Z])/changeCamelCaseToKebabCase.ts rename to HDesign/src/utils/changeCamelCaseToKebabCase.ts diff --git a/HDesign/src/utils/colors.ts b/HDesign/src/utils/colors.ts new file mode 100644 index 000000000..116c670b0 --- /dev/null +++ b/HDesign/src/utils/colors.ts @@ -0,0 +1,88 @@ +export const hexToRgb = (hex: string) => { + hex = hex.slice(1); + if (hex.length === 3) { + hex = hex + .split('') + .reduce<string[]>((acc, a) => { + acc.push(a + a); + return acc; + }, []) + .join(''); + } + + if (hex.length !== 6) { + throw new Error(`잘못된 색상값이 입력됐습니다. : ${hex} 3자리(#fff), 6자리(#fe0000)hex 값만 입력 가능합니다.`); + } + + const regex = new RegExp(`.{1,2}`, 'g'); + const hexArray = hex.match(regex) as string[]; + + return `rgb(${hexArray.map(n => parseInt(n, 16)).join(', ')})`; +}; + +export const rgbToColors = (rgb: string) => { + if (rgb.slice(0, 3) !== 'rgb') { + throw new Error('잘못된 색상값이 입력됐습니다. rgb() 값만 입력 가능합니다.'); + } + + return rgb + .slice(4, -1) + .split(',') + .map(a => Number(a.trim())); +}; + +export const hexToColors = (hex: string) => { + return rgbToColors(hexToRgb(hex)); +}; + +function intToHex(int: number) { + const hex = int.toString(16); + return hex.length === 1 ? `0${hex}` : hex; +} + +export const colorsToRgb = (colors: number[]) => { + return `rgb(${colors.join(', ')})`; +}; + +export const rgbToHex = (rgb: string) => { + const colors = rgbToColors(rgb); + return `#${colors.map((n, i) => intToHex(i === 3 ? Math.round(255 * n) : n)).join('')}`; +}; + +export const colorsToHex = (colors: number[]) => { + return rgbToHex(colorsToRgb(colors)); +}; + +export const setDarker = (hex: string, coefficient: number) => { + const colors = hexToColors(hex); + const adjustCoefficient = coefficient > 1 ? 1 : coefficient < 0 ? 0 : coefficient; + const darkerColors = colors.map(color => Math.round(color * (1 - adjustCoefficient))); + + return colorsToHex(darkerColors); +}; + +export const setLighter = (hex: string, coefficient: number) => { + const colors = hexToColors(hex); + const adjustCoefficient = coefficient > 1 ? 1 : coefficient < 0 ? 0 : coefficient; + const lighterColors = colors.map(color => Math.round(color + (255 - color) * adjustCoefficient)); + + return colorsToHex(lighterColors); +}; + +export const getLuminance = (hex: string) => { + const colors = hexToColors(hex); + const values = colors.map(color => { + const value = color / 255; + return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4; + }); + + return Number((0.2126 * values[0] + 0.7152 * values[1] + 0.0722 * values[2]).toFixed(3)); +}; + +export const setEmphasize = (hex: string, threshold: number, coefficient = 0.15) => { + return getLuminance(hex) > threshold ? setDarker(hex, coefficient) : setLighter(hex, coefficient); +}; + +export const setOnTextColor = (hex: string, threshold: number, blackHex: string, whiteHex: string) => { + return getLuminance(hex) > threshold ? blackHex : whiteHex; +}; diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json index 371b40efe..04b12a2a9 100644 --- a/HDesign/tsconfig.json +++ b/HDesign/tsconfig.json @@ -16,12 +16,14 @@ "allowJs": true, "baseUrl": ".", "paths": { - "@/*": ["src/*"], + "@*": ["src/*"], "@components/*": ["src/components/*"], "@layouts/*": ["src/layouts/*"], "@token/*": ["src/token/*"], + "@type/*": ["src/type/*"], "@theme/*": ["src/theme/*"], - "@assets/*": ["src/assets/*"] + "@assets/*": ["src/assets/*"], + "@utils/*": ["src/utils/*"] }, "jsxImportSource": "@emotion/react", "allowSyntheticDefaultImports": true From 4b6a9724e92a82d6faa4b1bf377d6751746d9c8e Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Mon, 5 Aug 2024 16:56:49 +0900 Subject: [PATCH 115/273] =?UTF-8?q?[FE]=20ListButton=20component=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20(#203)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 --- HDesign/.storybook/preview.tsx | 2 +- HDesign/src/assets/index.ts | 1 + HDesign/src/assets/rightChevron.svg | 3 ++ .../src/components/IconButton/IconButton.tsx | 6 +++- .../components/IconButton/IconButton.type.ts | 2 +- .../ListButton/ListButton.stories.tsx | 32 ++++++++++++++++++ .../components/ListButton/ListButton.style.ts | 21 ++++++++++++ .../src/components/ListButton/ListButton.tsx | 33 +++++++++++++++++++ .../components/ListButton/ListButton.type.ts | 10 ++++++ 9 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 HDesign/src/assets/rightChevron.svg create mode 100644 HDesign/src/components/ListButton/ListButton.stories.tsx create mode 100644 HDesign/src/components/ListButton/ListButton.style.ts create mode 100644 HDesign/src/components/ListButton/ListButton.tsx create mode 100644 HDesign/src/components/ListButton/ListButton.type.ts diff --git a/HDesign/.storybook/preview.tsx b/HDesign/.storybook/preview.tsx index 1b16d7c39..22008ad03 100644 --- a/HDesign/.storybook/preview.tsx +++ b/HDesign/.storybook/preview.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +/** @jsxImportSource @emotion/react */ import type {Preview} from '@storybook/react'; import {HDesignProvider} from '../src/theme/HDesignProvider'; diff --git a/HDesign/src/assets/index.ts b/HDesign/src/assets/index.ts index b20e4ad3d..870a1dec5 100644 --- a/HDesign/src/assets/index.ts +++ b/HDesign/src/assets/index.ts @@ -4,3 +4,4 @@ export {default as Buljusa} from '@assets/buljusa.svg'; export {default as Arrow} from '@assets/arrow.svg'; export {default as Error} from '@assets/error.svg'; export {default as Trash} from '@assets/trash.svg'; +export {default as RightChevron} from '@assets/rightChevron.svg'; diff --git a/HDesign/src/assets/rightChevron.svg b/HDesign/src/assets/rightChevron.svg new file mode 100644 index 000000000..59ecf5cb2 --- /dev/null +++ b/HDesign/src/assets/rightChevron.svg @@ -0,0 +1,3 @@ +<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M2 2L6 6L2 10" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +</svg> diff --git a/HDesign/src/components/IconButton/IconButton.tsx b/HDesign/src/components/IconButton/IconButton.tsx index f457fbb62..076274ac1 100644 --- a/HDesign/src/components/IconButton/IconButton.tsx +++ b/HDesign/src/components/IconButton/IconButton.tsx @@ -2,12 +2,16 @@ import {forwardRef} from 'react'; import {IconButtonProps} from '@components/IconButton/IconButton.type'; -import {InputDelete, Plus, Buljusa} from '@assets'; +import {InputDelete, Plus, Buljusa, RightChevron, Arrow, Trash, Error} from '@assets'; const ICON = { inputDelete: <InputDelete />, plus: <Plus />, buljusa: <Buljusa />, + rightChevron: <RightChevron />, + arrow: <Arrow />, + error: <Error />, + trash: <Trash />, }; export const IconButton: React.FC<IconButtonProps> = forwardRef<HTMLButtonElement, IconButtonProps>(function Button( diff --git a/HDesign/src/components/IconButton/IconButton.type.ts b/HDesign/src/components/IconButton/IconButton.type.ts index 10415621c..06141aaaa 100644 --- a/HDesign/src/components/IconButton/IconButton.type.ts +++ b/HDesign/src/components/IconButton/IconButton.type.ts @@ -1,4 +1,4 @@ -type IconButtonType = 'inputDelete' | 'plus' | 'buljusa'; +type IconButtonType = 'inputDelete' | 'plus' | 'buljusa' | 'rightChevron' | 'arrow' | 'error' | 'trash'; export interface IconButtonStyleProps {} diff --git a/HDesign/src/components/ListButton/ListButton.stories.tsx b/HDesign/src/components/ListButton/ListButton.stories.tsx new file mode 100644 index 000000000..27f7744d1 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.stories.tsx @@ -0,0 +1,32 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import ListButton from '@components/ListButton/ListButton'; + +const meta = { + title: 'Components/ListButton', + component: ListButton, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + prefix: { + description: '', + control: {type: 'text'}, + }, + suffix: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + prefix: '전체 참여자', + suffix: '7명', + }, +} satisfies Meta<typeof ListButton>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/ListButton/ListButton.style.ts b/HDesign/src/components/ListButton/ListButton.style.ts new file mode 100644 index 000000000..ca6a686ff --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.style.ts @@ -0,0 +1,21 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const listButtonStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + padding: '0.375rem 1rem', + backgroundColor: theme.colors.white, + + boxShadow: `0 1px 0 0 ${theme.colors.grayContainer} inset `, + }); + +export const textStyle = (theme: Theme) => + css({ + color: theme.colors.gray, + }); diff --git a/HDesign/src/components/ListButton/ListButton.tsx b/HDesign/src/components/ListButton/ListButton.tsx new file mode 100644 index 000000000..9a161f12b --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.tsx @@ -0,0 +1,33 @@ +/** @jsxImportSource @emotion/react */ +import React, {forwardRef} from 'react'; + +import Text from '@components/Text/Text'; +import IconButton from '@components/IconButton/IconButton'; +import Flex from '@components/Flex/Flex'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {ListButtonProps} from './ListButton.type'; +import {listButtonStyle, textStyle} from './ListButton.style'; + +export const ListButton: React.FC<ListButtonProps> = forwardRef<HTMLButtonElement, ListButtonProps>(function Button( + {prefix, suffix, ...htmlProps}: ListButtonProps, + ref, +) { + const {theme} = useTheme(); + return ( + <button css={listButtonStyle(theme)} ref={ref} {...htmlProps}> + <Text size="caption" css={textStyle(theme)}> + {prefix} + </Text> + <Flex gap="0.5rem" alignItems="center"> + <Text size="caption" css={textStyle(theme)}> + {suffix} + </Text> + <IconButton iconType="rightChevron" /> + </Flex> + </button> + ); +}); + +export default ListButton; diff --git a/HDesign/src/components/ListButton/ListButton.type.ts b/HDesign/src/components/ListButton/ListButton.type.ts new file mode 100644 index 000000000..788117870 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.type.ts @@ -0,0 +1,10 @@ +export interface ListButtonStyleProps {} + +export interface ListButtonCustomProps { + prefix?: string; + suffix?: string; +} + +export type ListButtonOptionProps = ListButtonStyleProps & ListButtonCustomProps; + +export type ListButtonProps = React.ComponentProps<'button'> & ListButtonOptionProps; From 4b836eacdfbc0776c46e9f41215bd190be8ba450 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:13:09 +0900 Subject: [PATCH 116/273] =?UTF-8?q?feat:=20=EA=B0=9C=EB=B3=84=20ActionItem?= =?UTF-8?q?=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?StepItem=20=EB=B0=8F=20BillItem=20/=20InOutItem=20component=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20(#211)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 --- HDesign/package-lock.json | 4 +- HDesign/package.json | 2 +- HDesign/src/assets/arrow.svg | 3 - HDesign/src/assets/buljusa.svg | 4 +- HDesign/src/assets/confirm.svg | 18 ++-- HDesign/src/assets/error.svg | 11 +- HDesign/src/assets/index.ts | 4 +- HDesign/src/assets/inputDelete.svg | 10 +- HDesign/src/assets/plus.svg | 4 - HDesign/src/assets/rightChevron.svg | 2 +- HDesign/src/assets/search.svg | 3 + HDesign/src/assets/trash.svg | 4 +- .../components/BillItem/BillItem.stories.tsx | 32 ------ .../src/components/BillItem/BillItem.style.ts | 8 -- HDesign/src/components/BillItem/BillItem.tsx | 34 ------ .../src/components/BillItem/BillItem.type.ts | 11 -- .../components/BottomSheet/BottomSheet.tsx | 8 +- .../BottomSheet/BottomSheet.type.ts | 4 - .../DragHandleItem/DragHandleItem.stories.tsx | 14 ++- .../DragHandleItem/DragHandleItem.style.ts | 7 +- .../DragHandleItem/DragHandleItem.tsx | 46 ++++---- .../DragHandleItem/DragHandleItem.type.ts | 18 ++++ .../DragHandleItemContainer.stories.tsx | 86 +++++++++++++++ .../DragHandleItemContainer.style.ts | 37 +++++++ .../DragHandleItemContainer.tsx | 49 +++++++++ .../DragHandleItemContainer.type.ts | 16 +++ .../components/ExpenseList/ExpenseList.tsx | 6 +- .../components/FixedButton/FixedButton.tsx | 8 +- HDesign/src/components/Icon/Icon.stories.tsx | 28 +++++ HDesign/src/components/Icon/Icon.style.ts | 38 +++++++ HDesign/src/components/Icon/Icon.tsx | 29 +++++ HDesign/src/components/Icon/Icon.type.ts | 16 +++ .../IconButton/IconButton.stories.tsx | 27 ++++- .../components/IconButton/IconButton.style.ts | 101 ++++++++++++++++++ .../src/components/IconButton/IconButton.tsx | 20 ++-- .../components/IconButton/IconButton.type.ts | 13 ++- .../InOutItem/InOutItem.stories.tsx | 32 ------ .../components/InOutItem/InOutItem.style.ts | 24 ----- .../src/components/InOutItem/InOutItem.tsx | 35 ------ .../components/InOutItem/InOutItem.type.ts | 13 --- HDesign/src/components/Input/Input.tsx | 7 +- .../src/components/ListButton/ListButton.tsx | 5 +- .../components/StepItem/StepItem.stories.tsx | 46 -------- .../src/components/StepItem/StepItem.style.ts | 34 ------ HDesign/src/components/StepItem/StepItem.tsx | 43 -------- .../src/components/StepItem/StepItem.type.ts | 13 --- HDesign/src/components/Toast/Toast.tsx | 8 +- HDesign/src/index.tsx | 21 ++-- HDesign/src/token/colors.ts | 16 ++- 49 files changed, 591 insertions(+), 431 deletions(-) delete mode 100644 HDesign/src/assets/arrow.svg delete mode 100644 HDesign/src/assets/plus.svg create mode 100644 HDesign/src/assets/search.svg delete mode 100644 HDesign/src/components/BillItem/BillItem.stories.tsx delete mode 100644 HDesign/src/components/BillItem/BillItem.style.ts delete mode 100644 HDesign/src/components/BillItem/BillItem.tsx delete mode 100644 HDesign/src/components/BillItem/BillItem.type.ts create mode 100644 HDesign/src/components/DragHandleItem/DragHandleItem.type.ts create mode 100644 HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx create mode 100644 HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts create mode 100644 HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx create mode 100644 HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts create mode 100644 HDesign/src/components/Icon/Icon.stories.tsx create mode 100644 HDesign/src/components/Icon/Icon.style.ts create mode 100644 HDesign/src/components/Icon/Icon.tsx create mode 100644 HDesign/src/components/Icon/Icon.type.ts create mode 100644 HDesign/src/components/IconButton/IconButton.style.ts delete mode 100644 HDesign/src/components/InOutItem/InOutItem.stories.tsx delete mode 100644 HDesign/src/components/InOutItem/InOutItem.style.ts delete mode 100644 HDesign/src/components/InOutItem/InOutItem.tsx delete mode 100644 HDesign/src/components/InOutItem/InOutItem.type.ts delete mode 100644 HDesign/src/components/StepItem/StepItem.stories.tsx delete mode 100644 HDesign/src/components/StepItem/StepItem.style.ts delete mode 100644 HDesign/src/components/StepItem/StepItem.tsx delete mode 100644 HDesign/src/components/StepItem/StepItem.type.ts diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index dae3e34ff..1dd57358e 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.55", + "version": "0.1.58", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.55", + "version": "0.1.58", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index 90ad0d4d1..dcbd20ea3 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.55", + "version": "0.1.58", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/assets/arrow.svg b/HDesign/src/assets/arrow.svg deleted file mode 100644 index 4d8bac605..000000000 --- a/HDesign/src/assets/arrow.svg +++ /dev/null @@ -1,3 +0,0 @@ -<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M1 1.5L6 6L1 10.5" stroke="black" stroke-opacity="0.4" stroke-width="1.5" stroke-linecap="round"/> -</svg> diff --git a/HDesign/src/assets/buljusa.svg b/HDesign/src/assets/buljusa.svg index e8008a2fb..fe5c47534 100644 --- a/HDesign/src/assets/buljusa.svg +++ b/HDesign/src/assets/buljusa.svg @@ -1,4 +1,4 @@ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M6.375 12.5C6.54076 12.5 6.69973 12.4407 6.81694 12.3352C6.93415 12.2298 7 12.0867 7 11.9375C7 11.7883 6.93415 11.6452 6.81694 11.5398C6.69973 11.4343 6.54076 11.375 6.375 11.375C6.20924 11.375 6.05027 11.4343 5.93306 11.5398C5.81585 11.6452 5.75 11.7883 5.75 11.9375C5.75 12.0867 5.81585 12.2298 5.93306 12.3352C6.05027 12.4407 6.20924 12.5 6.375 12.5ZM6.375 8.5625C6.54076 8.5625 6.69973 8.50324 6.81694 8.39775C6.93415 8.29226 7 8.14918 7 8C7 7.85082 6.93415 7.70774 6.81694 7.60225C6.69973 7.49676 6.54076 7.4375 6.375 7.4375C6.20924 7.4375 6.05027 7.49676 5.93306 7.60225C5.81585 7.70774 5.75 7.85082 5.75 8C5.75 8.14918 5.81585 8.29226 5.93306 8.39775C6.05027 8.50324 6.20924 8.5625 6.375 8.5625ZM6.375 4.625C6.54076 4.625 6.69973 4.56574 6.81694 4.46025C6.93415 4.35476 7 4.21168 7 4.0625C7 3.91332 6.93415 3.77024 6.81694 3.66475C6.69973 3.55926 6.54076 3.5 6.375 3.5C6.20924 3.5 6.05027 3.55926 5.93306 3.66475C5.81585 3.77024 5.75 3.91332 5.75 4.0625C5.75 4.21168 5.81585 4.35476 5.93306 4.46025C6.05027 4.56574 6.20924 4.625 6.375 4.625Z" fill="#B2B1B6" stroke="#B2B1B6"/> -<path d="M9.625 12.5C9.79076 12.5 9.94973 12.4407 10.0669 12.3352C10.1842 12.2298 10.25 12.0867 10.25 11.9375C10.25 11.7883 10.1842 11.6452 10.0669 11.5398C9.94973 11.4343 9.79076 11.375 9.625 11.375C9.45924 11.375 9.30027 11.4343 9.18306 11.5398C9.06585 11.6452 9 11.7883 9 11.9375C9 12.0867 9.06585 12.2298 9.18306 12.3352C9.30027 12.4407 9.45924 12.5 9.625 12.5ZM9.625 8.5625C9.79076 8.5625 9.94973 8.50324 10.0669 8.39775C10.1842 8.29226 10.25 8.14918 10.25 8C10.25 7.85082 10.1842 7.70774 10.0669 7.60225C9.94973 7.49676 9.79076 7.4375 9.625 7.4375C9.45924 7.4375 9.30027 7.49676 9.18306 7.60225C9.06585 7.70774 9 7.85082 9 8C9 8.14918 9.06585 8.29226 9.18306 8.39775C9.30027 8.50324 9.45924 8.5625 9.625 8.5625ZM9.625 4.625C9.79076 4.625 9.94973 4.56574 10.0669 4.46025C10.1842 4.35476 10.25 4.21168 10.25 4.0625C10.25 3.91332 10.1842 3.77024 10.0669 3.66475C9.94973 3.55926 9.79076 3.5 9.625 3.5C9.45924 3.5 9.30027 3.55926 9.18306 3.66475C9.06585 3.77024 9 3.91332 9 4.0625C9 4.21168 9.06585 4.35476 9.18306 4.46025C9.30027 4.56574 9.45924 4.625 9.625 4.625Z" fill="#B2B1B6" stroke="#B2B1B6"/> +<path d="M6.375 12.5C6.54076 12.5 6.69973 12.4407 6.81694 12.3352C6.93415 12.2298 7 12.0867 7 11.9375C7 11.7883 6.93415 11.6452 6.81694 11.5398C6.69973 11.4343 6.54076 11.375 6.375 11.375C6.20924 11.375 6.05027 11.4343 5.93306 11.5398C5.81585 11.6452 5.75 11.7883 5.75 11.9375C5.75 12.0867 5.81585 12.2298 5.93306 12.3352C6.05027 12.4407 6.20924 12.5 6.375 12.5ZM6.375 8.5625C6.54076 8.5625 6.69973 8.50324 6.81694 8.39775C6.93415 8.29226 7 8.14918 7 8C7 7.85082 6.93415 7.70774 6.81694 7.60225C6.69973 7.49676 6.54076 7.4375 6.375 7.4375C6.20924 7.4375 6.05027 7.49676 5.93306 7.60225C5.81585 7.70774 5.75 7.85082 5.75 8C5.75 8.14918 5.81585 8.29226 5.93306 8.39775C6.05027 8.50324 6.20924 8.5625 6.375 8.5625ZM6.375 4.625C6.54076 4.625 6.69973 4.56574 6.81694 4.46025C6.93415 4.35476 7 4.21168 7 4.0625C7 3.91332 6.93415 3.77024 6.81694 3.66475C6.69973 3.55926 6.54076 3.5 6.375 3.5C6.20924 3.5 6.05027 3.55926 5.93306 3.66475C5.81585 3.77024 5.75 3.91332 5.75 4.0625C5.75 4.21168 5.81585 4.35476 5.93306 4.46025C6.05027 4.56574 6.20924 4.625 6.375 4.625Z" fill="currentColor" stroke="currentColor"/> +<path d="M9.625 12.5C9.79076 12.5 9.94973 12.4407 10.0669 12.3352C10.1842 12.2298 10.25 12.0867 10.25 11.9375C10.25 11.7883 10.1842 11.6452 10.0669 11.5398C9.94973 11.4343 9.79076 11.375 9.625 11.375C9.45924 11.375 9.30027 11.4343 9.18306 11.5398C9.06585 11.6452 9 11.7883 9 11.9375C9 12.0867 9.06585 12.2298 9.18306 12.3352C9.30027 12.4407 9.45924 12.5 9.625 12.5ZM9.625 8.5625C9.79076 8.5625 9.94973 8.50324 10.0669 8.39775C10.1842 8.29226 10.25 8.14918 10.25 8C10.25 7.85082 10.1842 7.70774 10.0669 7.60225C9.94973 7.49676 9.79076 7.4375 9.625 7.4375C9.45924 7.4375 9.30027 7.49676 9.18306 7.60225C9.06585 7.70774 9 7.85082 9 8C9 8.14918 9.06585 8.29226 9.18306 8.39775C9.30027 8.50324 9.45924 8.5625 9.625 8.5625ZM9.625 4.625C9.79076 4.625 9.94973 4.56574 10.0669 4.46025C10.1842 4.35476 10.25 4.21168 10.25 4.0625C10.25 3.91332 10.1842 3.77024 10.0669 3.66475C9.94973 3.55926 9.79076 3.5 9.625 3.5C9.45924 3.5 9.30027 3.55926 9.18306 3.66475C9.06585 3.77024 9 3.91332 9 4.0625C9 4.21168 9.06585 4.35476 9.18306 4.46025C9.30027 4.56574 9.45924 4.625 9.625 4.625Z" fill="currentColor" stroke="currentColor"/> </svg> diff --git a/HDesign/src/assets/confirm.svg b/HDesign/src/assets/confirm.svg index 7e017c7b1..820585a17 100644 --- a/HDesign/src/assets/confirm.svg +++ b/HDesign/src/assets/confirm.svg @@ -1,10 +1,10 @@ -<svg width="26" height="26" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <g transform="translate(2, 2)"> - <path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C11.3132 20 12.6136 19.7413 13.8268 19.2388C15.0401 18.7362 16.1425 17.9997 17.0711 17.0711C17.9997 16.1425 18.7362 15.0401 19.2388 13.8268C19.7413 12.6136 20 11.3132 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 -1.95685e-08 10 0C7.34784 3.95203e-08 4.8043 1.05357 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C4.8043 18.9464 7.34784 20 10 20ZM15.2978 7.37778C15.3953 7.26627 15.4696 7.13638 15.5162 6.99574C15.5628 6.85511 15.5808 6.70657 15.5692 6.55887C15.5575 6.41117 15.5165 6.26729 15.4484 6.1357C15.3804 6.0041 15.2866 5.88745 15.1728 5.7926C15.059 5.69775 14.9274 5.62663 14.7857 5.5834C14.644 5.54018 14.495 5.52574 14.3476 5.54092C14.2003 5.5561 14.0574 5.60061 13.9275 5.67181C13.7976 5.74302 13.6832 5.83949 13.5911 5.95556L9.59333 10.7522C9.20778 11.2144 8.99111 11.4711 8.81889 11.6278L8.81222 11.6344L8.80444 11.6289C8.61778 11.4878 8.37889 11.2522 7.95445 10.8267L6.34111 9.21445C6.13155 9.01205 5.85088 8.90005 5.55956 8.90259C5.26823 8.90512 4.98954 9.02197 4.78354 9.22798C4.57753 9.43399 4.46067 9.71267 4.45814 10.004C4.45561 10.2953 4.5676 10.576 4.77 10.7856L6.38222 12.3978L6.42778 12.4433C6.79111 12.8067 7.13889 13.1556 7.46445 13.4011C7.82778 13.6767 8.30444 13.9344 8.91444 13.9078C9.52556 13.88 9.97667 13.5789 10.3144 13.2722C10.6144 12.9978 10.9311 12.6189 11.2589 12.2244L11.3 12.1756L15.2978 7.37778Z" fill="#BFFF75"/> - </g> - <defs> - <clipPath id="clip0_1042_1689"> - <rect width="24" height="24" rx="8" fill="white"/> - </clipPath> - </defs> +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1042_1615)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C11.3132 20 12.6136 19.7413 13.8268 19.2388C15.0401 18.7362 16.1425 17.9997 17.0711 17.0711C17.9997 16.1425 18.7362 15.0401 19.2388 13.8268C19.7413 12.6136 20 11.3132 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 -1.95685e-08 10 0C7.34784 3.95203e-08 4.8043 1.05357 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C4.8043 18.9464 7.34784 20 10 20ZM15.2978 7.37778C15.3953 7.26627 15.4696 7.13638 15.5162 6.99574C15.5628 6.85511 15.5808 6.70657 15.5692 6.55887C15.5575 6.41117 15.5165 6.26729 15.4484 6.1357C15.3804 6.0041 15.2866 5.88745 15.1728 5.7926C15.059 5.69775 14.9274 5.62663 14.7857 5.5834C14.644 5.54018 14.495 5.52574 14.3476 5.54092C14.2003 5.5561 14.0574 5.60061 13.9275 5.67181C13.7976 5.74302 13.6832 5.83949 13.5911 5.95556L9.59333 10.7522C9.20778 11.2144 8.99111 11.4711 8.81889 11.6278L8.81222 11.6344L8.80444 11.6289C8.61778 11.4878 8.37889 11.2522 7.95445 10.8267L6.34111 9.21445C6.13155 9.01205 5.85088 8.90005 5.55956 8.90259C5.26823 8.90512 4.98954 9.02197 4.78354 9.22798C4.57753 9.43399 4.46067 9.71267 4.45814 10.004C4.45561 10.2953 4.5676 10.576 4.77 10.7856L6.38222 12.3978L6.42778 12.4433C6.79111 12.8067 7.13889 13.1556 7.46445 13.4011C7.82778 13.6767 8.30444 13.9344 8.91444 13.9078C9.52556 13.88 9.97667 13.5789 10.3144 13.2722C10.6144 12.9978 10.9311 12.6189 11.2589 12.2244L11.3 12.1756L15.2978 7.37778Z" fill="#BFFF75"/> +</g> +<defs> +<clipPath id="clip0_1042_1615"> +<rect width="20" height="20" rx="8" fill="white"/> +</clipPath> +</defs> </svg> diff --git a/HDesign/src/assets/error.svg b/HDesign/src/assets/error.svg index 0c4014ab7..c77a2f4a3 100644 --- a/HDesign/src/assets/error.svg +++ b/HDesign/src/assets/error.svg @@ -1,3 +1,10 @@ -<svg width="26" height="26" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M13 13H11V7H13M13 17H11V15H13M12 2C10.6868 2 9.38642 2.25866 8.17317 2.7612C6.95991 3.26375 5.85752 4.00035 4.92893 4.92893C3.05357 6.8043 2 9.34784 2 12C2 14.6522 3.05357 17.1957 4.92893 19.0711C5.85752 19.9997 6.95991 20.7362 8.17317 21.2388C9.38642 21.7413 10.6868 22 12 22C14.6522 22 17.1957 20.9464 19.0711 19.0711C20.9464 17.1957 22 14.6522 22 12C22 10.6868 21.7413 9.38642 21.2388 8.17317C20.7362 6.95991 19.9997 5.85752 19.0711 4.92893C18.1425 4.00035 17.0401 3.26375 15.8268 2.7612C14.6136 2.25866 13.3132 2 12 2Z" fill="#ECFF59"/> +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1042_1585)"> +<path d="M11 11H9V5H11M11 15H9V13H11M10 0C8.68678 0 7.38642 0.258658 6.17317 0.761205C4.95991 1.26375 3.85752 2.00035 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C3.85752 17.9997 4.95991 18.7362 6.17317 19.2388C7.38642 19.7413 8.68678 20 10 20C12.6522 20 15.1957 18.9464 17.0711 17.0711C18.9464 15.1957 20 12.6522 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 0 10 0Z" fill="#ECFF59"/> +</g> +<defs> +<clipPath id="clip0_1042_1585"> +<rect width="20" height="20" rx="8" fill="white"/> +</clipPath> +</defs> </svg> diff --git a/HDesign/src/assets/index.ts b/HDesign/src/assets/index.ts index 870a1dec5..a9c277581 100644 --- a/HDesign/src/assets/index.ts +++ b/HDesign/src/assets/index.ts @@ -1,7 +1,7 @@ export {default as InputDelete} from '@assets/inputDelete.svg'; -export {default as Plus} from '@assets/plus.svg'; export {default as Buljusa} from '@assets/buljusa.svg'; -export {default as Arrow} from '@assets/arrow.svg'; export {default as Error} from '@assets/error.svg'; +export {default as Confirm} from '@assets/confirm.svg'; export {default as Trash} from '@assets/trash.svg'; +export {default as Search} from '@assets/search.svg'; export {default as RightChevron} from '@assets/rightChevron.svg'; diff --git a/HDesign/src/assets/inputDelete.svg b/HDesign/src/assets/inputDelete.svg index 06d850889..4356bb854 100644 --- a/HDesign/src/assets/inputDelete.svg +++ b/HDesign/src/assets/inputDelete.svg @@ -1,4 +1,10 @@ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> -<rect width="20" height="20" rx="10" fill="#B2B1B6"/> -<path d="M14 6L6 14M6 6L14 14" stroke="#E7E6EB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +<g clip-path="url(#clip0_940_872)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20ZM6.70711 5.29289C6.31658 4.90237 5.68342 4.90237 5.29289 5.29289C4.90237 5.68342 4.90237 6.31658 5.29289 6.70711L8.58579 10L5.29289 13.2929C4.90237 13.6834 4.90237 14.3166 5.29289 14.7071C5.68342 15.0976 6.31658 15.0976 6.70711 14.7071L10 11.4142L13.2929 14.7071C13.6834 15.0976 14.3166 15.0976 14.7071 14.7071C15.0976 14.3166 15.0976 13.6834 14.7071 13.2929L11.4142 10L14.7071 6.70711C15.0976 6.31658 15.0976 5.68342 14.7071 5.29289C14.3166 4.90237 13.6834 4.90237 13.2929 5.29289L10 8.58579L6.70711 5.29289Z" fill="currentColor"/> +</g> +<defs> +<clipPath id="clip0_940_872"> +<rect width="20" height="20" rx="8" fill="white"/> +</clipPath> +</defs> </svg> diff --git a/HDesign/src/assets/plus.svg b/HDesign/src/assets/plus.svg deleted file mode 100644 index 458dca8fd..000000000 --- a/HDesign/src/assets/plus.svg +++ /dev/null @@ -1,4 +0,0 @@ -<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> -<rect x="0.5" width="32" height="32" rx="8" fill="#F4E8FF"/> -<path d="M24.5 17.1429H17.6429V24H15.3571V17.1429H8.5V14.8571H15.3571V8H17.6429V14.8571H24.5V17.1429Z" fill="#8425EC"/> -</svg> diff --git a/HDesign/src/assets/rightChevron.svg b/HDesign/src/assets/rightChevron.svg index 59ecf5cb2..5cd777f1b 100644 --- a/HDesign/src/assets/rightChevron.svg +++ b/HDesign/src/assets/rightChevron.svg @@ -1,3 +1,3 @@ <svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M2 2L6 6L2 10" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +<path d="M2 2L6 6L2 10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> </svg> diff --git a/HDesign/src/assets/search.svg b/HDesign/src/assets/search.svg new file mode 100644 index 000000000..4f33e89c3 --- /dev/null +++ b/HDesign/src/assets/search.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M15.977 14.472H15.187L14.907 14.202C15.532 13.4759 15.9887 12.6207 16.2446 11.6976C16.5004 10.7744 16.5491 9.80612 16.387 8.86197C15.917 6.08197 13.597 3.86197 10.797 3.52197C9.81264 3.39744 8.81281 3.49974 7.87405 3.82106C6.93529 4.14238 6.08247 4.67419 5.38086 5.3758C4.67924 6.07742 4.14743 6.93023 3.82611 7.869C3.5048 8.80776 3.40249 9.80759 3.52703 10.792C3.86703 13.592 6.08703 15.912 8.86703 16.382C9.81118 16.544 10.7795 16.4954 11.7026 16.2395C12.6258 15.9837 13.481 15.5269 14.207 14.902L14.477 15.182V15.972L18.727 20.222C19.137 20.632 19.807 20.632 20.217 20.222C20.627 19.812 20.627 19.142 20.217 18.732L15.977 14.472ZM9.97703 14.472C7.48703 14.472 5.47703 12.462 5.47703 9.97197C5.47703 7.48197 7.48703 5.47197 9.97703 5.47197C12.467 5.47197 14.477 7.48197 14.477 9.97197C14.477 12.462 12.467 14.472 9.97703 14.472Z" fill="currentColor"/> +</svg> diff --git a/HDesign/src/assets/trash.svg b/HDesign/src/assets/trash.svg index 086ebc748..09b228b17 100644 --- a/HDesign/src/assets/trash.svg +++ b/HDesign/src/assets/trash.svg @@ -1,3 +1,3 @@ -<svg width="22" height="24" viewBox="0 0 22 24" fill="none" xmlns="http://www.w3.org/2000/svg"> -<path d="M8.5 4H13.5C13.5 3.33696 13.2366 2.70107 12.7678 2.23223C12.2989 1.76339 11.663 1.5 11 1.5C10.337 1.5 9.70107 1.76339 9.23223 2.23223C8.76339 2.70107 8.5 3.33696 8.5 4ZM7 4C7 2.93913 7.42143 1.92172 8.17157 1.17157C8.92172 0.421427 9.93913 0 11 0C12.0609 0 13.0783 0.421427 13.8284 1.17157C14.5786 1.92172 15 2.93913 15 4H21.25C21.4489 4 21.6397 4.07902 21.7803 4.21967C21.921 4.36032 22 4.55109 22 4.75C22 4.94891 21.921 5.13968 21.7803 5.28033C21.6397 5.42098 21.4489 5.5 21.25 5.5H19.94L18.723 20.103C18.6345 21.1653 18.1499 22.1556 17.3655 22.8774C16.5811 23.5992 15.554 23.9999 14.488 24H7.512C6.44599 23.9999 5.41894 23.5992 4.6345 22.8774C3.85007 22.1556 3.36554 21.1653 3.277 20.103L2.06 5.5H0.75C0.551088 5.5 0.360322 5.42098 0.21967 5.28033C0.0790175 5.13968 0 4.94891 0 4.75C0 4.55109 0.0790175 4.36032 0.21967 4.21967C0.360322 4.07902 0.551088 4 0.75 4H7ZM9.5 9.75C9.5 9.55109 9.42098 9.36032 9.28033 9.21967C9.13968 9.07902 8.94891 9 8.75 9C8.55109 9 8.36032 9.07902 8.21967 9.21967C8.07902 9.36032 8 9.55109 8 9.75V18.25C8 18.4489 8.07902 18.6397 8.21967 18.7803C8.36032 18.921 8.55109 19 8.75 19C8.94891 19 9.13968 18.921 9.28033 18.7803C9.42098 18.6397 9.5 18.4489 9.5 18.25V9.75ZM13.25 9C13.0511 9 12.8603 9.07902 12.7197 9.21967C12.579 9.36032 12.5 9.55109 12.5 9.75V18.25C12.5 18.4489 12.579 18.6397 12.7197 18.7803C12.8603 18.921 13.0511 19 13.25 19C13.4489 19 13.6397 18.921 13.7803 18.7803C13.921 18.6397 14 18.4489 14 18.25V9.75C14 9.55109 13.921 9.36032 13.7803 9.21967C13.6397 9.07902 13.4489 9 13.25 9Z" fill="white"/> +<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> +<path d="M9.5 4H14.5C14.5 3.33696 14.2366 2.70107 13.7678 2.23223C13.2989 1.76339 12.663 1.5 12 1.5C11.337 1.5 10.7011 1.76339 10.2322 2.23223C9.76339 2.70107 9.5 3.33696 9.5 4ZM8 4C8 2.93913 8.42143 1.92172 9.17157 1.17157C9.92172 0.421427 10.9391 0 12 0C13.0609 0 14.0783 0.421427 14.8284 1.17157C15.5786 1.92172 16 2.93913 16 4H22.25C22.4489 4 22.6397 4.07902 22.7803 4.21967C22.921 4.36032 23 4.55109 23 4.75C23 4.94891 22.921 5.13968 22.7803 5.28033C22.6397 5.42098 22.4489 5.5 22.25 5.5H20.94L19.723 20.103C19.6345 21.1653 19.1499 22.1556 18.3655 22.8774C17.5811 23.5992 16.554 23.9999 15.488 24H8.512C7.44599 23.9999 6.41894 23.5992 5.6345 22.8774C4.85007 22.1556 4.36554 21.1653 4.277 20.103L3.06 5.5H1.75C1.55109 5.5 1.36032 5.42098 1.21967 5.28033C1.07902 5.13968 1 4.94891 1 4.75C1 4.55109 1.07902 4.36032 1.21967 4.21967C1.36032 4.07902 1.55109 4 1.75 4H8ZM10.5 9.75C10.5 9.55109 10.421 9.36032 10.2803 9.21967C10.1397 9.07902 9.94891 9 9.75 9C9.55109 9 9.36032 9.07902 9.21967 9.21967C9.07902 9.36032 9 9.55109 9 9.75V18.25C9 18.4489 9.07902 18.6397 9.21967 18.7803C9.36032 18.921 9.55109 19 9.75 19C9.94891 19 10.1397 18.921 10.2803 18.7803C10.421 18.6397 10.5 18.4489 10.5 18.25V9.75ZM14.25 9C14.0511 9 13.8603 9.07902 13.7197 9.21967C13.579 9.36032 13.5 9.55109 13.5 9.75V18.25C13.5 18.4489 13.579 18.6397 13.7197 18.7803C13.8603 18.921 14.0511 19 14.25 19C14.4489 19 14.6397 18.921 14.7803 18.7803C14.921 18.6397 15 18.4489 15 18.25V9.75C15 9.55109 14.921 9.36032 14.7803 9.21967C14.6397 9.07902 14.4489 9 14.25 9Z"/> </svg> diff --git a/HDesign/src/components/BillItem/BillItem.stories.tsx b/HDesign/src/components/BillItem/BillItem.stories.tsx deleted file mode 100644 index efe1fbb83..000000000 --- a/HDesign/src/components/BillItem/BillItem.stories.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import BillItem from '@components/BillItem/BillItem'; - -const meta = { - title: 'Components/BillItem', - component: BillItem, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - argTypes: { - name: { - description: '', - control: {type: 'text'}, - }, - price: { - description: '', - control: {type: 'number'}, - }, - }, - args: { - name: '뽕쟁이족발', - price: 198000, - }, -} satisfies Meta<typeof BillItem>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/BillItem/BillItem.style.ts b/HDesign/src/components/BillItem/BillItem.style.ts deleted file mode 100644 index 3e3f3398a..000000000 --- a/HDesign/src/components/BillItem/BillItem.style.ts +++ /dev/null @@ -1,8 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const textStyle = (theme: Theme) => - css({ - color: theme.colors.black, - }); diff --git a/HDesign/src/components/BillItem/BillItem.tsx b/HDesign/src/components/BillItem/BillItem.tsx deleted file mode 100644 index f73c5d32d..000000000 --- a/HDesign/src/components/BillItem/BillItem.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import React from 'react'; - -import Text from '@components/Text/Text'; - -import {useTheme} from '@theme/HDesignProvider'; - -import DragHandleItem from '../DragHandleItem/DragHandleItem'; -import Flex from '../Flex/Flex'; - -import {BillItemProps} from './BillItem.type'; -import {textStyle} from './BillItem.style'; - -export const BillItem: React.FC<BillItemProps> = ({ - name = '', - price = 0, - hasDragHandle = false, - ...htmlProps -}: BillItemProps) => { - const {theme} = useTheme(); - return ( - <DragHandleItem {...htmlProps} hasDragHandle={hasDragHandle} backgroundColor="lightGrayContainer"> - <Flex justifyContent="spaceBetween" width="100%"> - <Text css={textStyle(theme)} size="bodyBold"> - {name} - </Text> - <Text css={textStyle(theme)} size="body"> - {price.toLocaleString('ko-kr')}원 - </Text> - </Flex> - </DragHandleItem> - ); -}; -export default BillItem; diff --git a/HDesign/src/components/BillItem/BillItem.type.ts b/HDesign/src/components/BillItem/BillItem.type.ts deleted file mode 100644 index 4d6487ac9..000000000 --- a/HDesign/src/components/BillItem/BillItem.type.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface BillItemStyleProps {} - -export interface BillItemCustomProps { - name?: string; - price?: number; - hasDragHandle?: boolean; -} - -export type BillItemOptionProps = BillItemStyleProps & BillItemCustomProps; - -export type BillItemProps = React.ComponentProps<'div'> & BillItemOptionProps; diff --git a/HDesign/src/components/BottomSheet/BottomSheet.tsx b/HDesign/src/components/BottomSheet/BottomSheet.tsx index f920a0fdb..a1d3590c2 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.tsx +++ b/HDesign/src/components/BottomSheet/BottomSheet.tsx @@ -19,16 +19,16 @@ import { const BottomSheet: React.FC<BottomSheetProps> = ({ isOpened = false, children, - onChangeClose, - onChangeOpen, + onClose, + onOpen, ...props }: BottomSheetProps) => { const {theme} = useTheme(); const {opened, visible, handleClose, handleDragStart, handleDrag, handleDragEnd, isDragging, translateY} = useBottomSheet({ isOpened, - onChangeClose, - onChangeOpen, + onClose, + onOpen, }); // TODO: (@todari) : children 길이 길 때 overflow button에 안가리는 영역 처리 diff --git a/HDesign/src/components/BottomSheet/BottomSheet.type.ts b/HDesign/src/components/BottomSheet/BottomSheet.type.ts index 8b350aef1..0cc05841c 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.type.ts +++ b/HDesign/src/components/BottomSheet/BottomSheet.type.ts @@ -1,11 +1,7 @@ import {ComponentPropsWithoutRef} from 'react'; -import {ButtonVariants} from '@components/Button/Button.type'; - import {Theme} from '@theme/theme.type'; -import {FixedButtonProps} from '../FixedButton/FixedButton.type'; - export interface BottomSheetStyleProps { theme?: Theme; } diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx index 773c181a2..534bbacf9 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx @@ -13,14 +13,24 @@ const meta = { control: {type: 'select'}, options: ['white', 'gray', 'darkGray', 'black', 'primary', 'onPrimary', 'secondary', 'onSecondary'], }, - hasDragHandle: { + hasDragHandler: { description: '드래그할 수 있는 핸들러(불주사 자국)를 켜고 끌 수 있습니다.', control: {type: 'boolean'}, }, + prefix: { + description: '', + control: {type: 'text'}, + }, + suffix: { + description: '', + control: {type: 'text'}, + }, }, args: { backgroundColor: 'white', - children: '이건 끌 수 있는 아이템을 위한 것', + hasDragHandler: true, + prefix: '뽕쟁이족발', + suffix: '398,000 원', }, } satisfies Meta<typeof DragHandleItem>; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts index 22a1e195a..117ae93c2 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts @@ -13,8 +13,13 @@ export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgr backgroundColor: theme.colors[backgroundColor], }); -export const prefixStyle = css({ +export const dragHandlerStyle = css({ display: 'flex', gap: '0.25rem', width: '100%', }); + +export const textStyle = (theme: Theme) => + css({ + color: theme.colors.black, + }); diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx index a58c6d663..1a2df5471 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx @@ -1,39 +1,45 @@ /** @jsxImportSource @emotion/react */ import React from 'react'; -import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; +import Icon from '@components/Icon/Icon'; +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; import {useTheme} from '@theme/HDesignProvider'; -import {COLORS, ColorKeys} from '@token/colors'; - import IconButton from '../IconButton/IconButton'; -import {dragHandleItemStyle, prefixStyle} from './DragHandleItem.style'; - -interface DragHandleItemCustomProps { - hasDragHandle?: boolean; - backgroundColor?: ColorKeys; -} - -export type DragHandleItemProps = React.ComponentProps<'div'> & DragHandleItemCustomProps; +import {dragHandleItemStyle, dragHandlerStyle, textStyle} from './DragHandleItem.style'; +import {DragHandleItemProps} from './DragHandleItem.type'; -export function DragHandleItem({ - hasDragHandle = false, +export const DragHandleItem = ({ + hasDragHandler = false, backgroundColor = 'white', - children, + prefix, + suffix, ...htmlProps -}: StrictPropsWithChildren<DragHandleItemProps>) { +}: DragHandleItemProps) => { const {theme} = useTheme(); // TODO: (@toari) : 사람 수 많을 때 UX writing 처리 return ( - <div css={dragHandleItemStyle(theme, hasDragHandle, backgroundColor)} {...htmlProps}> - <div css={prefixStyle}> - {hasDragHandle && <IconButton iconType="buljusa" />} - {children} + <div css={dragHandleItemStyle(theme, hasDragHandler, backgroundColor)} {...htmlProps}> + <div css={dragHandlerStyle}> + {hasDragHandler && ( + <IconButton variants="none"> + <Icon iconType="buljusa" /> + </IconButton> + )} + <Flex justifyContent="spaceBetween" width="100%"> + <Text css={textStyle(theme)} size="bodyBold"> + {prefix} + </Text> + <Text css={textStyle(theme)} size="body"> + {suffix} + </Text> + </Flex> </div> </div> ); -} +}; export default DragHandleItem; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts new file mode 100644 index 000000000..29b8ebfd4 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts @@ -0,0 +1,18 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export interface DragHandleItemStyleProps { + theme?: Theme; + backgroundColor?: ColorKeys; +} + +export interface DragHandleItemCustomProps { + hasDragHandler?: boolean; + prefix?: string; + suffix?: string; +} + +export type DragHandleItemOptionProps = DragHandleItemStyleProps & DragHandleItemCustomProps; + +export type DragHandleItemProps = React.ComponentProps<'div'> & DragHandleItemOptionProps; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx new file mode 100644 index 000000000..69d7e3b75 --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx @@ -0,0 +1,86 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; + +const meta = { + title: 'Components/DragHandleItemContainer', + component: DragHandleItemContainer, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + topLeftText: { + description: '', + control: {type: 'text'}, + }, + topRightText: { + description: '', + control: {type: 'text'}, + }, + bottomLeftText: { + description: '', + control: {type: 'text'}, + }, + bottomRightText: { + description: '', + control: {type: 'text'}, + }, + backgroundColor: { + description: '', + control: { + type: 'select', + options: [ + 'white', + 'black', + 'primary', + 'onPrimary', + 'secondary', + 'onSecondary', + 'tertiary', + 'onTertiary', + 'gray', + 'darkGray', + 'grayContainer', + 'lightGrayContainer', + 'error', + 'errorContainer', + 'onErrorContainer', + 'warn', + 'complete', + ], + }, + }, + }, + args: { + topLeftText: '으아니차', + topRightText: '8명', + bottomLeftText: '총액', + bottomRightText: '214,000 원', + backgroundColor: 'white', + children: ( + <> + <DragHandleItem + hasDragHandler={true} + prefix="뽕쟁이족발" + suffix="198,000원" + backgroundColor="lightGrayContainer" + /> + <DragHandleItem + hasDragHandler={true} + prefix="인생네컷" + suffix="16,000원" + backgroundColor="lightGrayContainer" + /> + </> + ), + }, +} satisfies Meta<typeof DragHandleItemContainer>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts new file mode 100644 index 000000000..d1a74247f --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts @@ -0,0 +1,37 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export const containerStyle = (theme: Theme, backgroundColor: ColorKeys) => + css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + padding: '0.5rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors[backgroundColor], + }); + +export const topLeftStyle = (theme: Theme) => + css({ + color: theme.colors.gray, + }); + +//TODO: (@todari) : 추후 클릭 기능을 넣었을 때 underline +export const topRightStyle = (theme: Theme) => + css({ + color: theme.colors.gray, + // textDecoration: 'underline', + }); + +export const bottomLeftTextStyle = (theme: Theme) => + css({ + color: theme.colors.gray, + }); + +export const bottomRightTextStyle = (theme: Theme) => + css({ + color: theme.colors.gray, + }); diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx new file mode 100644 index 000000000..b255f3391 --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx @@ -0,0 +1,49 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import { + bottomLeftTextStyle, + bottomRightTextStyle, + containerStyle, + topLeftStyle, + topRightStyle, +} from './DragHandleItemContainer.style'; +import {DragHandleItemContainerProps} from './DragHandleItemContainer.type'; + +export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ({ + topLeftText, + bottomLeftText, + topRightText, + bottomRightText, + backgroundColor = 'white', + children, + ...htmlProps +}: DragHandleItemContainerProps) => { + const {theme} = useTheme(); + + return ( + <div css={containerStyle(theme, backgroundColor)} {...htmlProps}> + <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> + <Text css={topLeftStyle(theme)} size="captionBold"> + {topLeftText} + </Text> + <Text css={topRightStyle(theme)} size="caption"> + {topRightText} + </Text> + </Flex> + {children} + <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> + <Text css={bottomLeftTextStyle(theme)} size="captionBold"> + {bottomLeftText} + </Text> + <Text css={bottomRightTextStyle(theme)} size="caption"> + {bottomRightText} + </Text> + </Flex> + </div> + ); +}; +export default DragHandleItemContainer; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts new file mode 100644 index 000000000..c605e6e0c --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts @@ -0,0 +1,16 @@ +import {ColorKeys} from '@token/colors'; + +export interface DragHandleItemContainerStyleProps { + backgroundColor?: ColorKeys; +} + +export interface DragHandleItemContainerCustomProps { + topLeftText?: string; + bottomLeftText?: string; + topRightText?: string; + bottomRightText?: string; +} + +export type DragHandleItemContainerOptionProps = DragHandleItemContainerStyleProps & DragHandleItemContainerCustomProps; + +export type DragHandleItemContainerProps = React.ComponentProps<'div'> & DragHandleItemContainerOptionProps; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx index e637c7b1b..3cc5e8354 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.tsx +++ b/HDesign/src/components/ExpenseList/ExpenseList.tsx @@ -1,8 +1,7 @@ /** @jsxImportSource @emotion/react */ import Text from '@components/Text/Text'; - -import {Arrow} from '@assets/index'; +import Icon from '@components/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; @@ -10,6 +9,7 @@ import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle, TextStyle} from './ExpenseList.style'; // TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 +// TODO: (@todari) : 추후 클릭 시 상호작용이 생기면 iconButton으로 변경할 수 있음 function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { const {theme} = useTheme(); return ( @@ -19,7 +19,7 @@ function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { </Text> <div css={expenseItemLeftStyle}> <Text css={TextStyle(theme)}>{price.toLocaleString('ko-kr')}원</Text> - <Arrow /> + <Icon iconType="rightChevron" /> </div> </button> ); diff --git a/HDesign/src/components/FixedButton/FixedButton.tsx b/HDesign/src/components/FixedButton/FixedButton.tsx index 275059172..bb0e0d98f 100644 --- a/HDesign/src/components/FixedButton/FixedButton.tsx +++ b/HDesign/src/components/FixedButton/FixedButton.tsx @@ -8,6 +8,8 @@ import { buttonContainerStyle, } from '@components/FixedButton/FixedButton.style'; import {FixedButtonProps} from '@components/FixedButton/FixedButton.type'; +import IconButton from '@components/IconButton/IconButton'; +import Icon from '@components/Icon/Icon'; import Trash from '@assets/trash.svg'; @@ -22,9 +24,9 @@ export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElem <div css={fixedButtonContainerStyle(theme)}> <div css={buttonContainerStyle}> {onDeleteClick && ( - <button css={deleteButtonStyle(theme)} onClick={onDeleteClick}> - <Trash /> - </button> + <IconButton size="large" variants="destructive" onClick={onDeleteClick}> + <Icon iconType="trash" /> + </IconButton> )} <button css={fixedButtonStyle({variants, theme})} ref={ref} {...htmlProps} /> </div> diff --git a/HDesign/src/components/Icon/Icon.stories.tsx b/HDesign/src/components/Icon/Icon.stories.tsx new file mode 100644 index 000000000..3d2ef4aae --- /dev/null +++ b/HDesign/src/components/Icon/Icon.stories.tsx @@ -0,0 +1,28 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Icon from '@components/Icon/Icon'; + +const meta = { + title: 'Components/Icon', + component: Icon, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + iconType: { + description: '', + control: {type: 'select'}, + options: ['inputDelete', 'buljusa', 'rightChevron', 'search', 'confirm', 'error', 'trash'], + }, + }, + args: { + iconType: 'rightChevron', + }, +} satisfies Meta<typeof Icon>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Icon/Icon.style.ts b/HDesign/src/components/Icon/Icon.style.ts new file mode 100644 index 000000000..32b5c08ee --- /dev/null +++ b/HDesign/src/components/Icon/Icon.style.ts @@ -0,0 +1,38 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +import {IconColor, IconType} from './Icon.type'; + +const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { + inputDelete: 'gray', + buljusa: 'gray', + rightChevron: 'gray', + search: 'gray', + confirm: 'complete', + error: 'warn', + trash: 'white', +}; + +export const iconStyle = (iconType: IconType, theme: Theme, iconColor?: IconColor) => { + return [ + css({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + }), + getIconColor(iconType, theme, iconColor), + ]; +}; + +const getIconColor = (iconType: IconType, theme: Theme, iconColor?: IconColor) => { + if (iconColor) { + return css({ + color: theme.colors[iconColor as ColorKeys], + }); + } else { + return css({color: theme.colors[ICON_DEFAULT_COLOR[iconType]]}); + } +}; diff --git a/HDesign/src/components/Icon/Icon.tsx b/HDesign/src/components/Icon/Icon.tsx new file mode 100644 index 000000000..d1d9e6e04 --- /dev/null +++ b/HDesign/src/components/Icon/Icon.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ + +import {IconProps} from '@components/Icon/Icon.type'; +import {InputDelete, Buljusa, RightChevron, Search, Trash, Confirm, Error} from '@assets'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {iconStyle} from './Icon.style'; + +const ICON = { + inputDelete: <InputDelete />, + buljusa: <Buljusa />, + rightChevron: <RightChevron />, + search: <Search />, + error: <Error />, + confirm: <Confirm />, + trash: <Trash />, +}; + +export const Icon: React.FC<IconProps> = ({iconColor, iconType, ...htmlProps}: IconProps) => { + const {theme} = useTheme(); + return ( + <div css={iconStyle(iconType, theme, iconColor)} {...htmlProps}> + {ICON[iconType]} + </div> + ); +}; + +export default Icon; diff --git a/HDesign/src/components/Icon/Icon.type.ts b/HDesign/src/components/Icon/Icon.type.ts new file mode 100644 index 000000000..e73bb1771 --- /dev/null +++ b/HDesign/src/components/Icon/Icon.type.ts @@ -0,0 +1,16 @@ +import {ColorKeys} from '@token/colors'; + +export type IconType = 'inputDelete' | 'buljusa' | 'rightChevron' | 'search' | 'error' | 'confirm' | 'trash'; +export type IconColor = ColorKeys; + +export interface IconStyleProps { + iconColor?: IconColor; +} + +export interface IconCustomProps { + iconType: IconType; +} + +export type IconOptionProps = IconStyleProps & IconCustomProps; + +export type IconProps = React.ComponentProps<'div'> & IconOptionProps; diff --git a/HDesign/src/components/IconButton/IconButton.stories.tsx b/HDesign/src/components/IconButton/IconButton.stories.tsx index 23b9f7bc5..e687ef854 100644 --- a/HDesign/src/components/IconButton/IconButton.stories.tsx +++ b/HDesign/src/components/IconButton/IconButton.stories.tsx @@ -1,6 +1,8 @@ +/** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; import IconButton from '@components/IconButton/IconButton'; +import Icon from '@components/Icon/Icon'; const meta = { title: 'Components/IconButton', @@ -10,14 +12,33 @@ const meta = { layout: 'centered', }, argTypes: { - iconType: { + size: { description: '', control: {type: 'select'}, - options: ['plus', 'inputDelete', 'buljusa'], + options: ['large', 'medium', 'small'], + }, + variants: { + description: '', + control: {type: 'select'}, + options: ['none', 'primary', 'secondary', 'tertiary', 'destructive'], + }, + children: { + description: '', + control: {type: 'select'}, + options: [ + <Icon iconType="inputDelete" />, + <Icon iconType="buljusa" />, + <Icon iconType="rightChevron" />, + <Icon iconType="search" />, + <Icon iconType="error" />, + <Icon iconType="trash" />, + ], }, }, args: { - iconType: 'plus', + size: 'medium', + variants: 'destructive', + children: <Icon iconType="trash" />, }, } satisfies Meta<typeof IconButton>; diff --git a/HDesign/src/components/IconButton/IconButton.style.ts b/HDesign/src/components/IconButton/IconButton.style.ts new file mode 100644 index 000000000..7e46a188c --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.style.ts @@ -0,0 +1,101 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {setDarker, setLighter} from '@utils/colors'; + +import {IconButtonSize, IconButtonStyleProps, IconButtonVariants} from './IconButton.type'; + +export const iconButtonStyle = (props: Required<IconButtonStyleProps>) => { + if (props.variants === 'none') { + return 'none'; + } + return [ + getIconButtonBase(props.theme), + getIconButtonSize(props.size), + getIconButtonVariants(props.variants, props.theme), + ]; +}; + +const getHoverAndActiveBackground = (color: string) => + css({ + ':not(:disabled)': { + '&:hover': { + backgroundColor: setLighter(color, 0.15), + }, + '&:active': { + backgroundColor: setDarker(color, 0.15), + }, + }, + }); + +const getIconButtonBase = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + whiteSpace: 'nowrap', + + '&:disabled': { + backgroundColor: theme.colors.tertiary, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + +const getIconButtonSize = (size: IconButtonSize) => { + const style = { + small: css({ + padding: '0.5rem', + borderRadius: '0.75rem', + }), + medium: css({ + padding: '0.75rem', + borderRadius: '1rem', + }), + large: css({ + padding: '1rem', + borderRadius: '1.25rem', + }), + }; + + return style[size]; +}; + +const getIconButtonVariants = (variants: IconButtonVariants, theme: Theme) => { + const style = { + none: [css({})], + primary: [ + css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.primary), + ], + secondary: [ + css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + getHoverAndActiveBackground(theme.colors.secondary), + ], + tertiary: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + destructive: [ + css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.error), + ], + }; + + return style[variants]; +}; diff --git a/HDesign/src/components/IconButton/IconButton.tsx b/HDesign/src/components/IconButton/IconButton.tsx index 076274ac1..f340e055f 100644 --- a/HDesign/src/components/IconButton/IconButton.tsx +++ b/HDesign/src/components/IconButton/IconButton.tsx @@ -2,25 +2,19 @@ import {forwardRef} from 'react'; import {IconButtonProps} from '@components/IconButton/IconButton.type'; -import {InputDelete, Plus, Buljusa, RightChevron, Arrow, Trash, Error} from '@assets'; -const ICON = { - inputDelete: <InputDelete />, - plus: <Plus />, - buljusa: <Buljusa />, - rightChevron: <RightChevron />, - arrow: <Arrow />, - error: <Error />, - trash: <Trash />, -}; +import {useTheme} from '@theme/HDesignProvider'; + +import {iconButtonStyle} from './IconButton.style'; export const IconButton: React.FC<IconButtonProps> = forwardRef<HTMLButtonElement, IconButtonProps>(function Button( - {iconType, ...htmlProps}: IconButtonProps, + {size = 'large', variants, children, ...htmlProps}: IconButtonProps, ref, ) { + const {theme} = useTheme(); return ( - <button ref={ref} {...htmlProps}> - {ICON[iconType]} + <button ref={ref} css={iconButtonStyle({theme, size, variants})} {...htmlProps}> + {children} </button> ); }); diff --git a/HDesign/src/components/IconButton/IconButton.type.ts b/HDesign/src/components/IconButton/IconButton.type.ts index 06141aaaa..5c277e578 100644 --- a/HDesign/src/components/IconButton/IconButton.type.ts +++ b/HDesign/src/components/IconButton/IconButton.type.ts @@ -1,11 +1,16 @@ -type IconButtonType = 'inputDelete' | 'plus' | 'buljusa' | 'rightChevron' | 'arrow' | 'error' | 'trash'; +import {Theme} from '@theme/theme.type'; -export interface IconButtonStyleProps {} +export type IconButtonSize = 'large' | 'medium' | 'small'; +export type IconButtonVariants = 'none' | 'primary' | 'secondary' | 'tertiary' | 'destructive'; -export interface IconButtonCustomProps { - iconType: IconButtonType; +export interface IconButtonStyleProps { + size?: IconButtonSize; + variants: IconButtonVariants; + theme?: Theme; } +export interface IconButtonCustomProps {} + export type IconButtonOptionProps = IconButtonStyleProps & IconButtonCustomProps; export type IconButtonProps = React.ComponentProps<'button'> & IconButtonOptionProps; diff --git a/HDesign/src/components/InOutItem/InOutItem.stories.tsx b/HDesign/src/components/InOutItem/InOutItem.stories.tsx deleted file mode 100644 index 1805fe0db..000000000 --- a/HDesign/src/components/InOutItem/InOutItem.stories.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import InOutItem from '@components/InOutItem/InOutItem'; - -const meta = { - title: 'Components/InOutItem', - component: InOutItem, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - argTypes: { - names: { - description: '', - control: {type: 'object'}, - }, - inOutType: { - description: '', - control: {type: 'select', options: ['IN', 'OUT']}, - }, - }, - args: { - names: ['감자', '토다리'], - inOutType: 'OUT', - }, -} satisfies Meta<typeof InOutItem>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/InOutItem/InOutItem.style.ts b/HDesign/src/components/InOutItem/InOutItem.style.ts deleted file mode 100644 index 41cd9f97a..000000000 --- a/HDesign/src/components/InOutItem/InOutItem.style.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const inOutItemStyle = (theme: Theme) => - css({ - display: 'flex', - justifyContent: 'space-between', - padding: '0.5rem 0.5rem 0.5rem 0.25rem', - borderRadius: '0.5rem', - backgroundColor: theme.colors.white, - }); - -export const prefixStyle = css({ - display: 'flex', - gap: '0.25rem', -}); - -export const textStyle = (theme: Theme, hasDragHandle: boolean) => - css({ - paddingLeft: hasDragHandle ? '0' : '0.5rem', - - color: theme.colors.black, - }); diff --git a/HDesign/src/components/InOutItem/InOutItem.tsx b/HDesign/src/components/InOutItem/InOutItem.tsx deleted file mode 100644 index 2f506f5f3..000000000 --- a/HDesign/src/components/InOutItem/InOutItem.tsx +++ /dev/null @@ -1,35 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import React from 'react'; - -import Text from '@components/Text/Text'; - -import {useTheme} from '@theme/HDesignProvider'; - -import DragHandleItem from '../DragHandleItem/DragHandleItem'; - -import {InOutItemProps, InOutType} from './InOutItem.type'; -import {textStyle} from './InOutItem.style'; - -const IN_OUT_TEXT: Record<InOutType, string> = { - IN: '들어옴', - OUT: '나감', -}; - -export const InOutItem: React.FC<InOutItemProps> = ({ - names = [], - inOutType = 'OUT', - hasDragHandle = false, - ...htmlProps -}: InOutItemProps) => { - const {theme} = useTheme(); - - // TODO: (@toari) : 사람 수 많을 때 UX writing 처리 - return ( - <DragHandleItem {...htmlProps} hasDragHandle={hasDragHandle}> - <Text css={textStyle(theme, hasDragHandle)} size="bodyBold"> - {names.join(', ')} {IN_OUT_TEXT[inOutType]} - </Text> - </DragHandleItem> - ); -}; -export default InOutItem; diff --git a/HDesign/src/components/InOutItem/InOutItem.type.ts b/HDesign/src/components/InOutItem/InOutItem.type.ts deleted file mode 100644 index 2872e5d55..000000000 --- a/HDesign/src/components/InOutItem/InOutItem.type.ts +++ /dev/null @@ -1,13 +0,0 @@ -export type InOutType = 'IN' | 'OUT'; - -export interface InOutItemStyleProps {} - -export interface InOutItemCustomProps { - names?: string[]; - inOutType?: InOutType; - hasDragHandle?: boolean; -} - -export type InOutItemOptionProps = InOutItemStyleProps & InOutItemCustomProps; - -export type InOutItemProps = React.ComponentProps<'div'> & InOutItemOptionProps; diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx index 410c0a618..a1b495afd 100644 --- a/HDesign/src/components/Input/Input.tsx +++ b/HDesign/src/components/Input/Input.tsx @@ -5,6 +5,7 @@ import IconButton from '@components/IconButton/IconButton'; import {InputProps} from '@components/Input/Input.type'; import {inputBoxStyle, inputStyle} from '@components/Input/Input.style'; import {useInput} from '@components/Input/useInput'; +import Icon from '@components/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; @@ -38,7 +39,11 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro autoFocus={autoFocus} {...htmlProps} /> - {value && hasFocus && <IconButton tabIndex={-1} iconType="inputDelete" onMouseDown={handleClickDelete} />} + {value && hasFocus && ( + <IconButton tabIndex={-1} variants="none" onMouseDown={handleClickDelete}> + <Icon iconType="inputDelete" /> + </IconButton> + )} </div> ); }); diff --git a/HDesign/src/components/ListButton/ListButton.tsx b/HDesign/src/components/ListButton/ListButton.tsx index 9a161f12b..c90bbd122 100644 --- a/HDesign/src/components/ListButton/ListButton.tsx +++ b/HDesign/src/components/ListButton/ListButton.tsx @@ -4,6 +4,7 @@ import React, {forwardRef} from 'react'; import Text from '@components/Text/Text'; import IconButton from '@components/IconButton/IconButton'; import Flex from '@components/Flex/Flex'; +import Icon from '@components/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; @@ -24,7 +25,9 @@ export const ListButton: React.FC<ListButtonProps> = forwardRef<HTMLButtonElemen <Text size="caption" css={textStyle(theme)}> {suffix} </Text> - <IconButton iconType="rightChevron" /> + <IconButton variants="none"> + <Icon iconType="rightChevron" /> + </IconButton> </Flex> </button> ); diff --git a/HDesign/src/components/StepItem/StepItem.stories.tsx b/HDesign/src/components/StepItem/StepItem.stories.tsx deleted file mode 100644 index 3a81c38f6..000000000 --- a/HDesign/src/components/StepItem/StepItem.stories.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import StepItem from '@components/StepItem/StepItem'; - -const meta = { - title: 'Components/StepItem', - component: StepItem, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - argTypes: { - name: { - description: '', - control: {type: 'text'}, - }, - personCount: { - description: '', - control: {type: 'number'}, - }, - bills: { - description: '', - control: {type: 'object'}, - }, - }, - args: { - name: '으랏차차', - personCount: 8, - bills: [ - { - name: '뽕나무쟁이', - price: 150000, - }, - { - name: '인생네컷', - price: 12000, - }, - ], - }, -} satisfies Meta<typeof StepItem>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = {}; diff --git a/HDesign/src/components/StepItem/StepItem.style.ts b/HDesign/src/components/StepItem/StepItem.style.ts deleted file mode 100644 index c4752b560..000000000 --- a/HDesign/src/components/StepItem/StepItem.style.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const stepItemStyle = (theme: Theme) => - css({ - display: 'flex', - flexDirection: 'column', - gap: '0.5rem', - padding: '0.5rem', - borderRadius: '0.75rem', - backgroundColor: theme.colors.white, - }); - -export const nameStyle = (theme: Theme) => - css({ - color: theme.colors.black, - }); - -export const personCountStyle = (theme: Theme) => - css({ - color: theme.colors.gray, - textDecoration: 'underline', - }); - -export const totalTitleStyle = (theme: Theme) => - css({ - color: theme.colors.black, - }); - -export const totalAmountStyle = (theme: Theme) => - css({ - color: theme.colors.gray, - }); diff --git a/HDesign/src/components/StepItem/StepItem.tsx b/HDesign/src/components/StepItem/StepItem.tsx deleted file mode 100644 index 3d7eaf69d..000000000 --- a/HDesign/src/components/StepItem/StepItem.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {useTheme} from '@theme/HDesignProvider'; - -import Text from '../Text/Text'; -import BillItem from '../BillItem/BillItem'; -import {BillItemCustomProps} from '../BillItem/BillItem.type'; -import Flex from '../Flex/Flex'; - -import {nameStyle, personCountStyle, stepItemStyle, totalAmountStyle, totalTitleStyle} from './StepItem.style'; -import {StepItemCustomProps} from './StepItem.type'; - -export const StepItem: React.FC<StepItemCustomProps> = ({ - name = '', - personCount = 0, - bills, - ...htmlProps -}: StepItemCustomProps) => { - const {theme} = useTheme(); - return ( - <div css={stepItemStyle(theme)} {...htmlProps}> - <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> - <Text css={nameStyle(theme)} size="captionBold"> - {name} - </Text> - <Text css={personCountStyle(theme)} size="caption"> - {personCount}명 - </Text> - </Flex> - {bills.map((props: BillItemCustomProps) => ( - <BillItem {...props} /> - ))} - <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> - <Text css={totalTitleStyle(theme)} size="captionBold"> - 총액 - </Text> - <Text css={totalAmountStyle(theme)} size="caption"> - {bills.reduce((acc, prev) => acc + (prev.price ?? 0), 0).toLocaleString('ko-kr')}원 - </Text> - </Flex> - </div> - ); -}; -export default StepItem; diff --git a/HDesign/src/components/StepItem/StepItem.type.ts b/HDesign/src/components/StepItem/StepItem.type.ts deleted file mode 100644 index 516b7b675..000000000 --- a/HDesign/src/components/StepItem/StepItem.type.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {BillItemCustomProps} from '../BillItem/BillItem.type'; - -export interface StepItemStyleProps {} - -export interface StepItemCustomProps { - name: string; - personCount: number; - bills: BillItemCustomProps[]; -} - -export type StepItemOptionProps = StepItemStyleProps & StepItemCustomProps; - -export type StepItemProps = React.ComponentProps<'div'> & StepItemOptionProps; diff --git a/HDesign/src/components/Toast/Toast.tsx b/HDesign/src/components/Toast/Toast.tsx index 47d60c8dc..972ce6220 100644 --- a/HDesign/src/components/Toast/Toast.tsx +++ b/HDesign/src/components/Toast/Toast.tsx @@ -3,9 +3,7 @@ import {createPortal} from 'react-dom'; import Text from '@components/Text/Text'; import Flex from '@components/Flex/Flex'; - -import ErrorIcon from '@assets/error.svg'; -import ConfirmIcon from '@assets/confirm.svg'; +import Icon from '@components/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; @@ -17,10 +15,10 @@ import {ToastProps, ToastType} from './Toast.type'; const renderIcon = (type: ToastType) => { switch (type) { case 'error': - return <ErrorIcon />; + return <Icon iconType="error" />; case 'confirm': - return <ConfirmIcon />; + return <Icon iconType="confirm" />; case 'none': return null; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index f63e55edf..e6498965e 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -1,23 +1,25 @@ -import BillItem from '@components/BillItem/BillItem'; import BottomSheet from '@components/BottomSheet/BottomSheet'; import Button from '@components/Button/Button'; import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; import ExpenseList from '@components/ExpenseList/ExpenseList'; import FixedButton from '@components/FixedButton/FixedButton'; import Flex from '@components/Flex/Flex'; +import Icon from '@components/Icon/Icon'; import IconButton from '@components/IconButton/IconButton'; -import InOutItem from '@components/InOutItem/InOutItem'; import Input from '@components/Input/Input'; import LabelInput from '@components/LabelInput/LabelInput'; +import ListButton from '@components/ListButton/ListButton'; import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; import Search from '@components/Search/Search'; -import StepItem from '@components/StepItem/StepItem'; import Switch from '@components/Switch/Switch'; +import Tab from '@components/Tabs/Tab'; import Tabs from '@components/Tabs/Tabs'; import Text from '@components/Text/Text'; import TextButton from '@components/TextButton/TextButton'; import Title from '@components/Title/Title'; import Toast from '@components/Toast/Toast'; +import Back from '@components/TopNav/Back'; import TopNav from '@components/TopNav/TopNav'; import {ToastProvider, useToast} from '@components/Toast/ToastProvider'; @@ -26,35 +28,32 @@ import {ContentLayout} from '@layouts/ContentLayout'; import {HDesignProvider} from '@theme/HDesignProvider'; -import Tab from './components/Tabs/Tab'; -import Back from './components/TopNav/Back'; - export { - Back, - BillItem, BottomSheet, Button, DragHandleItem, + DragHandleItemContainer, ExpenseList, FixedButton, Flex, + Icon, IconButton, - InOutItem, Input, LabelInput, + ListButton, LabelGroupInput, Search, - StepItem, Switch, Tab, Tabs, Text, TextButton, Title, + Toast, TopNav, + Back, MainLayout, ContentLayout, - Toast, ToastProvider, useToast, HDesignProvider, diff --git a/HDesign/src/token/colors.ts b/HDesign/src/token/colors.ts index d01c6883e..3dccdf2d3 100644 --- a/HDesign/src/token/colors.ts +++ b/HDesign/src/token/colors.ts @@ -36,6 +36,18 @@ const PRIMITIVE_COLORS = { 800: '#b9bb17', 900: '#9e9305', }, + green: { + 50: '#f4ffe8', + 100: '#e4ffc6', + 200: '#d1ff9f', + 300: '#bfff75', + 400: '#b0fd51', + 500: '#a4f932', + 600: '#9de728', + 700: '#90cf18', + 800: '#85b704', + 900: '#748f00', + }, gray: { 50: '#F9F8FD', 100: '#F1F0F5', @@ -68,7 +80,8 @@ export type ColorKeys = | 'error' | 'errorContainer' | 'onErrorContainer' - | 'warn'; + | 'warn' + | 'complete'; export type ColorTokens = Record<ColorKeys, Color>; // TODO: (@soha) 대괄호 사용에 대해 논의 @@ -92,4 +105,5 @@ export const COLORS: ColorTokens = { errorContainer: PRIMITIVE_COLORS.pink[50], onErrorContainer: PRIMITIVE_COLORS.pink[300], warn: PRIMITIVE_COLORS.yellow[400], + complete: PRIMITIVE_COLORS.green[300], }; From c8d8c172a71bf1b017735f4fd523cc95fba48abe Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:53:30 +0900 Subject: [PATCH 117/273] =?UTF-8?q?feat:=20=EC=82=AD=EC=A0=9C=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=EC=9D=84=20=EC=9C=84=ED=95=9C=20IconButton?= =?UTF-8?q?=20component=20=EC=88=98=EC=A0=95=20(#209)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 --- HDesign/package-lock.json | 2 +- HDesign/package.json | 2 +- HDesign/src/assets/confirm.svg | 2 +- HDesign/src/assets/error.svg | 2 +- HDesign/src/components/Icon/Icon.style.ts | 8 ++++---- HDesign/src/components/Icon/Icon.tsx | 2 +- HDesign/src/components/Icon/Icon.type.ts | 9 +++++++-- .../IconButton/IconButton.stories.tsx | 2 ++ .../components/IconButton/IconButton.style.ts | 19 ++++++++++--------- .../src/components/IconButton/IconButton.tsx | 2 +- .../components/IconButton/IconButton.type.ts | 5 ++++- 11 files changed, 33 insertions(+), 22 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 1dd57358e..739bbabe5 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -13821,4 +13821,4 @@ } } } -} +} \ No newline at end of file diff --git a/HDesign/package.json b/HDesign/package.json index dcbd20ea3..22232fb75 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -68,4 +68,4 @@ "npm": ">=10.7.0", "node": ">=20.15.1" } -} +} \ No newline at end of file diff --git a/HDesign/src/assets/confirm.svg b/HDesign/src/assets/confirm.svg index 820585a17..ef31a5152 100644 --- a/HDesign/src/assets/confirm.svg +++ b/HDesign/src/assets/confirm.svg @@ -1,6 +1,6 @@ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> <g clip-path="url(#clip0_1042_1615)"> -<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C11.3132 20 12.6136 19.7413 13.8268 19.2388C15.0401 18.7362 16.1425 17.9997 17.0711 17.0711C17.9997 16.1425 18.7362 15.0401 19.2388 13.8268C19.7413 12.6136 20 11.3132 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 -1.95685e-08 10 0C7.34784 3.95203e-08 4.8043 1.05357 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C4.8043 18.9464 7.34784 20 10 20ZM15.2978 7.37778C15.3953 7.26627 15.4696 7.13638 15.5162 6.99574C15.5628 6.85511 15.5808 6.70657 15.5692 6.55887C15.5575 6.41117 15.5165 6.26729 15.4484 6.1357C15.3804 6.0041 15.2866 5.88745 15.1728 5.7926C15.059 5.69775 14.9274 5.62663 14.7857 5.5834C14.644 5.54018 14.495 5.52574 14.3476 5.54092C14.2003 5.5561 14.0574 5.60061 13.9275 5.67181C13.7976 5.74302 13.6832 5.83949 13.5911 5.95556L9.59333 10.7522C9.20778 11.2144 8.99111 11.4711 8.81889 11.6278L8.81222 11.6344L8.80444 11.6289C8.61778 11.4878 8.37889 11.2522 7.95445 10.8267L6.34111 9.21445C6.13155 9.01205 5.85088 8.90005 5.55956 8.90259C5.26823 8.90512 4.98954 9.02197 4.78354 9.22798C4.57753 9.43399 4.46067 9.71267 4.45814 10.004C4.45561 10.2953 4.5676 10.576 4.77 10.7856L6.38222 12.3978L6.42778 12.4433C6.79111 12.8067 7.13889 13.1556 7.46445 13.4011C7.82778 13.6767 8.30444 13.9344 8.91444 13.9078C9.52556 13.88 9.97667 13.5789 10.3144 13.2722C10.6144 12.9978 10.9311 12.6189 11.2589 12.2244L11.3 12.1756L15.2978 7.37778Z" fill="#BFFF75"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C11.3132 20 12.6136 19.7413 13.8268 19.2388C15.0401 18.7362 16.1425 17.9997 17.0711 17.0711C17.9997 16.1425 18.7362 15.0401 19.2388 13.8268C19.7413 12.6136 20 11.3132 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 -1.95685e-08 10 0C7.34784 3.95203e-08 4.8043 1.05357 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C4.8043 18.9464 7.34784 20 10 20ZM15.2978 7.37778C15.3953 7.26627 15.4696 7.13638 15.5162 6.99574C15.5628 6.85511 15.5808 6.70657 15.5692 6.55887C15.5575 6.41117 15.5165 6.26729 15.4484 6.1357C15.3804 6.0041 15.2866 5.88745 15.1728 5.7926C15.059 5.69775 14.9274 5.62663 14.7857 5.5834C14.644 5.54018 14.495 5.52574 14.3476 5.54092C14.2003 5.5561 14.0574 5.60061 13.9275 5.67181C13.7976 5.74302 13.6832 5.83949 13.5911 5.95556L9.59333 10.7522C9.20778 11.2144 8.99111 11.4711 8.81889 11.6278L8.81222 11.6344L8.80444 11.6289C8.61778 11.4878 8.37889 11.2522 7.95445 10.8267L6.34111 9.21445C6.13155 9.01205 5.85088 8.90005 5.55956 8.90259C5.26823 8.90512 4.98954 9.02197 4.78354 9.22798C4.57753 9.43399 4.46067 9.71267 4.45814 10.004C4.45561 10.2953 4.5676 10.576 4.77 10.7856L6.38222 12.3978L6.42778 12.4433C6.79111 12.8067 7.13889 13.1556 7.46445 13.4011C7.82778 13.6767 8.30444 13.9344 8.91444 13.9078C9.52556 13.88 9.97667 13.5789 10.3144 13.2722C10.6144 12.9978 10.9311 12.6189 11.2589 12.2244L11.3 12.1756L15.2978 7.37778Z" fill="currentColor"/> </g> <defs> <clipPath id="clip0_1042_1615"> diff --git a/HDesign/src/assets/error.svg b/HDesign/src/assets/error.svg index c77a2f4a3..479cae34a 100644 --- a/HDesign/src/assets/error.svg +++ b/HDesign/src/assets/error.svg @@ -1,6 +1,6 @@ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> <g clip-path="url(#clip0_1042_1585)"> -<path d="M11 11H9V5H11M11 15H9V13H11M10 0C8.68678 0 7.38642 0.258658 6.17317 0.761205C4.95991 1.26375 3.85752 2.00035 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C3.85752 17.9997 4.95991 18.7362 6.17317 19.2388C7.38642 19.7413 8.68678 20 10 20C12.6522 20 15.1957 18.9464 17.0711 17.0711C18.9464 15.1957 20 12.6522 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 0 10 0Z" fill="#ECFF59"/> +<path d="M11 11H9V5H11M11 15H9V13H11M10 0C8.68678 0 7.38642 0.258658 6.17317 0.761205C4.95991 1.26375 3.85752 2.00035 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C3.85752 17.9997 4.95991 18.7362 6.17317 19.2388C7.38642 19.7413 8.68678 20 10 20C12.6522 20 15.1957 18.9464 17.0711 17.0711C18.9464 15.1957 20 12.6522 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 0 10 0Z" fill="currentColor"/> </g> <defs> <clipPath id="clip0_1042_1585"> diff --git a/HDesign/src/components/Icon/Icon.style.ts b/HDesign/src/components/Icon/Icon.style.ts index 32b5c08ee..b19601da6 100644 --- a/HDesign/src/components/Icon/Icon.style.ts +++ b/HDesign/src/components/Icon/Icon.style.ts @@ -4,7 +4,7 @@ import {Theme} from '@theme/theme.type'; import {ColorKeys} from '@token/colors'; -import {IconColor, IconType} from './Icon.type'; +import {IconColor, IconStylePropsWithTheme, IconType} from './Icon.type'; const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { inputDelete: 'gray', @@ -16,18 +16,18 @@ const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { trash: 'white', }; -export const iconStyle = (iconType: IconType, theme: Theme, iconColor?: IconColor) => { +export const iconStyle = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { return [ css({ display: 'flex', justifyContent: 'center', alignItems: 'center', }), - getIconColor(iconType, theme, iconColor), + getIconColor({iconType, theme, iconColor}), ]; }; -const getIconColor = (iconType: IconType, theme: Theme, iconColor?: IconColor) => { +const getIconColor = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { if (iconColor) { return css({ color: theme.colors[iconColor as ColorKeys], diff --git a/HDesign/src/components/Icon/Icon.tsx b/HDesign/src/components/Icon/Icon.tsx index d1d9e6e04..13d8e7835 100644 --- a/HDesign/src/components/Icon/Icon.tsx +++ b/HDesign/src/components/Icon/Icon.tsx @@ -20,7 +20,7 @@ const ICON = { export const Icon: React.FC<IconProps> = ({iconColor, iconType, ...htmlProps}: IconProps) => { const {theme} = useTheme(); return ( - <div css={iconStyle(iconType, theme, iconColor)} {...htmlProps}> + <div css={iconStyle({iconType, theme, iconColor})} {...htmlProps}> {ICON[iconType]} </div> ); diff --git a/HDesign/src/components/Icon/Icon.type.ts b/HDesign/src/components/Icon/Icon.type.ts index e73bb1771..57fc25cfb 100644 --- a/HDesign/src/components/Icon/Icon.type.ts +++ b/HDesign/src/components/Icon/Icon.type.ts @@ -1,3 +1,5 @@ +import {Theme} from '@theme/theme.type'; + import {ColorKeys} from '@token/colors'; export type IconType = 'inputDelete' | 'buljusa' | 'rightChevron' | 'search' | 'error' | 'confirm' | 'trash'; @@ -5,12 +7,15 @@ export type IconColor = ColorKeys; export interface IconStyleProps { iconColor?: IconColor; + iconType: IconType; } -export interface IconCustomProps { - iconType: IconType; +export interface IconStylePropsWithTheme extends IconStyleProps { + theme: Theme; } +export interface IconCustomProps {} + export type IconOptionProps = IconStyleProps & IconCustomProps; export type IconProps = React.ComponentProps<'div'> & IconOptionProps; diff --git a/HDesign/src/components/IconButton/IconButton.stories.tsx b/HDesign/src/components/IconButton/IconButton.stories.tsx index e687ef854..6cc2b5f3d 100644 --- a/HDesign/src/components/IconButton/IconButton.stories.tsx +++ b/HDesign/src/components/IconButton/IconButton.stories.tsx @@ -25,11 +25,13 @@ const meta = { children: { description: '', control: {type: 'select'}, + // TODO: (@todari) : Icon의 색상을 variants에 의해 자동으로 변경해 줄 수 있는 로직 추가 options: [ <Icon iconType="inputDelete" />, <Icon iconType="buljusa" />, <Icon iconType="rightChevron" />, <Icon iconType="search" />, + <Icon iconType="confirm" />, <Icon iconType="error" />, <Icon iconType="trash" />, ], diff --git a/HDesign/src/components/IconButton/IconButton.style.ts b/HDesign/src/components/IconButton/IconButton.style.ts index 7e46a188c..18ffc4533 100644 --- a/HDesign/src/components/IconButton/IconButton.style.ts +++ b/HDesign/src/components/IconButton/IconButton.style.ts @@ -5,17 +5,18 @@ import {Theme} from '@theme/theme.type'; import {setDarker, setLighter} from '@utils/colors'; -import {IconButtonSize, IconButtonStyleProps, IconButtonVariants} from './IconButton.type'; +import { + IconButtonSize, + IconButtonStyleProps, + IconButtonStylePropsWithTheme, + IconButtonVariants, +} from './IconButton.type'; -export const iconButtonStyle = (props: Required<IconButtonStyleProps>) => { - if (props.variants === 'none') { +export const iconButtonStyle = ({theme, size = 'large', variants}: IconButtonStylePropsWithTheme) => { + if (variants === 'none') { return 'none'; } - return [ - getIconButtonBase(props.theme), - getIconButtonSize(props.size), - getIconButtonVariants(props.variants, props.theme), - ]; + return [getIconButtonBase(theme), getIconButtonSize(size), getIconButtonVariants({variants, theme})]; }; const getHoverAndActiveBackground = (color: string) => @@ -64,7 +65,7 @@ const getIconButtonSize = (size: IconButtonSize) => { return style[size]; }; -const getIconButtonVariants = (variants: IconButtonVariants, theme: Theme) => { +const getIconButtonVariants = ({variants, theme}: IconButtonStylePropsWithTheme) => { const style = { none: [css({})], primary: [ diff --git a/HDesign/src/components/IconButton/IconButton.tsx b/HDesign/src/components/IconButton/IconButton.tsx index f340e055f..bc704db67 100644 --- a/HDesign/src/components/IconButton/IconButton.tsx +++ b/HDesign/src/components/IconButton/IconButton.tsx @@ -8,7 +8,7 @@ import {useTheme} from '@theme/HDesignProvider'; import {iconButtonStyle} from './IconButton.style'; export const IconButton: React.FC<IconButtonProps> = forwardRef<HTMLButtonElement, IconButtonProps>(function Button( - {size = 'large', variants, children, ...htmlProps}: IconButtonProps, + {size, variants, children, ...htmlProps}: IconButtonProps, ref, ) { const {theme} = useTheme(); diff --git a/HDesign/src/components/IconButton/IconButton.type.ts b/HDesign/src/components/IconButton/IconButton.type.ts index 5c277e578..de891e0ba 100644 --- a/HDesign/src/components/IconButton/IconButton.type.ts +++ b/HDesign/src/components/IconButton/IconButton.type.ts @@ -6,7 +6,10 @@ export type IconButtonVariants = 'none' | 'primary' | 'secondary' | 'tertiary' | export interface IconButtonStyleProps { size?: IconButtonSize; variants: IconButtonVariants; - theme?: Theme; +} + +export interface IconButtonStylePropsWithTheme extends IconButtonStyleProps { + theme: Theme; } export interface IconButtonCustomProps {} From 9336798081a92fcd51cf424dc83c4ab00b8d38c8 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 7 Aug 2024 13:03:30 +0900 Subject: [PATCH 118/273] =?UTF-8?q?feat:=20=EB=A9=A4=EB=B2=84=20=EC=95=A1?= =?UTF-8?q?=EC=85=98=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20+=20=EB=B0=94=EB=80=90=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=A0=81=EC=9A=A9=20(#2?= =?UTF-8?q?14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --- client/package-lock.json | 231 ++++++++++++------ client/package.json | 6 +- client/src/App.tsx | 6 +- client/src/apis/fetcher.ts | 5 +- client/src/apis/request/bill.ts | 2 + client/src/apis/request/member.ts | 2 + client/src/apis/request/report.ts | 2 + client/src/apis/request/stepList.ts | 2 + .../AddBillActionListModalContent.tsx | 4 +- .../AddBillActionListModalContent/index.ts | 1 + .../AddMemberActionListModalContent.tsx | 7 +- .../AddMemberActionListModalContent/index.ts | 1 + .../DeleteMemberActionModal.style.ts | 26 ++ .../DeleteMemberActionModal.tsx | 60 +++++ .../DeleteMemberActionModal/index.ts | 1 + .../SetActionModal/SetActionListModal.tsx | 12 +- .../SetInitialMemberListModal.tsx | 2 +- client/src/components/Modal/index.ts | 2 +- .../src/components/StepList/BillStepItem.tsx | 34 +++ .../components/StepList/MemberStepItem.tsx | 33 +++ client/src/components/StepList/Step.tsx | 24 ++ client/src/components/StepList/StepList.tsx | 22 +- .../useDeleteMemberAction.tsx | 91 +++++++ .../useSearchMemberReportList.tsx | 2 + client/src/hooks/useStepList/type.ts | 38 --- client/src/hooks/useStepList/useStepList.tsx | 6 +- client/src/mocks/stepList.json | 59 +++-- ...EvenPageLayout.tsx => EventPageLayout.tsx} | 0 client/src/pages/EventPage/index.ts | 2 +- client/src/type.d.ts | 18 -- client/src/utils/validate/validatePurchase.ts | 2 + 31 files changed, 502 insertions(+), 201 deletions(-) create mode 100644 client/src/components/Modal/SetActionModal/AddBillActionListModalContent/index.ts create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts create mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts create mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx create mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts create mode 100644 client/src/components/StepList/BillStepItem.tsx create mode 100644 client/src/components/StepList/MemberStepItem.tsx create mode 100644 client/src/components/StepList/Step.tsx create mode 100644 client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx delete mode 100644 client/src/hooks/useStepList/type.ts rename client/src/pages/EventPage/{EvenPageLayout.tsx => EventPageLayout.tsx} (100%) delete mode 100644 client/src/type.d.ts diff --git a/client/package-lock.json b/client/package-lock.json index 2b1894624..67f32bd58 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,9 +10,7 @@ "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", - "@types/dotenv-webpack": "^7.0.7", - "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.53", + "haengdong-design": "^0.1.58", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -21,11 +19,13 @@ "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", "@svgr/webpack": "^8.1.0", + "@types/dotenv-webpack": "^7.0.7", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "dotenv": "^16.4.5", + "dotenv-webpack": "^8.1.0", "eslint": "^9.6.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", @@ -2152,6 +2152,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -2552,9 +2553,9 @@ } }, "node_modules/@swc/core": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.5.tgz", - "integrity": "sha512-qKK0/Ta4qvxs/ok3XyYVPT7OBenwRn1sSINf1cKQTBHPqr7U/uB4k2GTl6JgEs8H4PiJrMTNWfMLTucIoVSfAg==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.6.tgz", + "integrity": "sha512-FZxyao9eQks1MRmUshgsZTmlg/HB2oXK5fghkoWJm/1CU2q2kaJlVDll2as5j+rmWiwkp0Gidlq8wlXcEEAO+g==", "hasInstallScript": true, "dependencies": { "@swc/counter": "^0.1.3", @@ -2568,16 +2569,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.5", - "@swc/core-darwin-x64": "1.7.5", - "@swc/core-linux-arm-gnueabihf": "1.7.5", - "@swc/core-linux-arm64-gnu": "1.7.5", - "@swc/core-linux-arm64-musl": "1.7.5", - "@swc/core-linux-x64-gnu": "1.7.5", - "@swc/core-linux-x64-musl": "1.7.5", - "@swc/core-win32-arm64-msvc": "1.7.5", - "@swc/core-win32-ia32-msvc": "1.7.5", - "@swc/core-win32-x64-msvc": "1.7.5" + "@swc/core-darwin-arm64": "1.7.6", + "@swc/core-darwin-x64": "1.7.6", + "@swc/core-linux-arm-gnueabihf": "1.7.6", + "@swc/core-linux-arm64-gnu": "1.7.6", + "@swc/core-linux-arm64-musl": "1.7.6", + "@swc/core-linux-x64-gnu": "1.7.6", + "@swc/core-linux-x64-musl": "1.7.6", + "@swc/core-win32-arm64-msvc": "1.7.6", + "@swc/core-win32-ia32-msvc": "1.7.6", + "@swc/core-win32-x64-msvc": "1.7.6" }, "peerDependencies": { "@swc/helpers": "*" @@ -2589,9 +2590,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.5.tgz", - "integrity": "sha512-Y+bvW9C4/u26DskMbtQKT4FU6QQenaDYkKDi028vDIKAa7v1NZqYG9wmhD/Ih7n5EUy2uJ5I5EWD7WaoLzT6PA==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.6.tgz", + "integrity": "sha512-6lYHey84ZzsdtC7UuPheM4Rm0Inzxm6Sb8U6dmKc4eCx8JL0LfWG4LC5RsdsrTxnjTsbriWlnhZBffh8ijUHIQ==", "cpu": [ "arm64" ], @@ -2604,9 +2605,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.5.tgz", - "integrity": "sha512-AuIbDlcaAhYS6mtF4UqvXgrLeAfXZbVf4pgtgShPbutF80VbCQiIB55zOFz5aZdCpsBVuCWcBq0zLneK+VQKkQ==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.6.tgz", + "integrity": "sha512-Fyl+8aH9O5rpx4O7r2KnsPpoi32iWoKOYKiipeTbGjQ/E95tNPxbmsz4yqE8Ovldcga60IPJ5OKQA3HWRiuzdw==", "cpu": [ "x64" ], @@ -2619,9 +2620,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.5.tgz", - "integrity": "sha512-99uBPHITRqgGwCXAjHY94VaV3Z40+D2NQNgR1t6xQpO8ZnevI6YSzX6GVZfBnV7+7oisiGkrVEwfIRRa+1s8FA==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.6.tgz", + "integrity": "sha512-2WxYTqFaOx48GKC2cbO1/IntA+w+kfCFy436Ij7qRqqtV/WAvTM9TC1OmiFbqq436rSot52qYmX8fkwdB5UcLQ==", "cpu": [ "arm" ], @@ -2634,9 +2635,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.5.tgz", - "integrity": "sha512-xHL3Erlz+OGGCG4h6K2HWiR56H5UYMuBWWPbbUufi2bJpfhuKQy/X3vWffwL8ZVfJmCUwr4/G91GHcm32uYzRg==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.6.tgz", + "integrity": "sha512-TBEGMSe0LhvPe4S7E68c7VzgT3OMu4VTmBLS7B2aHv4v8uZO92Khpp7L0WqgYU1y5eMjk+XLDLi4kokiNHv/Hg==", "cpu": [ "arm64" ], @@ -2649,9 +2650,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.5.tgz", - "integrity": "sha512-5ArGdqvFMszNHdi4a67vopeYq8d1K+FuTWDrblHrAvZFhAyv+GQz2PnKqYOgl0sWmQxsNPfNwBFtxACpUO3Jzg==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.6.tgz", + "integrity": "sha512-QI8QGL0HGT42tj7F1A+YAzhGkJjUcvvTfI1e2m704W0Enl2/UIK9v5D1zvQzYwusRyKuaQfbeBRYDh0NcLOGLg==", "cpu": [ "arm64" ], @@ -2664,9 +2665,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.5.tgz", - "integrity": "sha512-mSVVV/PFzCGtI1nVQQyx34NwCMgSurF6ZX/me8pUAX054vsE/pSFL66xN+kQOe/1Z/LOd4UmXFkZ/EzOSnYcSg==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.6.tgz", + "integrity": "sha512-61AYVzhjuNQAVIKKWOJu3H0/pFD28RYJGxnGg3YMhvRLRyuWNyY5Nyyj2WkKcz/ON+g38Arlz00NT1LDIViRLg==", "cpu": [ "x64" ], @@ -2679,9 +2680,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.5.tgz", - "integrity": "sha512-09hY3ZKMUORXVunESKS9yuP78+gQbr759GKHo8wyCdtAx8lCZdEjfI5NtC7/1VqwfeE32/U6u+5MBTVhZTt0AA==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.6.tgz", + "integrity": "sha512-hQFznpfLK8XajfAAN9Cjs0w/aVmO7iu9VZvInyrTCRcPqxV5O+rvrhRxKvC1LRMZXr5M6JRSRtepp5w+TK4kAw==", "cpu": [ "x64" ], @@ -2694,9 +2695,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.5.tgz", - "integrity": "sha512-B/UDtPI3RlYRFW42xQxOpl6kI/9LtkD7No+XeRIKQTPe15EP2o+rUlv7CmKljVBXgJ8KmaQbZlaEh1YP+QZEEQ==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.6.tgz", + "integrity": "sha512-Aqsd9afykVMuekzjm4X4TDqwxmG4CrzoOSFe0hZrn9SMio72l5eAPnMtYoe5LsIqtjV8MNprLfXaNbjHjTegmA==", "cpu": [ "arm64" ], @@ -2709,9 +2710,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.5.tgz", - "integrity": "sha512-BgLesVGmIY6Nub/sURqtSRvWYcbCE/ACfuZB3bZHVKD6nsZJJuOpdB8oC41fZPyc8yZUzL3XTBIifkT2RP+w9w==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.6.tgz", + "integrity": "sha512-9h0hYnOeRVNeQgHQTvD1Im67faNSSzBZ7Adtxyu9urNLfBTJilMllFd2QuGHlKW5+uaT6ZH7ZWDb+c/enx7Lcg==", "cpu": [ "ia32" ], @@ -2724,9 +2725,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.5.tgz", - "integrity": "sha512-CnF557tidLfQRPczcqDJ8x+LBQYsFa0Ra6w2+YU1iFUboaI2jJVuqt3vEChu80y6JiRIBAaaV2L/GawDJh1dIQ==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.6.tgz", + "integrity": "sha512-izeoB8glCSe6IIDQmrVm6bvR9muk9TeKgmtY7b6l1BwL4BFnTUk4dMmpbntT90bEVQn3JPCaPtUG4HfL8VuyuA==", "cpu": [ "x64" ], @@ -2801,6 +2802,7 @@ "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", "integrity": "sha512-tltVokFUeYuSjNmHc6N892Asu/JIQcnH2iUF5A29/VKqv9opq6KlrmnKd/Lt/bBikV/z0YN2K0kguTwWirYCMQ==", + "dev": true, "dependencies": { "@types/node": "*", "tapable": "^2.2.0", @@ -2811,6 +2813,7 @@ "version": "9.6.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -2820,6 +2823,7 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -2828,7 +2832,8 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, "node_modules/@types/express": { "version": "4.17.21", @@ -2878,7 +2883,8 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true }, "node_modules/@types/json5": { "version": "0.0.29", @@ -2896,6 +2902,7 @@ "version": "22.1.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, "dependencies": { "undici-types": "~6.13.0" } @@ -3206,6 +3213,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -3214,22 +3222,26 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -3239,12 +3251,14 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -3256,6 +3270,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -3264,6 +3279,7 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -3271,12 +3287,14 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -3292,6 +3310,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -3304,6 +3323,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -3315,6 +3335,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -3328,6 +3349,7 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" @@ -3380,12 +3402,14 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true }, "node_modules/accepts": { "version": "1.3.8", @@ -3404,6 +3428,7 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -3415,6 +3440,7 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, "peerDependencies": { "acorn": "^8" } @@ -3432,6 +3458,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3486,6 +3513,7 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -3796,12 +3824,12 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -3969,7 +3997,8 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true }, "node_modules/bundle-name": { "version": "4.1.0", @@ -4044,9 +4073,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001646", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001646.tgz", - "integrity": "sha512-dRg00gudiBDDTmUhClSdv3hqRfpbOnU28IpI1T6PBTLWa+kOj0681C8uML3PifYfREuBrVjDGhL3adYpBT6spw==", + "version": "1.0.30001649", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz", + "integrity": "sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ==", "funding": [ { "type": "opencollective", @@ -4123,6 +4152,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, "engines": { "node": ">=6.0" } @@ -4298,11 +4328,11 @@ "dev": true }, "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "version": "3.38.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", + "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==", "dependencies": { - "browserslist": "^4.23.0" + "browserslist": "^4.23.3" }, "funding": { "type": "opencollective", @@ -4791,6 +4821,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz", "integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==", + "dev": true, "dependencies": { "dotenv": "^8.2.0" } @@ -4799,6 +4830,7 @@ "version": "8.6.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "dev": true, "engines": { "node": ">=10" } @@ -4807,6 +4839,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz", "integrity": "sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag==", + "dev": true, "dependencies": { "dotenv-defaults": "^2.0.2" }, @@ -4862,6 +4895,7 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -5030,7 +5064,8 @@ "node_modules/es-module-lexer": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -5635,6 +5670,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -5646,6 +5682,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -5677,6 +5714,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, "engines": { "node": ">=0.8.x" } @@ -5764,7 +5802,8 @@ "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==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "node_modules/fast-diff": { "version": "1.3.0", @@ -5803,7 +5842,8 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -6332,7 +6372,8 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true }, "node_modules/globals": { "version": "15.9.0", @@ -6397,7 +6438,8 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", @@ -6406,9 +6448,9 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.53", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.53.tgz", - "integrity": "sha512-CtaoUUdE6iTcTceAzKxZyn8LjJvMjrlYiQhxXC7RC36G1Jxc0OcU2WlAv/6yT8mfFKc1yUOi5H1omTXWjCD5gA==", + "version": "0.1.58", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.58.tgz", + "integrity": "sha512-eXpjBpFJKwrVjEN6m7GMAQ0qzbc/mgN6/A76Y/Q1oKRMuS48m/EjIqp886AgdoqEz7CwDUtJcDEcf239KYk5JA==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", @@ -7444,6 +7486,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -7457,6 +7500,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -7465,6 +7509,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -7516,7 +7561,8 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -7630,6 +7676,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, "engines": { "node": ">=6.11.5" } @@ -7743,7 +7790,8 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "node_modules/merge2": { "version": "1.4.1", @@ -7792,6 +7840,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -7800,6 +7849,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -7957,7 +8007,8 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true }, "node_modules/no-case": { "version": "3.0.4", @@ -8593,6 +8644,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "engines": { "node": ">=6" } @@ -8636,6 +8688,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -9054,6 +9107,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -9104,6 +9158,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -9193,6 +9248,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -9443,6 +9499,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -9452,6 +9509,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -9882,6 +9940,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, "engines": { "node": ">=6" } @@ -9890,6 +9949,7 @@ "version": "5.31.3", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", + "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -9907,6 +9967,7 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -9939,7 +10000,8 @@ "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "node_modules/text-table": { "version": "0.2.0", @@ -10317,7 +10379,8 @@ "node_modules/undici-types": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", - "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -10406,6 +10469,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -10453,6 +10517,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -10474,6 +10539,7 @@ "version": "5.93.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -10792,6 +10858,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, "engines": { "node": ">=10.13.0" } @@ -10800,6 +10867,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -10812,6 +10880,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, "engines": { "node": ">=4.0" } diff --git a/client/package.json b/client/package.json index 833053883..0216028cc 100644 --- a/client/package.json +++ b/client/package.json @@ -16,11 +16,13 @@ "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", "@svgr/webpack": "^8.1.0", + "@types/dotenv-webpack": "^7.0.7", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "dotenv": "^16.4.5", + "dotenv-webpack": "^8.1.0", "eslint": "^9.6.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.1", @@ -43,9 +45,7 @@ }, "dependencies": { "@emotion/react": "^11.11.4", - "@types/dotenv-webpack": "^7.0.7", - "dotenv-webpack": "^8.1.0", - "haengdong-design": "^0.1.53", + "haengdong-design": "^0.1.58", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/App.tsx b/client/src/App.tsx index e09f98e8d..849d78420 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,5 +1,5 @@ import {Outlet} from 'react-router-dom'; -import {HDesignProvider} from 'haengdong-design'; +import {HDesignProvider, ToastProvider} from 'haengdong-design'; import {Global} from '@emotion/react'; import {GlobalStyle} from './GlobalStyle'; @@ -8,7 +8,9 @@ const App: React.FC = () => { return ( <HDesignProvider> <Global styles={GlobalStyle} /> - <Outlet /> + <ToastProvider> + <Outlet /> + </ToastProvider> </HDesignProvider> ); }; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index f0bdb9887..f7ac3b976 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -105,8 +105,9 @@ const errorHandler = async (url: string, options: Options) => { } return response; } catch (error) { - console.error(error); - // throw new ErrorWithHeader(errorMessageHeader, getErrorMessage(error)); + if (error instanceof Error) { + throw new Error(error.message); + } return; } }; diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 6e5a0f3ab..6996ac01c 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -1,3 +1,5 @@ +import type {Bill} from 'types/serviceType'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestPost, requestDelete, requestPut} from '@apis/fetcher'; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 2ae3c384a..2552de857 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -1,3 +1,5 @@ +import type {MemberType} from 'types/serviceType'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestPost, requestDelete} from '@apis/fetcher'; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts index 7450f0978..8992f9c30 100644 --- a/client/src/apis/request/report.ts +++ b/client/src/apis/request/report.ts @@ -1,3 +1,5 @@ +import type {MemberReport} from 'types/serviceType'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet} from '@apis/fetcher'; diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts index 7abb80f59..0d47ab90e 100644 --- a/client/src/apis/request/stepList.ts +++ b/client/src/apis/request/stepList.ts @@ -1,3 +1,5 @@ +import type {StepList} from 'types/serviceType'; + import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet} from '@apis/fetcher'; diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index 873fe8118..8fac562f5 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -7,12 +7,12 @@ import useDynamicBillActionInput from '@hooks/useDynamicBillActionInput'; import style from './AddBillActionListModalContent.style'; -interface SetPurchaseProps { +interface AddBillActionListModalContentProps { setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; setOrder: React.Dispatch<React.SetStateAction<number>>; } -const AddBillActionListModalContent = ({setOpenBottomSheet, setOrder}: SetPurchaseProps) => { +const AddBillActionListModalContent = ({setOpenBottomSheet, setOrder}: AddBillActionListModalContentProps) => { const { inputPairList, inputRefList, diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/index.ts b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/index.ts new file mode 100644 index 000000000..ed3e43886 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/index.ts @@ -0,0 +1 @@ +export {default as AddBillActionListModalContent} from './AddBillActionListModalContent'; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index 59894493c..aff2764c8 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -1,19 +1,20 @@ +import type {MemberType} from 'types/serviceType'; + import {FixedButton, LabelGroupInput} from 'haengdong-design'; import {useStepList} from '@hooks/useStepList/useStepList'; import validateMemberName from '@utils/validate/validateMemberName'; -import {MemberType} from 'types/serviceType'; import useDynamicInput from '@hooks/useDynamicInput'; import style from './AddMemberActionListModalContent.style'; -interface UpdateMembersProps { +interface AddMemberActionListModalContentProps { inOutAction: MemberType; setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; } -const AddMemberActionListModalContent = ({inOutAction, setOpenBottomSheet}: UpdateMembersProps) => { +const AddMemberActionListModalContent = ({inOutAction, setOpenBottomSheet}: AddMemberActionListModalContentProps) => { const { inputList, inputRefList, diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts new file mode 100644 index 000000000..6519283f4 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts @@ -0,0 +1 @@ +export {default as AddMemberActionListModalContent} from './AddMemberActionListModalContent'; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts new file mode 100644 index 000000000..48e4c13af --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts @@ -0,0 +1,26 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1.5rem', +}); + +export const bottomSheetHeaderStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignContent: 'center', + + width: '100%', +}); + +export const inputGroupStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '11rem', +}); diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx new file mode 100644 index 000000000..d1c0c2556 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -0,0 +1,60 @@ +import type {MemberAction, MemberType} from 'types/serviceType'; + +import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; + +import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; + +import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; + +type DeleteMemberActionModalProps = { + memberActionType: MemberType; + memberActionList: MemberAction[]; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; +}; + +const DeleteMemberActionModal = ({ + memberActionType, + memberActionList, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: DeleteMemberActionModalProps) => { + const {aliveActionList, deleteMemberActionList, addDeleteMemberAction} = useDeleteMemberAction( + memberActionList, + setIsBottomSheetOpened, + ); + + return ( + <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> + <div css={bottomSheetStyle}> + <header css={bottomSheetHeaderStyle}> + <Text size="bodyBold">{memberActionType === 'IN' ? '들어온' : '나간'} 인원 수정하기</Text> + {/* TODO: (@cookie): 텍스트 색 수정 필요 */} + <Text size="bodyBold">{`${aliveActionList.length}명`}</Text> + </header> + <ul css={inputGroupStyle}> + {aliveActionList.map(member => ( + <li key={member.actionId}> + <Flex flexDirection="row" width="100%" gap="1rem"> + <div style={{flexGrow: 1}}> + <Input disabled key={`${member.actionId}`} type="text" style={{flexGrow: 1}} value={member.name} /> + </div> + <IconButton size="medium" variants="tertiary" onClick={() => addDeleteMemberAction(member)}> + <Icon iconType="trash" iconColor="onTertiary" /> + </IconButton> + </Flex> + </li> + ))} + </ul> + <FixedButton + variants="primary" + children="수정 완료" + onClick={deleteMemberActionList} + disabled={memberActionList.length === aliveActionList.length} + /> + </div> + </BottomSheet> + ); +}; + +export default DeleteMemberActionModal; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts new file mode 100644 index 000000000..2a6b52b45 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts @@ -0,0 +1 @@ +export {default as DeleteMemberActionModal} from './DeleteMemberActionModal'; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx index f33597334..a4c38e6c4 100644 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -1,8 +1,10 @@ +import type {InOutType} from 'types/serviceType'; + import {useState} from 'react'; import {BottomSheet, Switch} from 'haengdong-design'; -import SetPurchase from './AddBillActionListModalContent/AddBillActionListModalContent'; -import AddMemberActionListModalContent from './AddMemberActionListModalContent/AddMemberActionListModalContent'; +import {AddBillActionListModalContent} from './AddBillActionListModalContent'; +import {AddMemberActionListModalContent} from './AddMemberActionListModalContent'; import style from './SetActionListModal.style'; export type ActionType = '지출' | '인원'; @@ -26,7 +28,7 @@ const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: Set }; return ( - <BottomSheet isOpened={openBottomSheet} onChangeClose={() => setOpenBottomSheet(false)}> + <BottomSheet isOpened={openBottomSheet} onClose={() => setOpenBottomSheet(false)}> <div css={style.container}> <div css={style.switchContainer}> <Switch value={action} onChange={handleActionTypeChange} values={['지출', '인원']} /> @@ -35,7 +37,9 @@ const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: Set )} </div> - {action === '지출' && <SetPurchase setOpenBottomSheet={setOpenBottomSheet} setOrder={setOrder} />} + {action === '지출' && ( + <AddBillActionListModalContent setOpenBottomSheet={setOpenBottomSheet} setOrder={setOrder} /> + )} {action === '인원' && ( <AddMemberActionListModalContent inOutAction={inOutAction === '탈주' ? 'OUT' : 'IN'} diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index 4546e0540..d273c5e6a 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -34,7 +34,7 @@ const SetInitialMemberListModal = ({openBottomSheet, setOpenBottomSheet}: SetIni }; return ( - <BottomSheet isOpened={openBottomSheet} onChangeClose={() => setOpenBottomSheet(false)}> + <BottomSheet isOpened={openBottomSheet} onClose={() => setOpenBottomSheet(false)}> <div css={setInitialMemberListModalStyle}> <Text size="bodyBold">초기 인원 설정하기</Text> <div css={setInitialMemberListModalInputGroupStyle}> diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts index 36ccd8b2e..a6e55f84a 100644 --- a/client/src/components/Modal/index.ts +++ b/client/src/components/Modal/index.ts @@ -1,2 +1,2 @@ -export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; +export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx new file mode 100644 index 000000000..c1021ee5b --- /dev/null +++ b/client/src/components/StepList/BillStepItem.tsx @@ -0,0 +1,34 @@ +import type {BillStep} from 'types/serviceType'; + +import {DragHandleItem, DragHandleItemContainer} from 'haengdong-design'; + +interface BillStepItemProps { + step: BillStep; + isOpenBottomSheet: boolean; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; +} + +const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, setOpenBottomSheet}) => { + const totalPrice = step.actions.reduce((acc, cur) => acc + cur.price, 0); + + return ( + <DragHandleItemContainer + topLeftText={step.stepName} + topRightText={`${step.members.length}명`} + bottomLeftText="총액" + bottomRightText={`${totalPrice.toLocaleString('ko-kr')} 원`} + backgroundColor="white" + > + {step.actions.map(action => ( + <DragHandleItem + hasDragHandler={true} + prefix={action.name} + suffix={`${action.price.toLocaleString('ko-kr')} 원`} + backgroundColor="lightGrayContainer" + /> + ))} + </DragHandleItemContainer> + ); +}; + +export default BillStepItem; diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx new file mode 100644 index 000000000..8d93b373d --- /dev/null +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -0,0 +1,33 @@ +import type {MemberStep} from 'types/serviceType'; + +import {DragHandleItem} from 'haengdong-design'; + +import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMemberActionModal'; + +interface MemberStepItemProps { + step: MemberStep; + isOpenBottomSheet: boolean; + setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; +} + +const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, setOpenBottomSheet}) => { + return ( + <> + <DragHandleItem + backgroundColor="white" + prefix={`${step.actions.map(({name}) => name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} + onClick={() => setOpenBottomSheet(prev => !prev)} + /> + {isOpenBottomSheet && ( + <DeleteMemberActionModal + memberActionType={step.type} + memberActionList={step.actions} + isBottomSheetOpened={isOpenBottomSheet} + setIsBottomSheetOpened={setOpenBottomSheet} + /> + )} + </> + ); +}; + +export default MemberStepItem; diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx new file mode 100644 index 000000000..859085800 --- /dev/null +++ b/client/src/components/StepList/Step.tsx @@ -0,0 +1,24 @@ +import type {BillStep, MemberStep} from 'types/serviceType'; + +import {useState} from 'react'; + +import BillStepItem from './BillStepItem'; +import MemberStepItem from './MemberStepItem'; + +interface StepProps { + step: BillStep | MemberStep; +} + +const Step = ({step}: StepProps) => { + const [isOpenBottomSheet, setOpenBottomSheet] = useState<boolean>(false); + + if (step.type === 'BILL') { + return <BillStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setOpenBottomSheet={setOpenBottomSheet} />; + } else if (step.type === 'IN' || step.type === 'OUT') { + return <MemberStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setOpenBottomSheet={setOpenBottomSheet} />; + } else { + return <></>; + } +}; + +export default Step; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 6e9961f99..ccd6afd94 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,28 +1,18 @@ -import {Flex, InOutItem, StepItem} from 'haengdong-design'; +import {Flex} from 'haengdong-design'; import {useStepList} from '@hooks/useStepList/useStepList'; +import Step from './Step'; + const StepList = () => { const {stepList} = useStepList(); // TODO: (@weadie) if else 구문이 지저분하므로 리펙터링이 필요합니다. return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - {stepList.map(step => { - if (step.type === 'BILL') { - return ( - <StepItem - name={step.stepName === null ? '행사' : step.stepName} - bills={step.actions} - personCount={step.members.length} - /> - ); - } else if (step.type === 'IN' || step.type === 'OUT') { - return <InOutItem inOutType={step.type} names={step.actions.map(({name}) => name)} />; - } else { - return <></>; - } - })} + {stepList.map((step, index) => ( + <Step step={step} key={`${step.stepName}${index}`}></Step> + ))} </Flex> ); }; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx new file mode 100644 index 000000000..1e3965820 --- /dev/null +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx @@ -0,0 +1,91 @@ +import type {MemberAction} from 'types/serviceType'; + +import {useState} from 'react'; +import {useToast} from 'haengdong-design'; + +import useEventId from '@hooks/useEventId/useEventId'; +import {requestDeleteMemberAction} from '@apis/request/member'; +import {useStepList} from '@hooks/useStepList/useStepList'; + +const useDeleteMemberAction = ( + memberActionList: MemberAction[], + setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>, +) => { + const {stepList, refreshStepList} = useStepList(); + const [aliveActionList, setAliveActionList] = useState<MemberAction[]>(memberActionList); + const {eventId} = useEventId(); + const {showToast} = useToast(); + + const deleteMemberAction = async (actionId: number) => { + try { + await requestDeleteMemberAction({actionId, eventId}); + } catch (error) { + // TODO: (@cookie): 에러처리 백엔드에 맞게 나중에 메시지 설정 + // 원래는 백엔드가 만들어준 에러토큰을 이용해서 나눠서 보여주는 것이 맞지만 우리가 에러처리를 아무곳에서도 하지않아서 후추 + showToast({ + isClickToClose: true, + message: '멤버 삭제가 되지 않았어요 :(', + showingTime: 3000, + type: 'error', + bottom: '160px', + }); + } + }; + + const deleteMemberActionList = async () => { + const aliveActionIdList = aliveActionList.map(({actionId}) => actionId); + const deleteMemberActionIdList = memberActionList + .filter(({actionId}) => !aliveActionIdList.includes(actionId)) + .map(({actionId}) => actionId); + + for (const deleteMemberActionId of deleteMemberActionIdList) { + await deleteMemberAction(deleteMemberActionId); + } + + refreshStepList(); + setIsBottomSheetOpened(false); + }; + + const addDeleteMemberAction = (memberAction: MemberAction) => { + if (!memberActionList.includes(memberAction)) { + showToast({ + isClickToClose: true, + showingTime: 3000, + message: '이미 삭제된 인원입니다.', + type: 'error', + bottom: '160px', + }); + return; + } + + if (isExistSameMemberFromAfterStep(memberAction)) { + showToast({ + isClickToClose: true, + showingTime: 3000, + message: `이후의 ${memberAction.name}가 사라져요`, + type: 'error', + position: 'top', + top: '30px', + style: { + zIndex: 9000, + }, + }); + } + + setAliveActionList(prev => prev.filter(aliveMember => aliveMember.actionId !== memberAction.actionId)); + }; + + // 현재 선택된 액션의 인덱스를 구해서 뒤의 동일인물의 액션이 있는지를 파악하는 기능 + const isExistSameMemberFromAfterStep = (memberAction: MemberAction) => { + const memberActionList = stepList.filter(step => step.type !== 'BILL').flatMap(({actions}) => actions); + const currentActionIndex = memberActionList.findIndex(action => action.actionId === memberAction.actionId); + const memberActionListAfterCurrentAction = memberActionList.slice(Math.max(currentActionIndex - 1, 0)); + const memberNameList = memberActionListAfterCurrentAction.map(({name}) => name); + + return memberNameList.filter(member => member === memberAction.name).length >= 2; + }; + + return {aliveActionList, deleteMemberActionList, addDeleteMemberAction}; +}; + +export default useDeleteMemberAction; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx index 84718891e..e7c0d7626 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -1,3 +1,5 @@ +import type {MemberReport} from 'types/serviceType'; + import {useEffect, useState} from 'react'; import {requestGetMemberReportList} from '@apis/request/report'; diff --git a/client/src/hooks/useStepList/type.ts b/client/src/hooks/useStepList/type.ts deleted file mode 100644 index 6d9b78de1..000000000 --- a/client/src/hooks/useStepList/type.ts +++ /dev/null @@ -1,38 +0,0 @@ -export type Step = { - type: MemberType | 'BILL'; - stepName: string | null; - members: string[]; - actions: (BillAction | MemberAction)[]; -}; - -export type MemberStep = Omit<Step, 'type' | 'stepName' | 'actions'> & { - type: MemberType; - stepName: null; - actions: MemberAction[]; -}; - -export type BillStep = Omit<Step, 'type' | 'stepName' | 'actions'> & { - type: 'BILL'; - stepName: string; - actions: BillAction[]; -}; - -export type Action = { - actionId: number; - name: string; - price: number | null; - sequence?: number; -}; - -export type BillAction = Omit<Action, 'price'> & { - price: number; -}; - -export type MemberAction = Omit<Action, 'price'> & { - price: null; -}; - -export type Member = { - name: string; - status: MemberType; -}; diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx index e42732e05..f2aa12b66 100644 --- a/client/src/hooks/useStepList/useStepList.tsx +++ b/client/src/hooks/useStepList/useStepList.tsx @@ -1,3 +1,5 @@ +import type {MemberType, Bill, BillAction, BillStep, MemberStep} from 'types/serviceType.ts'; + import {PropsWithChildren, createContext, useContext, useEffect, useState} from 'react'; import useEventId from '@hooks/useEventId/useEventId'; @@ -5,14 +7,13 @@ import {requestPostBillList} from '@apis/request/bill'; import {requestPostMemberList} from '@apis/request/member'; import {requestGetStepList} from '@apis/request/stepList'; -import {BillAction, BillStep, MemberStep} from './type.ts'; - interface StepListContextProps { stepList: (BillStep | MemberStep)[]; getTotalPrice: () => number; addBill: (billList: Bill[]) => Promise<void>; updateMemberList: ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => Promise<void>; memberNameList: string[]; + refreshStepList: () => Promise<void>; } export const StepListContext = createContext<StepListContextProps | null>(null); // TODO: (@weadie) 인자를 어떻게 줘야 하는지 고민하기. @@ -83,6 +84,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { updateMemberList, stepList, memberNameList, + refreshStepList, }} > {children} diff --git a/client/src/mocks/stepList.json b/client/src/mocks/stepList.json index cc3815a75..e4221ffd3 100644 --- a/client/src/mocks/stepList.json +++ b/client/src/mocks/stepList.json @@ -2,60 +2,45 @@ { "type": "IN", "stepName": null, + "members": [], "actions": [ { - "actionId": 3, + "actionId": 1, "name": "망쵸", "price": null, - "sequence": 3 + "sequence": 1 }, { - "actionId": 4, + "actionId": 2, "name": "백호", "price": null, - "sequence": 4 + "sequence": 2 } ] }, { "type": "BILL", "stepName": "1차", + "members": ["망쵸", "백호"], "actions": [ { - "actionId": 1, + "actionId": 3, "name": "감자탕", "price": 10000, - "sequence": 1 - }, - { - "actionId": 2, - "name": "인생네컷", - "price": 10000, - "sequence": 2 - } - ] - }, - { - "type": "IN", - "stepName": null, - "actions": [ - { - "actionId": 3, - "name": "망쵸", - "price": null, "sequence": 3 }, { "actionId": 4, - "name": "백호", - "price": null, + "name": "인생네컷", + "price": 10000, "sequence": 4 } ] }, { - "type": "OUT", + "type": "IN", "stepName": null, + "members": [], "actions": [ { "actionId": 5, @@ -74,12 +59,32 @@ { "type": "BILL", "stepName": "2차", + "members": ["소하", "웨디"], "actions": [ { - "actionId": 8, + "actionId": 9, "name": "노래방", "price": 20000, + "sequence": 10 + } + ] + }, + { + "type": "OUT", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 7, + "name": "망쵸", + "price": null, "sequence": 7 + }, + { + "actionId": 8, + "name": "백호", + "price": null, + "sequence": 8 } ] } diff --git a/client/src/pages/EventPage/EvenPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx similarity index 100% rename from client/src/pages/EventPage/EvenPageLayout.tsx rename to client/src/pages/EventPage/EventPageLayout.tsx diff --git a/client/src/pages/EventPage/index.ts b/client/src/pages/EventPage/index.ts index c560632da..5b5c314c7 100644 --- a/client/src/pages/EventPage/index.ts +++ b/client/src/pages/EventPage/index.ts @@ -1 +1 @@ -export {default as EventPage} from './EvenPageLayout'; +export {default as EventPage} from './EventPageLayout'; diff --git a/client/src/type.d.ts b/client/src/type.d.ts deleted file mode 100644 index a81318e4c..000000000 --- a/client/src/type.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -type MemberType = 'IN' | 'OUT'; - -type InOutType = '늦참' | '탈주'; - -type MemberReport = { - name: string; - price: number; -}; - -type Bill = { - title: string; - price: number; -}; - -// TODO: (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. -type StepList = { - steps: (MemberStep | BillStep)[]; -}; diff --git a/client/src/utils/validate/validatePurchase.ts b/client/src/utils/validate/validatePurchase.ts index 026cfb496..b20742901 100644 --- a/client/src/utils/validate/validatePurchase.ts +++ b/client/src/utils/validate/validatePurchase.ts @@ -1,3 +1,5 @@ +import type {Bill} from 'types/serviceType'; + import ERROR_MESSAGE from '@constants/errorMessage'; import RULE from '@constants/rule'; import REGEXP from '@constants/regExp'; From 241cdce83d7b3461b9507bd73c87d5090eac386a Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:36:43 +0900 Subject: [PATCH 119/273] =?UTF-8?q?fix:=20FixedButton=EC=9D=98=20delete=20?= =?UTF-8?q?button=20type=20"button"=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20(#234)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 --- HDesign/package-lock.json | 6 +++--- HDesign/package.json | 4 ++-- HDesign/src/components/FixedButton/FixedButton.tsx | 5 +---- HDesign/src/components/IconButton/IconButton.style.ts | 4 ++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 739bbabe5..f465f5c3a 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.58", + "version": "0.1.60", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.58", + "version": "0.1.60", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", @@ -13821,4 +13821,4 @@ } } } -} \ No newline at end of file +} diff --git a/HDesign/package.json b/HDesign/package.json index 22232fb75..737f07b5b 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.58", + "version": "0.1.60", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", @@ -68,4 +68,4 @@ "npm": ">=10.7.0", "node": ">=20.15.1" } -} \ No newline at end of file +} diff --git a/HDesign/src/components/FixedButton/FixedButton.tsx b/HDesign/src/components/FixedButton/FixedButton.tsx index bb0e0d98f..efbfe164d 100644 --- a/HDesign/src/components/FixedButton/FixedButton.tsx +++ b/HDesign/src/components/FixedButton/FixedButton.tsx @@ -4,15 +4,12 @@ import {forwardRef} from 'react'; import { fixedButtonContainerStyle, fixedButtonStyle, - deleteButtonStyle, buttonContainerStyle, } from '@components/FixedButton/FixedButton.style'; import {FixedButtonProps} from '@components/FixedButton/FixedButton.type'; import IconButton from '@components/IconButton/IconButton'; import Icon from '@components/Icon/Icon'; -import Trash from '@assets/trash.svg'; - import {useTheme} from '@theme/HDesignProvider'; export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElement, FixedButtonProps>(function Button( @@ -24,7 +21,7 @@ export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElem <div css={fixedButtonContainerStyle(theme)}> <div css={buttonContainerStyle}> {onDeleteClick && ( - <IconButton size="large" variants="destructive" onClick={onDeleteClick}> + <IconButton type="button" size="large" variants="destructive" onClick={onDeleteClick}> <Icon iconType="trash" /> </IconButton> )} diff --git a/HDesign/src/components/IconButton/IconButton.style.ts b/HDesign/src/components/IconButton/IconButton.style.ts index 18ffc4533..53036eb68 100644 --- a/HDesign/src/components/IconButton/IconButton.style.ts +++ b/HDesign/src/components/IconButton/IconButton.style.ts @@ -57,8 +57,8 @@ const getIconButtonSize = (size: IconButtonSize) => { borderRadius: '1rem', }), large: css({ - padding: '1rem', - borderRadius: '1.25rem', + padding: '0.875rem', + borderRadius: '1.125rem', }), }; From bfbce95af47a00df9bfa6e211c60f9b1d22f0d91 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:37:33 +0900 Subject: [PATCH 120/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20flow=EC=97=90=EC=84=9C=20admin=20=EC=A0=91=EA=B7=BC?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=EB=A5=BC=20=EC=9E=85=EB=A0=A5=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#226)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 --- client/src/apis/fetcher.ts | 1 + client/src/apis/request/event.ts | 8 +- client/src/apis/requestPostEvent.ts | 13 --- client/src/constants/errorMessage.ts | 1 + client/src/constants/regExp.ts | 1 + client/src/constants/routerUrls.ts | 3 +- client/src/constants/rule.ts | 1 + .../CreateEventPage/SetEventNamePage.tsx | 12 +-- .../CreateEventPage/SetEventPasswordPage.tsx | 80 +++++++++++++++++++ client/src/router.tsx | 5 ++ .../utils/validate/validateEventPassword.ts | 13 +++ client/webpack.config.js | 2 +- 12 files changed, 113 insertions(+), 27 deletions(-) delete mode 100644 client/src/apis/requestPostEvent.ts create mode 100644 client/src/pages/CreateEventPage/SetEventPasswordPage.tsx create mode 100644 client/src/utils/validate/validateEventPassword.ts diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index f7ac3b976..4e53c5065 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -71,6 +71,7 @@ const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, query // const token = generateBasicToken(USER_ID, USER_PASSWORD); const options = { method, + credentials: 'include', headers: { 'Content-Type': 'application/json', // Authorization: token, diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index fc4708bf7..b6eb84b36 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -4,17 +4,21 @@ import {WithEventId} from '@apis/withEventId.type'; type RequestPostNewEvent = { eventName: string; + password: number; }; type ResponsePostNewEvent = { eventId: string; }; -export const requestPostNewEvent = async ({eventName}: RequestPostNewEvent) => { +export const requestPostNewEvent = async ({eventName, password}: RequestPostNewEvent) => { // TODO: (@weadie) 뼈대만 둔 것. header값을 꺼내오는 로직이 필요하다. 또는 바디에 달라고 부탁할 수 있다. return requestPost<ResponsePostNewEvent>({ endpoint: TEMP_PREFIX, - body: {eventName}, + body: { + eventName: eventName, + password: password, + }, }); }; diff --git a/client/src/apis/requestPostEvent.ts b/client/src/apis/requestPostEvent.ts deleted file mode 100644 index c03ae02af..000000000 --- a/client/src/apis/requestPostEvent.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {requestPost} from './fetcher'; - -interface RequestPostEventProps { - name: string; -} - -export const requestPostEvent = async ({name}: RequestPostEventProps) => { - await requestPost({ - headers: {'Content-Type': 'application/json'}, - body: {name}, - endpoint: '/api/events', - }); -}; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index e37220f7f..869359974 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -1,5 +1,6 @@ const ERROR_MESSAGE = { eventName: '행사 이름은 30자 이하만 가능해요', + eventPasswordType: '비밀번호는 숫자만 입력이 가능해요', memberName: '참여자 이름은 8자 이하의 한글, 영어만 가능해요', purchasePrice: '10,000,000원 이하의 숫자만 입력이 가능해요', purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts index 674be7ba2..ab9d5fcc0 100644 --- a/client/src/constants/regExp.ts +++ b/client/src/constants/regExp.ts @@ -1,4 +1,5 @@ const REGEXP = { + eventPassword: /^[0-9]*$/, memberName: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s]*$/, purchaseTitle: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s]*$/, }; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index c57ab181e..f9587b530 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -1,6 +1,7 @@ export const ROUTER_URLS = { - main: '', + main: '/', eventCreateName: '/event/create/name', + eventCreatePassword: '/event/create/password', eventCreateComplete: '/event/create/complete', event: '/event', // TODO: (@weadie) baseurl을 어떻게 관리할 것인가? eventManage: '/event/:eventId/admin', diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts index 0001cb73a..d6d53cd55 100644 --- a/client/src/constants/rule.ts +++ b/client/src/constants/rule.ts @@ -1,5 +1,6 @@ const RULE = { maxEventNameLength: 30, + maxEventPasswordLength: 4, maxMemberNameLength: 8, maxPrice: 10000000, }; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index 360db3f17..01f3304b8 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -16,15 +16,7 @@ const SetEventNamePage = () => { const submitEventName = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); - const response = await requestPostNewEvent({eventName}); - - if (response) { - const {eventId} = response; - navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`); - } else { - // TODO: (@weadie) - alert('오류님'); - } + navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); }; const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { @@ -58,7 +50,7 @@ const SetEventNamePage = () => { isError={!!errorMessage} autoFocus ></LabelInput> - <FixedButton disabled={!canSubmit}>행동 개시!</FixedButton> + <FixedButton disabled={!canSubmit}>다음</FixedButton> </form> </MainLayout> ); diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx new file mode 100644 index 000000000..682b7eda8 --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -0,0 +1,80 @@ +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; +import {requestPostNewEvent} from '@apis/request/event'; + +import RULE from '@constants/rule'; +import {ROUTER_URLS} from '@constants/routerUrls'; + +const SetEventPasswordPage = () => { + const [eventName, setEventName] = useState(''); + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + + const navigate = useNavigate(); + const location = useLocation(); + + useEffect(() => { + if (!location.state) { + navigate(ROUTER_URLS.main); + } else { + setEventName(location.state.eventName); + } + }, []); + + const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + const response = await requestPostNewEvent({eventName, password: parseInt(password)}); + + if (response) { + const {eventId} = response; + navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`); + } else { + // TODO: (@weadie) + alert('오류님'); + } + }; + + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (validation.isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + return ( + <MainLayout> + <TopNav> + <Back /> + </TopNav> + <Title title="행사 비밀번호 설정" description="행사 관리에 필요한 4 자리의 숫자 비밀번호를 입력해 주세요." /> + <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <LabelInput + labelText="비밀번호" + errorText={errorMessage} + value={password} + type="secret" + maxLength={RULE.maxEventPasswordLength} + placeholder="비밀번호" + onChange={e => handleChange(e)} + isError={!!errorMessage} + autoFocus + ></LabelInput> + <FixedButton disabled={!canSubmit}>행동 개시!</FixedButton> + </form> + </MainLayout> + ); +}; + +export default SetEventPasswordPage; diff --git a/client/src/router.tsx b/client/src/router.tsx index 75777310a..6daa7d260 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -2,6 +2,7 @@ import {createBrowserRouter} from 'react-router-dom'; import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; +import SetEventPasswordPage from '@pages/CreateEventPage/SetEventPasswordPage'; import {CompleteCreateEventPage, SetEventNamePage} from '@pages/CreateEventPage'; import {MainPage} from '@pages/MainPage'; @@ -25,6 +26,10 @@ const router = createBrowserRouter([ path: ROUTER_URLS.eventCreateName, element: <SetEventNamePage />, }, + { + path: ROUTER_URLS.eventCreatePassword, + element: <SetEventPasswordPage />, + }, { path: ROUTER_URLS.eventCreateComplete, element: <CompleteCreateEventPage />, diff --git a/client/src/utils/validate/validateEventPassword.ts b/client/src/utils/validate/validateEventPassword.ts new file mode 100644 index 000000000..70499e393 --- /dev/null +++ b/client/src/utils/validate/validateEventPassword.ts @@ -0,0 +1,13 @@ +import ERROR_MESSAGE from '@constants/errorMessage'; +import REGEXP from '@constants/regExp'; + +import {ValidateResult} from './type'; + +const validateEventPassword = (password: string): ValidateResult => { + if (!REGEXP.eventPassword.test(password)) { + return {isValid: false, errorMessage: ERROR_MESSAGE.eventPasswordType}; + } + return {isValid: true}; +}; + +export default validateEventPassword; diff --git a/client/webpack.config.js b/client/webpack.config.js index 2c706beec..43890bb68 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -28,7 +28,7 @@ export default { }, output: { path: path.join(__dirname, 'dist'), - filename: 'bundle.min.js', + filename: '[name].[hash].js', publicPath: '/', }, module: { From 03d370b052d0b2ef4b76f04344ce2f68418cf56f Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:55:43 +0900 Subject: [PATCH 121/273] =?UTF-8?q?feat:=20=EC=A7=80=EC=B6=9C=20=EC=95=A1?= =?UTF-8?q?=EC=85=98=20=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20(#230)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 --- client/package-lock.json | 8 +- client/package.json | 2 +- .../DeleteMemberActionModal.style.ts | 3 +- .../PutAndDeleteBillActionModal.tsx | 72 ++++++++++++ .../PutAndDeltetBillActionModal.style.ts | 28 +++++ .../PutAndDeleteBillActionModal/index.ts | 1 + .../src/components/StepList/BillStepItem.tsx | 33 ++++-- client/src/constants/errorMessage.ts | 1 + .../src/hooks/useDynamicBillActionInput.tsx | 6 +- .../hooks/usePutAndDeleteBillAction/index.ts | 1 + .../usePutAndDeleteBillAction.ts | 110 ++++++++++++++++++ client/src/utils/validate/type.ts | 1 + client/src/utils/validate/validatePurchase.ts | 17 ++- 13 files changed, 263 insertions(+), 20 deletions(-) create mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx create mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts create mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts create mode 100644 client/src/hooks/usePutAndDeleteBillAction/index.ts create mode 100644 client/src/hooks/usePutAndDeleteBillAction/usePutAndDeleteBillAction.ts diff --git a/client/package-lock.json b/client/package-lock.json index 67f32bd58..b67e728fc 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", - "haengdong-design": "^0.1.58", + "haengdong-design": "^0.1.60", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -6448,9 +6448,9 @@ "dev": true }, "node_modules/haengdong-design": { - "version": "0.1.58", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.58.tgz", - "integrity": "sha512-eXpjBpFJKwrVjEN6m7GMAQ0qzbc/mgN6/A76Y/Q1oKRMuS48m/EjIqp886AgdoqEz7CwDUtJcDEcf239KYk5JA==", + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.60.tgz", + "integrity": "sha512-XZ8Dtsg9s3WAiQ3XCGNbSjMUOkH0yw1HYvjkmp/BgwErMhwVOH5QlpM9O7jsiSf9p08foS+K2w9Xqtg2pMWZFg==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index 0216028cc..aa612a630 100644 --- a/client/package.json +++ b/client/package.json @@ -45,7 +45,7 @@ }, "dependencies": { "@emotion/react": "^11.11.4", - "haengdong-design": "^0.1.58", + "haengdong-design": "^0.1.60", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts index 48e4c13af..7be2f2141 100644 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts @@ -6,7 +6,7 @@ export const bottomSheetStyle = css({ gap: '1.5rem', width: '100%', height: '100%', - padding: '0 1.5rem', + padding: '0 1rem', }); export const bottomSheetHeaderStyle = css({ @@ -15,6 +15,7 @@ export const bottomSheetHeaderStyle = css({ alignContent: 'center', width: '100%', + padding: '0 0.5rem', }); export const inputGroupStyle = css({ diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx new file mode 100644 index 000000000..52bab8b73 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -0,0 +1,72 @@ +import type {BillAction} from 'types/serviceType'; + +import {BottomSheet, FixedButton, LabelGroupInput, Text} from 'haengdong-design'; + +import validatePurchase from '@utils/validate/validatePurchase'; + +import {usePutAndDeleteBillAction} from '@hooks/usePutAndDeleteBillAction'; + +import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './PutAndDeltetBillActionModal.style'; + +type PutAndDeleteBillActionModalProps = { + billAction: BillAction; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; +}; + +const PutAndDeleteBillActionModal = ({ + billAction, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: PutAndDeleteBillActionModalProps) => { + const {inputPair, handleInputChange, handleOnBlur, errorMessage, errorInfo, canSubmit, onSubmit, onDelete} = + usePutAndDeleteBillAction( + {title: billAction.name, price: String(billAction.price), index: 0}, + validatePurchase, + () => setIsBottomSheetOpened(false), + ); + + return ( + <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> + <form css={bottomSheetStyle} onSubmit={event => onSubmit(event, inputPair, billAction.actionId)}> + <h2 css={bottomSheetHeaderStyle}> + <Text size="bodyBold">지출 내역 수정하기</Text> + </h2> + <fieldset css={inputContainerStyle}> + <LabelGroupInput labelText="지출내역 / 금액" errorText={errorMessage}> + <LabelGroupInput.Element + aria-label="지출 내역" + elementKey={'title'} + type="text" + value={inputPair.title} + onChange={event => handleInputChange('title', event)} + onBlur={handleOnBlur} + isError={errorInfo.title} + placeholder="지출 내역" + /> + <LabelGroupInput.Element + aria-label="금액" + elementKey={'price'} + type="number" + value={inputPair.price} + onChange={event => handleInputChange('price', event)} + onBlur={handleOnBlur} + isError={errorInfo.price} + placeholder="금액" + /> + </LabelGroupInput> + </fieldset> + <FixedButton + type="submit" + variants="primary" + disabled={!canSubmit} + onDeleteClick={() => onDelete(billAction.actionId)} + > + 수정 완료 + </FixedButton> + </form> + </BottomSheet> + ); +}; + +export default PutAndDeleteBillActionModal; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts new file mode 100644 index 000000000..f58f43425 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts @@ -0,0 +1,28 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1rem', +}); + +export const bottomSheetHeaderStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignContent: 'center', + + width: '100%', + padding: '0 0.5rem', +}); + +export const inputContainerStyle = css({ + display: 'flex', + height: '100%', + flexDirection: 'column', + gap: '1.5rem', + overflow: 'auto', + paddingBottom: '14rem', +}); diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts new file mode 100644 index 000000000..c7cbcfcb6 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts @@ -0,0 +1 @@ +export {default as PutAndDeleteBillActionModal} from './PutAndDeleteBillActionModal'; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index c1021ee5b..a386aec30 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -1,6 +1,9 @@ import type {BillStep} from 'types/serviceType'; import {DragHandleItem, DragHandleItemContainer} from 'haengdong-design'; +import {Fragment, useState} from 'react'; + +import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; interface BillStepItemProps { step: BillStep; @@ -9,8 +12,14 @@ interface BillStepItemProps { } const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, setOpenBottomSheet}) => { + const [clickedIndex, setClickedIndex] = useState(-1); const totalPrice = step.actions.reduce((acc, cur) => acc + cur.price, 0); + const handleDragHandleItemClick = (index: number) => { + setClickedIndex(index); + setOpenBottomSheet(true); + }; + return ( <DragHandleItemContainer topLeftText={step.stepName} @@ -19,13 +28,23 @@ const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, set bottomRightText={`${totalPrice.toLocaleString('ko-kr')} 원`} backgroundColor="white" > - {step.actions.map(action => ( - <DragHandleItem - hasDragHandler={true} - prefix={action.name} - suffix={`${action.price.toLocaleString('ko-kr')} 원`} - backgroundColor="lightGrayContainer" - /> + {step.actions.map((action, index) => ( + <Fragment key={action.actionId}> + <DragHandleItem + hasDragHandler={true} + prefix={action.name} + suffix={`${action.price.toLocaleString('ko-kr')} 원`} + backgroundColor="lightGrayContainer" + onClick={() => handleDragHandleItemClick(index)} + /> + {isOpenBottomSheet && clickedIndex === index && ( + <PutAndDeleteBillActionModal + billAction={action} + isBottomSheetOpened={isOpenBottomSheet} + setIsBottomSheetOpened={setOpenBottomSheet} + /> + )} + </Fragment> ))} </DragHandleItemContainer> ); diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index 869359974..08820665d 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -4,6 +4,7 @@ const ERROR_MESSAGE = { memberName: '참여자 이름은 8자 이하의 한글, 영어만 가능해요', purchasePrice: '10,000,000원 이하의 숫자만 입력이 가능해요', purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', + preventEmpty: '값은 비어있을 수 없어요', }; export default ERROR_MESSAGE; diff --git a/client/src/hooks/useDynamicBillActionInput.tsx b/client/src/hooks/useDynamicBillActionInput.tsx index f81e0b114..d07794751 100644 --- a/client/src/hooks/useDynamicBillActionInput.tsx +++ b/client/src/hooks/useDynamicBillActionInput.tsx @@ -3,12 +3,12 @@ import {useEffect, useRef, useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; import {Bill} from 'types/serviceType'; -type InputPair = Omit<Bill, 'price'> & { +export type InputPair = Omit<Bill, 'price'> & { price: string; index: number; }; -type BillInputType = 'title' | 'price'; +export type BillInputType = 'title' | 'price'; // TODO: (@weadie) 지나치게 도메인에 묶여있는 인풋. 절대 다른 페어인풋으로 재사용할 수 없다. const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateResult) => { @@ -33,8 +33,6 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe [field]: value, }); - const {title, price} = targetInputPair; - // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수로 분리 if (isLastInputPairFilled({index, field, value})) { setErrorMessage(''); diff --git a/client/src/hooks/usePutAndDeleteBillAction/index.ts b/client/src/hooks/usePutAndDeleteBillAction/index.ts new file mode 100644 index 000000000..c8c82acf9 --- /dev/null +++ b/client/src/hooks/usePutAndDeleteBillAction/index.ts @@ -0,0 +1 @@ +export {default as usePutAndDeleteBillAction} from './usePutAndDeleteBillAction'; diff --git a/client/src/hooks/usePutAndDeleteBillAction/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction/usePutAndDeleteBillAction.ts new file mode 100644 index 000000000..50052e08d --- /dev/null +++ b/client/src/hooks/usePutAndDeleteBillAction/usePutAndDeleteBillAction.ts @@ -0,0 +1,110 @@ +import type {Bill} from 'types/serviceType'; + +import {useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; +import {requestDeleteBillAction, requestPutBillAction} from '@apis/request/bill'; +import useEventId from '@hooks/useEventId/useEventId'; +import {useStepList} from '@hooks/useStepList/useStepList'; + +import {BillInputType, InputPair} from '@hooks/useDynamicBillActionInput'; + +import ERROR_MESSAGE from '@constants/errorMessage'; + +const usePutAndDeleteBillAction = ( + initialValue: InputPair, + validateFunc: (inputPair: Bill) => ValidateResult, + onClose: () => void, +) => { + const {eventId} = useEventId(); + const {refreshStepList} = useStepList(); + + const [inputPair, setInputPair] = useState<InputPair>(initialValue); + const [canSubmit, setCanSubmit] = useState(false); + const [errorInfo, setErrorInfo] = useState<Record<string, boolean>>({title: false, price: false}); + const [errorMessage, setErrorMessage] = useState<string | undefined>(); + + const handleInputChange = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { + const {value} = event.target; + + // 현재 타겟의 event.target.value를 넣어주기 위해서 + const getFieldValue = (): Bill => { + if (field === 'title') { + return {title: value, price: Number(inputPair.price)}; + } else { + return {title: inputPair.title, price: Number(value)}; + } + }; + + const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue()); + + if (isValid) { + // valid일 경우 에러메시지 nope, setValue, submit은 value가 비지 않았을 때 true를 설정 + setErrorMessage(undefined); + setInputPair(prevInputPair => { + return { + ...prevInputPair, + [field]: value, + }; + }); + setCanSubmit(value.length !== 0); + } else { + // valid하지 않으면 event.target.value 덮어쓰기 + event.target.value = inputPair[field]; + setErrorMessage(errorMessage); + setCanSubmit(false); + } + + if (field === 'title') { + // 현재 field가 title일 때는 title의 errorInfo만 반영해줌 (blur에서도 errorInfo를 조작하기 때문) + setErrorInfo(prev => ({title: errorInfo?.title ?? false, price: prev.price})); + } else { + setErrorInfo(prev => ({title: prev.title, price: errorInfo?.price ?? false})); + } + }; + + const handleOnBlur = () => { + const {isValid, errorMessage, errorInfo} = validateFunc({title: inputPair.title, price: Number(inputPair.price)}); + + // blur시 값이 비었을 때 error state 반영 + if (inputPair.price.length === 0 || inputPair.title.length === 0) { + setErrorMessage(ERROR_MESSAGE.preventEmpty); + setErrorInfo({title: inputPair.title.length === 0, price: inputPair.price.length === 0}); + setCanSubmit(false); + return; + } + + // 이외 blur시에 추가로 검증함 + setErrorMessage(errorMessage); + setCanSubmit(isValid); + setErrorInfo(errorInfo ?? {title: false, price: false}); + }; + + const onSubmit = async (event: React.FormEvent<HTMLFormElement>, inputPair: InputPair, actionId: number) => { + event.preventDefault(); + + const {title, price} = inputPair; + await requestPutBillAction({eventId, actionId, title, price: Number(price)}); + refreshStepList(); + onClose(); + }; + + const onDelete = async (actionId: number) => { + await requestDeleteBillAction({eventId, actionId}); + refreshStepList(); + onClose(); + }; + + return { + inputPair, + handleInputChange, + handleOnBlur, + onSubmit, + onDelete, + canSubmit, + errorMessage, + errorInfo, + }; +}; + +export default usePutAndDeleteBillAction; diff --git a/client/src/utils/validate/type.ts b/client/src/utils/validate/type.ts index 1c994c1f8..ba8b0953b 100644 --- a/client/src/utils/validate/type.ts +++ b/client/src/utils/validate/type.ts @@ -1,4 +1,5 @@ export interface ValidateResult { isValid: boolean; errorMessage?: string; + errorInfo?: Record<string, boolean>; } diff --git a/client/src/utils/validate/validatePurchase.ts b/client/src/utils/validate/validatePurchase.ts index b20742901..7c7a4b3d6 100644 --- a/client/src/utils/validate/validatePurchase.ts +++ b/client/src/utils/validate/validatePurchase.ts @@ -10,27 +10,38 @@ const validatePurchase = (inputPair: Bill): ValidateResult => { const {title, price} = inputPair; let errorMessage; + const errorInfo = { + price: false, + title: false, + }; + const validatePrice = () => { if (price > RULE.maxPrice) { errorMessage = ERROR_MESSAGE.purchasePrice; + errorInfo.price = true; return false; } + + errorInfo.price = false; return true; }; const validateTitle = () => { - if (REGEXP.purchaseTitle.test(title)) { + if (!REGEXP.purchaseTitle.test(title)) { errorMessage = ERROR_MESSAGE.purchaseTitle; + errorInfo.title = true; return false; } + + errorInfo.title = false; return true; }; if (validatePrice() && validateTitle()) { - return {isValid: true}; + return {isValid: true, errorMessage: ''}; } - return {isValid: true, errorMessage: ''}; + return {isValid: false, errorMessage, errorInfo}; }; export default validatePurchase; From 815360127815ffea886da81cb63aa6b902fb0ebc Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:58:16 +0900 Subject: [PATCH 122/273] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20BottomSheet=20=EB=82=B4=EB=B6=80=20?= =?UTF-8?q?=EB=94=94=EC=9E=90=EC=9D=B8=20=ED=8D=BC=EB=B8=94=EB=A6=AC?= =?UTF-8?q?=EC=8B=B1=20(#228)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 --- .../InputAndDeleteButton.style.ts | 9 +++ .../InputAndDeleteButton.tsx | 18 +++++ .../ModalBasedOnMemberCount.tsx | 46 +++++++++++ .../AddBillActionListModalContent.tsx | 6 +- .../AddMemberActionListModalContent.tsx | 6 +- .../SetActionModal/SetActionListModal.tsx | 12 +-- .../SetAllMemberListModal.style.ts | 28 +++++++ .../SetAllMemberListModal.tsx | 48 ++++++++++++ .../SetInitialMemberListModal.tsx | 10 +-- client/src/components/Modal/index.ts | 1 + .../src/components/StepList/BillStepItem.tsx | 3 +- .../components/StepList/MemberStepItem.tsx | 8 +- client/src/components/StepList/Step.tsx | 10 ++- .../EventPage/AdminPage/AdminPage.style.ts | 8 +- .../pages/EventPage/AdminPage/AdminPage.tsx | 77 ++++++++----------- 15 files changed, 218 insertions(+), 72 deletions(-) create mode 100644 client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts create mode 100644 client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx create mode 100644 client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx create mode 100644 client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts create mode 100644 client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx diff --git a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts new file mode 100644 index 000000000..ff9f6cf6e --- /dev/null +++ b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +export const InputAndDeleteButtonContainer = () => + css({ + display: 'flex', + alignItems: 'center', + width: '100%', + gap: '1rem', + }); diff --git a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx new file mode 100644 index 000000000..5ce491099 --- /dev/null +++ b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx @@ -0,0 +1,18 @@ +import {Icon, IconButton, LabelGroupInput} from 'haengdong-design'; + +import {InputAndDeleteButtonContainer} from './InputAndDeleteButton.style'; + +const InputAndDeleteButton = () => { + return ( + <div css={InputAndDeleteButtonContainer}> + <div css={{flexGrow: 1}}> + <LabelGroupInput.Element elementKey="e" /> + </div> + <IconButton variants="tertiary" size="medium"> + <Icon iconType="trash" iconColor="onTertiary" /> + </IconButton> + </div> + ); +}; + +export default InputAndDeleteButton; diff --git a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx new file mode 100644 index 000000000..83e6c58f1 --- /dev/null +++ b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx @@ -0,0 +1,46 @@ +import {SetAllMemberListModal, SetInitialMemberListModal, SetActionListModal} from '@components/Modal/index'; + +interface ModalBasedOnMemberCountProps { + memberNameList: string[]; + isOpenBottomSheet: boolean; + isOpenAllMemberListButton: boolean; + setOrder: React.Dispatch<React.SetStateAction<number>>; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setIsOpenAllMemberListButton: React.Dispatch<React.SetStateAction<boolean>>; +} + +const ModalBasedOnMemberCount = ({ + memberNameList, + isOpenBottomSheet, + isOpenAllMemberListButton, + setOrder, + setIsOpenBottomSheet, + setIsOpenAllMemberListButton, +}: ModalBasedOnMemberCountProps) => { + if (isOpenAllMemberListButton) { + return ( + <SetAllMemberListModal + setIsOpenBottomSheet={setIsOpenBottomSheet} + isOpenBottomSheet={isOpenBottomSheet} + setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} + /> + ); + } + switch (memberNameList.length) { + case 0: + return ( + <SetInitialMemberListModal setIsOpenBottomSheet={setIsOpenBottomSheet} isOpenBottomSheet={isOpenBottomSheet} /> + ); + + default: + return ( + <SetActionListModal + setOrder={setOrder} + setIsOpenBottomSheet={setIsOpenBottomSheet} + isOpenBottomSheet={isOpenBottomSheet} + /> + ); + } +}; + +export default ModalBasedOnMemberCount; diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index 8fac562f5..c59388472 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -8,11 +8,11 @@ import useDynamicBillActionInput from '@hooks/useDynamicBillActionInput'; import style from './AddBillActionListModalContent.style'; interface AddBillActionListModalContentProps { - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; setOrder: React.Dispatch<React.SetStateAction<number>>; } -const AddBillActionListModalContent = ({setOpenBottomSheet, setOrder}: AddBillActionListModalContentProps) => { +const AddBillActionListModalContent = ({setIsOpenBottomSheet, setOrder}: AddBillActionListModalContentProps) => { const { inputPairList, inputRefList, @@ -28,7 +28,7 @@ const AddBillActionListModalContent = ({setOpenBottomSheet, setOrder}: AddBillAc // TODO: (@weadie) 요청 실패시 오류 핸들 필요 addBill(getFilledInputPairList().map(({title, price}) => ({title, price: Number(price)}))); // TODO: (@weadie) DTO같은게 다이내믹에 필요할까? - setOpenBottomSheet(false); + setIsOpenBottomSheet(false); }; return ( diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index aff2764c8..b88befbb5 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -11,10 +11,10 @@ import style from './AddMemberActionListModalContent.style'; interface AddMemberActionListModalContentProps { inOutAction: MemberType; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; } -const AddMemberActionListModalContent = ({inOutAction, setOpenBottomSheet}: AddMemberActionListModalContentProps) => { +const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: AddMemberActionListModalContentProps) => { const { inputList, inputRefList, @@ -30,7 +30,7 @@ const AddMemberActionListModalContent = ({inOutAction, setOpenBottomSheet}: AddM const handleUpdateMemberListSubmit = () => { updateMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); - setOpenBottomSheet(false); + setIsOpenBottomSheet(false); }; return ( diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx index a4c38e6c4..9b4b7facf 100644 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -10,12 +10,12 @@ import style from './SetActionListModal.style'; export type ActionType = '지출' | '인원'; interface SetActionModalContentProps { - openBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; setOrder: React.Dispatch<React.SetStateAction<number>>; } -const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: SetActionModalContentProps) => { +const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet, setOrder}: SetActionModalContentProps) => { const [action, setAction] = useState<ActionType>('지출'); const [inOutAction, setInOutAction] = useState<InOutType>('탈주'); @@ -28,7 +28,7 @@ const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: Set }; return ( - <BottomSheet isOpened={openBottomSheet} onClose={() => setOpenBottomSheet(false)}> + <BottomSheet isOpened={isOpenBottomSheet} onClose={() => setIsOpenBottomSheet(false)}> <div css={style.container}> <div css={style.switchContainer}> <Switch value={action} onChange={handleActionTypeChange} values={['지출', '인원']} /> @@ -38,12 +38,12 @@ const SetActionListModal = ({openBottomSheet, setOpenBottomSheet, setOrder}: Set </div> {action === '지출' && ( - <AddBillActionListModalContent setOpenBottomSheet={setOpenBottomSheet} setOrder={setOrder} /> + <AddBillActionListModalContent setIsOpenBottomSheet={setIsOpenBottomSheet} setOrder={setOrder} /> )} {action === '인원' && ( <AddMemberActionListModalContent inOutAction={inOutAction === '탈주' ? 'OUT' : 'IN'} - setOpenBottomSheet={setOpenBottomSheet} + setIsOpenBottomSheet={setIsOpenBottomSheet} /> )} </div> diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts new file mode 100644 index 000000000..b703e43de --- /dev/null +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts @@ -0,0 +1,28 @@ +import {css} from '@emotion/react'; + +export const allMemberListModalStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + width: '100%', + height: '100%', + }); + +export const allMemberListModalTitleStyle = () => + css({ + display: 'flex', + justifyContent: 'space-between', + width: '100%', + padding: '0 1.5rem', + }); + +export const allMemberListModalLabelGroupInputStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + padding: '0 1rem', + paddingBottom: '10rem', + + overflow: 'auto', + }); diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx new file mode 100644 index 000000000..7eb4ab1fb --- /dev/null +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx @@ -0,0 +1,48 @@ +import {BottomSheet, Text, LabelGroupInput, FixedButton} from 'haengdong-design'; + +import InputAndDeleteButton from '@components/InputAndDeleteButton/InputAndDeleteButton'; + +import { + allMemberListModalLabelGroupInputStyle, + allMemberListModalStyle, + allMemberListModalTitleStyle, +} from './SetAllMemberListModal.style'; + +interface SetAllMemberListModalProps { + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setIsOpenAllMemberListButton: React.Dispatch<React.SetStateAction<boolean>>; +} + +const SetAllMemberListModal = ({ + isOpenBottomSheet, + setIsOpenBottomSheet, + setIsOpenAllMemberListButton, +}: SetAllMemberListModalProps) => { + const handleCloseAllMemberListModal = () => { + setIsOpenAllMemberListButton(prev => !prev); + setIsOpenBottomSheet(false); + }; + + return ( + <BottomSheet isOpened={isOpenBottomSheet} onClose={handleCloseAllMemberListModal}> + <div css={allMemberListModalStyle}> + <div css={allMemberListModalTitleStyle}> + <Text size="bodyBold">전체 참여자 수정하기</Text> + {/* TODO: (@soha): 인원 텍스트 색 수정 필요 */} + <Text size="bodyBold" color="sematic"> + 총 N명 + </Text> + </div> + <div css={allMemberListModalLabelGroupInputStyle}> + <LabelGroupInput labelText="이름"> + <InputAndDeleteButton /> + </LabelGroupInput> + </div> + <FixedButton children="수정 완료" /> + </div> + </BottomSheet> + ); +}; + +export default SetAllMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index d273c5e6a..070ff7cd1 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -11,11 +11,11 @@ import { } from './SetInitialMemberListModal.style'; interface SetInitialMemberListProps { - openBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; } -const SetInitialMemberListModal = ({openBottomSheet, setOpenBottomSheet}: SetInitialMemberListProps) => { +const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetInitialMemberListProps) => { const { inputList, inputRefList, @@ -30,11 +30,11 @@ const SetInitialMemberListModal = ({openBottomSheet, setOpenBottomSheet}: SetIni const handleSubmit = () => { updateMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); - setOpenBottomSheet(false); + setIsOpenBottomSheet(false); }; return ( - <BottomSheet isOpened={openBottomSheet} onClose={() => setOpenBottomSheet(false)}> + <BottomSheet isOpened={isOpenBottomSheet} onClose={() => setIsOpenBottomSheet(false)}> <div css={setInitialMemberListModalStyle}> <Text size="bodyBold">초기 인원 설정하기</Text> <div css={setInitialMemberListModalInputGroupStyle}> diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts index a6e55f84a..7a9d0eaa4 100644 --- a/client/src/components/Modal/index.ts +++ b/client/src/components/Modal/index.ts @@ -1,2 +1,3 @@ export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; +export {default as SetAllMemberListModal} from './SetAllMemberListModal/SetAllMemberListModal'; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index a386aec30..9a0474e5d 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -8,11 +8,12 @@ import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutA interface BillStepItemProps { step: BillStep; isOpenBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; } const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, setOpenBottomSheet}) => { const [clickedIndex, setClickedIndex] = useState(-1); + const totalPrice = step.actions.reduce((acc, cur) => acc + cur.price, 0); const handleDragHandleItemClick = (index: number) => { diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx index 8d93b373d..9a482c665 100644 --- a/client/src/components/StepList/MemberStepItem.tsx +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -7,23 +7,23 @@ import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMe interface MemberStepItemProps { step: MemberStep; isOpenBottomSheet: boolean; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; } -const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, setOpenBottomSheet}) => { +const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { return ( <> <DragHandleItem backgroundColor="white" prefix={`${step.actions.map(({name}) => name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} - onClick={() => setOpenBottomSheet(prev => !prev)} + onClick={() => setIsOpenBottomSheet(prev => !prev)} /> {isOpenBottomSheet && ( <DeleteMemberActionModal memberActionType={step.type} memberActionList={step.actions} isBottomSheetOpened={isOpenBottomSheet} - setIsBottomSheetOpened={setOpenBottomSheet} + setIsBottomSheetOpened={setIsOpenBottomSheet} /> )} </> diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index 859085800..4d0f08903 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -10,12 +10,16 @@ interface StepProps { } const Step = ({step}: StepProps) => { - const [isOpenBottomSheet, setOpenBottomSheet] = useState<boolean>(false); + const [isOpenBottomSheet, setIsOpenBottomSheet] = useState<boolean>(false); if (step.type === 'BILL') { - return <BillStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setOpenBottomSheet={setOpenBottomSheet} />; + return ( + <BillStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setIsOpenBottomSheet={setIsOpenBottomSheet} /> + ); } else if (step.type === 'IN' || step.type === 'OUT') { - return <MemberStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setOpenBottomSheet={setOpenBottomSheet} />; + return ( + <MemberStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setIsOpenBottomSheet={setIsOpenBottomSheet} /> + ); } else { return <></>; } diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts index 2025006d4..6fea4be3b 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts +++ b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -export const ReceiptStyle = () => +export const receiptStyle = () => css({ display: 'flex', flexDirection: 'column', @@ -8,3 +8,9 @@ export const ReceiptStyle = () => padding: '0 8px', paddingBottom: '8.75rem', }); + +export const titleAndListButtonContainerStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + }); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 2c4ccd5a9..0918aa1da 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,52 +1,22 @@ import {useEffect, useState} from 'react'; -import {Title, FixedButton} from 'haengdong-design'; +import {Title, FixedButton, ListButton} from 'haengdong-design'; import StepList from '@components/StepList/StepList'; import {useStepList} from '@hooks/useStepList/useStepList'; import {requestGetEventName} from '@apis/request/event'; import useEventId from '@hooks/useEventId/useEventId'; +import ModalBasedOnMemberCount from '@components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount'; -import {SetActionListModal, SetInitialMemberListModal} from '@components/Modal'; - -import {ReceiptStyle} from './AdminPage.style'; - -interface ModalBasedOnMemberCountProps { - memberNameList: string[]; - openBottomSheet: boolean; - setOrder: React.Dispatch<React.SetStateAction<number>>; - setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -} - -const ModalBasedOnMemberCount = ({ - memberNameList, - openBottomSheet, - setOrder, - setOpenBottomSheet, -}: ModalBasedOnMemberCountProps) => { - switch (memberNameList.length) { - case 0: - return <SetInitialMemberListModal setOpenBottomSheet={setOpenBottomSheet} openBottomSheet={openBottomSheet} />; - - default: - return ( - <SetActionListModal - setOrder={setOrder} - setOpenBottomSheet={setOpenBottomSheet} - openBottomSheet={openBottomSheet} - /> - ); - } -}; +import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; const AdminPage = () => { - const [openBottomSheet, setOpenBottomSheet] = useState(false); + const [isOpenFixedButtonBottomSheet, setIsOpenFixedBottomBottomSheet] = useState(false); const [order, setOrder] = useState<number>(1); + const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); // TODO: (@weadie) eventName이 새로고침시 공간이 없다가 생겨나 레이아웃이 움직이는 문제 const [eventName, setEventName] = useState(' '); - const {getTotalPrice, memberNameList} = useStepList(); - const {eventId} = useEventId(); // TODO: (@weadie) 아래 로직을 훅으로 분리합니다. @@ -62,26 +32,41 @@ const AdminPage = () => { getEventName(); }, [eventId]); + const handleOpenAllMemberListButton = () => { + setIsOpenFixedBottomBottomSheet(prev => !prev); + setIsOpenAllMemberListButton(prev => !prev); + }; + return ( <> - <Title - title={eventName} - description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." - price={getTotalPrice()} - /> - <section css={ReceiptStyle}> + <div css={titleAndListButtonContainerStyle}> + <Title + title={eventName} + description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." + price={getTotalPrice()} + /> + {memberNameList.length !== 0 && ( + <ListButton + prefix="전체 참여자" + suffix={`${memberNameList.length}명`} + onClick={handleOpenAllMemberListButton} + /> + )} + </div> + <section css={receiptStyle}> <StepList /> - {/* TODO: (@soha) 추후 버튼 width 화면에 맞게 수정 */} <FixedButton children={memberNameList.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} - onClick={() => setOpenBottomSheet(prev => !prev)} + onClick={() => setIsOpenFixedBottomBottomSheet(prev => !prev)} /> - {openBottomSheet && ( + {isOpenFixedButtonBottomSheet && ( <ModalBasedOnMemberCount memberNameList={memberNameList} setOrder={setOrder} - setOpenBottomSheet={setOpenBottomSheet} - openBottomSheet={openBottomSheet} + setIsOpenBottomSheet={setIsOpenFixedBottomBottomSheet} + isOpenBottomSheet={isOpenFixedButtonBottomSheet} + isOpenAllMemberListButton={isOpenAllMemberListButton} + setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} /> )} </section> From 5a7374298e8fda315d2b288feabe033c0a69b010 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:59:20 +0900 Subject: [PATCH 123/273] =?UTF-8?q?feat:=20api=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EB=93=B1=EC=9D=98=20=EC=97=90=EB=9F=AC=EB=A5=BC=20=EC=9E=A1?= =?UTF-8?q?=EC=95=84=20=ED=95=B8=EB=93=A4=EB=A7=81=20(#232)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 --- client/package-lock.json | 696 ++++++++++++++++++ client/package.json | 2 + client/public/mockServiceWorker.js | 284 +++++++ client/src/App.tsx | 20 +- client/src/ErrorProvider.tsx | 76 ++ client/src/UnhandledErrorBoundary.tsx | 10 + client/src/apis/fetcher.ts | 62 +- client/src/apis/request/event.ts | 2 +- client/src/apis/useFetch.ts | 33 + client/src/components/Toast/Toast.style.ts | 65 ++ client/src/components/Toast/Toast.tsx | 75 ++ client/src/components/Toast/Toast.type.ts | 22 + client/src/components/Toast/ToastProvider.tsx | 82 +++ client/src/constants/errorMessage.ts | 43 +- client/src/hooks/useEvent.tsx | 15 + client/src/index.tsx | 17 +- client/src/mocks/browser.ts | 5 + client/src/mocks/handlers.ts | 12 + .../CreateEventPage/SetEventNamePage.tsx | 8 +- client/src/pages/ErrorPage/ErrorPage.tsx | 12 + client/src/router.tsx | 5 + client/webpack.config.js | 3 + 22 files changed, 1480 insertions(+), 69 deletions(-) create mode 100644 client/public/mockServiceWorker.js create mode 100644 client/src/ErrorProvider.tsx create mode 100644 client/src/UnhandledErrorBoundary.tsx create mode 100644 client/src/apis/useFetch.ts create mode 100644 client/src/components/Toast/Toast.style.ts create mode 100644 client/src/components/Toast/Toast.tsx create mode 100644 client/src/components/Toast/Toast.type.ts create mode 100644 client/src/components/Toast/ToastProvider.tsx create mode 100644 client/src/hooks/useEvent.tsx create mode 100644 client/src/mocks/browser.ts create mode 100644 client/src/mocks/handlers.ts create mode 100644 client/src/pages/ErrorPage/ErrorPage.tsx diff --git a/client/package-lock.json b/client/package-lock.json index b67e728fc..e7b17303d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -13,6 +13,7 @@ "haengdong-design": "^0.1.60", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-error-boundary": "^4.0.13", "react-router-dom": "^6.24.1" }, "devDependencies": { @@ -38,6 +39,7 @@ "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", "modify-source-webpack-plugin": "^4.1.0", + "msw": "^2.3.5", "prettier": "3.3.2", "ts-loader": "^9.5.1", "typescript": "^5.5.3", @@ -1793,6 +1795,43 @@ "node": ">=6.9.0" } }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz", + "integrity": "sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0" + } + }, + "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "dependencies": { + "statuses": "^2.0.1" + } + }, + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, + "dependencies": { + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -2075,6 +2114,143 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@inquirer/confirm": { + "version": "3.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", + "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", + "dev": true, + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.10.tgz", + "integrity": "sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==", + "dev": true, + "dependencies": { + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "@types/mute-stream": "^0.0.4", + "@types/node": "^22.1.0", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@inquirer/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@inquirer/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", + "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.2.tgz", + "integrity": "sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==", + "dev": true, + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -2232,6 +2408,23 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "dev": true }, + "node_modules/@mswjs/interceptors": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", + "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2267,6 +2460,28 @@ "node": ">= 8" } }, + "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", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -2798,6 +3013,12 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true + }, "node_modules/@types/dotenv-webpack": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", @@ -2898,6 +3119,15 @@ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "22.1.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", @@ -3003,6 +3233,24 @@ "@types/node": "*" } }, + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, "node_modules/@types/ws": { "version": "8.5.12", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", @@ -3518,6 +3766,33 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -4178,6 +4453,111 @@ "node": ">=0.10.0" } }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -6277,6 +6657,15 @@ "node": ">=6.9.0" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -6447,6 +6836,15 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/haengdong-design": { "version": "0.1.60", "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.60.tgz", @@ -6558,6 +6956,12 @@ "he": "bin/he" } }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -7221,6 +7625,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -7976,6 +8386,125 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/msw": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.3.5.tgz", + "integrity": "sha512-+GUI4gX5YC5Bv33epBrD+BGdmDvBg2XGruiWnI3GbIbRmMMBeZ5gs3mJ51OWSGHgJKztZ8AtZeYMMNMVrje2/Q==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@bundled-es-modules/cookie": "^2.0.0", + "@bundled-es-modules/statuses": "^1.0.1", + "@bundled-es-modules/tough-cookie": "^0.1.6", + "@inquirer/confirm": "^3.0.0", + "@mswjs/interceptors": "^0.29.0", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "chalk": "^4.1.2", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.2", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.5.1", + "type-fest": "^4.9.0", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.7.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/msw/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/msw/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/msw/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/msw/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "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", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -7989,6 +8518,15 @@ "multicast-dns": "cli.js" } }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -8275,6 +8813,12 @@ "node": ">= 0.8.0" } }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -8640,6 +9184,12 @@ "node": ">= 0.10" } }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -8664,6 +9214,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -8749,6 +9305,17 @@ "react": "^18.3.1" } }, + "node_modules/react-error-boundary": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", + "integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -8947,6 +9514,15 @@ "strip-ansi": "^6.0.1" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -9565,6 +10141,12 @@ "node": ">= 0.4" } }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10056,6 +10638,30 @@ "node": ">=0.6" } }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/tree-dump": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", @@ -10236,6 +10842,18 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", + "integrity": "sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -10474,6 +11092,16 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -11165,6 +11793,15 @@ } } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", @@ -11178,6 +11815,53 @@ "node": ">= 6" } }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -11189,6 +11873,18 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/client/package.json b/client/package.json index aa612a630..6b1025048 100644 --- a/client/package.json +++ b/client/package.json @@ -35,6 +35,7 @@ "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", "modify-source-webpack-plugin": "^4.1.0", + "msw": "^2.3.5", "prettier": "3.3.2", "ts-loader": "^9.5.1", "typescript": "^5.5.3", @@ -48,6 +49,7 @@ "haengdong-design": "^0.1.60", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-error-boundary": "^4.0.13", "react-router-dom": "^6.24.1" }, "engines": { diff --git a/client/public/mockServiceWorker.js b/client/public/mockServiceWorker.js new file mode 100644 index 000000000..15751fa19 --- /dev/null +++ b/client/public/mockServiceWorker.js @@ -0,0 +1,284 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker. + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const PACKAGE_VERSION = '2.3.5' +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423' +const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') +const activeClientIds = new Set() + +self.addEventListener('install', function () { + self.skipWaiting() +}) + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()) +}) + +self.addEventListener('message', async function (event) { + const clientId = event.source.id + + if (!clientId || !self.clients) { + return + } + + const client = await self.clients.get(clientId) + + if (!client) { + return + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }) + break + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, + }) + break + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId) + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }) + break + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId) + break + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId) + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId + }) + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister() + } + + break + } + } +}) + +self.addEventListener('fetch', function (event) { + const { request } = event + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return + } + + // Generate unique request ID. + const requestId = crypto.randomUUID() + event.respondWith(handleRequest(event, requestId)) +}) + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event) + const response = await getResponse(event, client, requestId) + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + ;(async function () { + const responseClone = response.clone() + + sendToClient( + client, + { + type: 'RESPONSE', + payload: { + requestId, + isMockedResponse: IS_MOCKED_RESPONSE in response, + type: responseClone.type, + status: responseClone.status, + statusText: responseClone.statusText, + body: responseClone.body, + headers: Object.fromEntries(responseClone.headers.entries()), + }, + }, + [responseClone.body], + ) + })() + } + + return response +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId) + + if (client?.frameType === 'top-level') { + return client + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible' + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id) + }) +} + +async function getResponse(event, client, requestId) { + const { request } = event + + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const requestClone = request.clone() + + function passthrough() { + const headers = Object.fromEntries(requestClone.headers.entries()) + + // Remove internal MSW request header so the passthrough request + // complies with any potential CORS preflight checks on the server. + // Some servers forbid unknown request headers. + delete headers['x-msw-intention'] + + return fetch(requestClone, { headers }) + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough() + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough() + } + + // Notify the client that a request has been intercepted. + const requestBuffer = await request.arrayBuffer() + const clientMessage = await sendToClient( + client, + { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + mode: request.mode, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: requestBuffer, + keepalive: request.keepalive, + }, + }, + [requestBuffer], + ) + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.data) + } + + case 'PASSTHROUGH': { + return passthrough() + } + } + + return passthrough() +} + +function sendToClient(client, message, transferrables = []) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel() + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error) + } + + resolve(event.data) + } + + client.postMessage( + message, + [channel.port2].concat(transferrables.filter(Boolean)), + ) + }) +} + +async function respondWithMock(response) { + // Setting response status code to 0 is a no-op. + // However, when responding with a "Response.error()", the produced Response + // instance will have status code set to 0. Since it's not possible to create + // a Response instance with status code 0, handle that use-case separately. + if (response.status === 0) { + return Response.error() + } + + const mockedResponse = new Response(response.body, response) + + Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { + value: true, + enumerable: true, + }) + + return mockedResponse +} diff --git a/client/src/App.tsx b/client/src/App.tsx index 849d78420..64de1e68c 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,16 +1,26 @@ import {Outlet} from 'react-router-dom'; -import {HDesignProvider, ToastProvider} from 'haengdong-design'; +import {HDesignProvider} from 'haengdong-design'; import {Global} from '@emotion/react'; +import {ToastProvider} from '@components/Toast/ToastProvider'; + import {GlobalStyle} from './GlobalStyle'; +// import toast from 'react-simple-toasts'; +import {ErrorProvider} from './ErrorProvider'; +import UnhandledErrorBoundary from './UnhandledErrorBoundary'; const App: React.FC = () => { return ( <HDesignProvider> - <Global styles={GlobalStyle} /> - <ToastProvider> - <Outlet /> - </ToastProvider> + <UnhandledErrorBoundary> + <Global styles={GlobalStyle} /> + <ErrorProvider> + {/* <ErrorProvider callback={toast}> */} + <ToastProvider> + <Outlet /> + </ToastProvider> + </ErrorProvider> + </UnhandledErrorBoundary> </HDesignProvider> ); }; diff --git a/client/src/ErrorProvider.tsx b/client/src/ErrorProvider.tsx new file mode 100644 index 000000000..b63610047 --- /dev/null +++ b/client/src/ErrorProvider.tsx @@ -0,0 +1,76 @@ +import React, {createContext, useState, useContext, useEffect, ReactNode} from 'react'; + +import SERVER_ERROR_MESSAGES, {UNHANDLED_ERROR} from '@constants/errorMessage'; + +// 에러 컨텍스트 생성 +interface ErrorContextType { + hasError: boolean; + errorMessage: string; + setError: (error: ServerError) => void; + clearError: (ms?: number) => void; +} + +const ErrorContext = createContext<ErrorContextType | undefined>(undefined); + +// 에러 컨텍스트를 제공하는 프로바이더 컴포넌트 +interface ErrorProviderProps { + children: ReactNode; + callback?: (message: string) => void; +} + +export type ServerError = { + errorCode: string; + message: string; +}; + +export const ErrorProvider = ({children, callback}: ErrorProviderProps) => { + const [hasError, setHasError] = useState(false); + const [errorMessage, setErrorMessage] = useState(''); + const [error, setErrorState] = useState<ServerError | null>(null); + + useEffect(() => { + if (error) { + if (isUnhandledError(error.errorCode)) { + throw new Error(UNHANDLED_ERROR); + } + + setHasError(true); + const message = SERVER_ERROR_MESSAGES[error.errorCode]; + setErrorMessage(message); + // callback(message); + } + }, [error, callback]); + + const setError = (error: ServerError) => { + setHasError(true); + setErrorMessage(''); + setErrorState(error); + }; + + const clearError = (ms: number = 0) => { + setTimeout(() => { + setHasError(false); + setErrorMessage(''); + setErrorState(null); + }, ms); + }; + + return ( + <ErrorContext.Provider value={{hasError, errorMessage, setError, clearError}}>{children}</ErrorContext.Provider> + ); +}; + +// 에러 컨텍스트를 사용하는 커스텀 훅 +export const useError = (): ErrorContextType => { + const context = useContext(ErrorContext); + if (!context) { + throw new Error('useError must be used within an ErrorProvider'); + } + return context; +}; + +const isUnhandledError = (errorCode: string) => { + if (errorCode === 'INTERNAL_SERVER_ERROR') return true; + + return SERVER_ERROR_MESSAGES[errorCode] === undefined; +}; diff --git a/client/src/UnhandledErrorBoundary.tsx b/client/src/UnhandledErrorBoundary.tsx new file mode 100644 index 000000000..78d017344 --- /dev/null +++ b/client/src/UnhandledErrorBoundary.tsx @@ -0,0 +1,10 @@ +import {StrictPropsWithChildren} from 'haengdong-design/dist/type/strictPropsWithChildren'; +import {ErrorBoundary} from 'react-error-boundary'; + +import ErrorPage from '@pages/ErrorPage/ErrorPage'; + +const UnhandledErrorBoundary = ({children}: StrictPropsWithChildren) => { + return <ErrorBoundary fallback={<ErrorPage />}>{children}</ErrorBoundary>; +}; + +export default UnhandledErrorBoundary; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 4e53c5065..c5eea59e5 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -51,16 +51,11 @@ export const requestPut = ({headers = {}, ...args}: RequestProps) => { return fetcher({method: 'PUT', headers, ...args}); }; -export const requestPost = async <T>({headers = {}, ...args}: RequestProps): Promise<T | undefined> => { +export const requestPost = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { const response = await fetcher({method: 'POST', headers, ...args}); - const contentType = response!.headers.get('Content-Type'); - if (contentType && contentType.includes('application/json')) { - const data: T = await response!.json(); - return data; - } - - return; + const data: T = await response!.json(); + return data; }; export const requestDelete = ({headers = {}, ...args}: RequestProps) => { @@ -87,52 +82,11 @@ const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, query return errorHandler(url, options); }; -// class ErrorWithHeader extends Error { -// header: string; - -// constructor(header: string, message: string) { -// super(message); -// this.name = this.constructor.name; -// this.header = header; -// } -// } - const errorHandler = async (url: string, options: Options) => { - try { - const response = await fetch(url, options); - if (!response.ok) { - const serverErrorMessage = await response.text(); - throw new Error(serverErrorMessage || ''); // 받은 에러 메세지가 없는 경우는 서버에게.. - } - return response; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } - return; + const response = await fetch(url, options); + if (!response.ok) { + const serverErrorMessage = await response.text(); + throw new Error(serverErrorMessage || ''); // 받은 에러 메세지가 없는 경우는 서버에게.. } + return response; }; - -// export const ERROR_MESSAGE = { -// SYSTEM_FAULT: 'system error. 관리자에게 문의하십시오', -// OFFLINE: '네트워크 연결이 끊어졌습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.', -// UNKNOWN: '알 수 없는 에러입니다. 관리자에게 문의해주세요. (연락처...)', -// }; - -// const getErrorMessage = (error: unknown) => { -// return ERROR_MESSAGE.UNKNOWN; - -// if (error instanceof TypeError) return ERROR_MESSAGE.OFFLINE; - -// if (error instanceof Error) { -// const mappedErrorMessage = Object.entries(SERVER_ERROR_MESSAGE).find(([key]) => { -// const upperCaseErrorMessage = convertToUpperCase(error.message.split(SERVER_ERROR_MESSAGE_DIVIDER)[0]); - -// return upperCaseErrorMessage.includes(key); -// })?.[1]; - -// return mappedErrorMessage ?? ERROR_MESSAGE.UNKNOWN; -// } - -// return ERROR_MESSAGE.UNKNOWN; -// }; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index b6eb84b36..0663474b5 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -7,7 +7,7 @@ type RequestPostNewEvent = { password: number; }; -type ResponsePostNewEvent = { +export type ResponsePostNewEvent = { eventId: string; }; diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts new file mode 100644 index 000000000..2a52b583e --- /dev/null +++ b/client/src/apis/useFetch.ts @@ -0,0 +1,33 @@ +import {useState} from 'react'; + +import {UNHANDLED_ERROR} from '@constants/errorMessage'; + +import {ServerError, useError} from '../ErrorProvider'; + +export const useFetch = () => { + const {setError, clearError} = useError(); + const [loading, setLoading] = useState(false); + + const fetch = async <T>(queryFunction: () => Promise<T>): Promise<T> => { + setLoading(true); + clearError(); + + try { + const result = await queryFunction(); + return result; + } catch (error) { + if (error instanceof Error) { + const errorBody: ServerError = await JSON.parse(error.message); + + setError(errorBody); + throw new Error(errorBody.message); + } else { + throw new Error(UNHANDLED_ERROR); + } + } finally { + setLoading(false); + } + }; + + return {loading, fetch}; +}; diff --git a/client/src/components/Toast/Toast.style.ts b/client/src/components/Toast/Toast.style.ts new file mode 100644 index 000000000..a0b5c7cd4 --- /dev/null +++ b/client/src/components/Toast/Toast.style.ts @@ -0,0 +1,65 @@ +import {css, keyframes} from '@emotion/react'; + +import {ToastPosition} from './Toast.type'; + +type ToastMarginStyle = { + position?: ToastPosition; + bottom?: string; + top?: string; +}; + +// 애니메이션 키프레임 정의 +const fadeInWithTransformY = keyframes` + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +`; + +const fadeOutWithTransformY = keyframes` + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(20px); + } +`; + +export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => + css({ + position: 'absolute', + bottom: position === 'bottom' ? `${bottom}` : 'auto', + top: position === 'top' ? `${top}` : 'auto', + left: '50%', + transform: 'translate(-50%)', + + width: '100%', + maxWidth: '48rem', + paddingInline: '1rem', + }); + +export const toastStyle = (isVisible: boolean) => + css({ + width: '100%', + padding: '0.625rem 1rem', + + backgroundColor: 'gray', + boxShadow: '0 0.5rem 0.75rem rgba(0, 0, 0, 0.16);', + + borderRadius: '1.25rem', + + // 애니메이션 추가 + animation: `${isVisible ? fadeInWithTransformY : fadeOutWithTransformY} 0.5s forwards`, + }); + +export const textStyle = css({ + width: '100%', + color: 'white', + whiteSpace: 'pre-line', +}); diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx new file mode 100644 index 000000000..d19b11ca3 --- /dev/null +++ b/client/src/components/Toast/Toast.tsx @@ -0,0 +1,75 @@ +import {createPortal} from 'react-dom'; +import {useState, useEffect} from 'react'; +import {Button, Flex, Icon, Text} from 'haengdong-design'; + +import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; +import {ToastProps, ToastType} from './Toast.type'; + +const renderIcon = (type: ToastType) => { + if (type === 'none') return null; + + return <Icon iconType={type} />; +}; + +const ANIMATION_TIME = 500; + +const Toast = ({ + type = 'confirm', + top = '0px', + bottom = '0px', + isClickToClose = true, + position = 'bottom', + showingTime, + message, + onUndo, + onClose, + ...htmlProps +}: ToastProps) => { + const [isVisible, setIsVisible] = useState(true); + const styleProps = {position, top, bottom}; + + useEffect(() => { + const timer = setTimeout(() => { + setIsVisible(false); + setTimeout(() => { + if (onClose) onClose(); + }, ANIMATION_TIME); // fadeOut 애니메이션 시간과 동일하게 설정 + }, showingTime - ANIMATION_TIME); // 토스트가 내려가는 시간 확보 + + return () => { + clearTimeout(timer); + }; + }, [onClose]); + + const handleClickToClose = () => { + if (!isClickToClose || !onClose) return; + + setIsVisible(false); + setTimeout(() => { + onClose(); + }, ANIMATION_TIME); // fadeOut 애니메이션 시간과 동일하게 설정 + }; + + return createPortal( + <div css={toastMarginStyle({...styleProps})} {...htmlProps} onClick={handleClickToClose}> + <div css={toastStyle(isVisible)}> + <Flex justifyContent="spaceBetween" alignItems="center"> + <Flex alignItems="center" gap="0.5rem"> + {renderIcon(type)} + <Text size="smallBodyBold" css={textStyle}> + {message} + </Text> + </Flex> + {onUndo && ( + <Button variants="tertiary" size="small" onClick={onUndo}> + 되돌리기 + </Button> + )} + </Flex> + </div> + </div>, + document.body, + ); +}; + +export default Toast; diff --git a/client/src/components/Toast/Toast.type.ts b/client/src/components/Toast/Toast.type.ts new file mode 100644 index 000000000..31ec64e3d --- /dev/null +++ b/client/src/components/Toast/Toast.type.ts @@ -0,0 +1,22 @@ +export type ToastPosition = 'bottom' | 'top'; +export type ToastType = 'error' | 'confirm' | 'none'; + +export interface ToastStyleProps { + bottom?: string; + top?: string; +} + +export interface ToastOptionProps { + position?: ToastPosition; + type?: ToastType; + onUndo?: () => void; + isClickToClose?: boolean; + onClose?: () => void; + showingTime: number; +} + +export interface ToastRequiredProps { + message: string; +} + +export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; diff --git a/client/src/components/Toast/ToastProvider.tsx b/client/src/components/Toast/ToastProvider.tsx new file mode 100644 index 000000000..974361dd7 --- /dev/null +++ b/client/src/components/Toast/ToastProvider.tsx @@ -0,0 +1,82 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, useContext, useEffect, useState} from 'react'; + +import SERVER_ERROR_MESSAGES from '@constants/errorMessage'; + +import {useError} from '../../ErrorProvider'; + +import {ToastProps} from './Toast.type'; +import Toast from './Toast'; + +export const ToastContext = createContext<ToastContextProps | null>(null); + +const DEFAULT_TIME = 3000; + +interface ToastContextProps { + showToast: (args: ShowToast) => void; +} + +type ShowToast = ToastProps & { + showingTime?: number; + isAlwaysOn?: boolean; +}; + +const ToastProvider = ({children}: React.PropsWithChildren) => { + const [currentToast, setCurrentToast] = useState<ShowToast | null>(null); + const {hasError, errorMessage, clearError} = useError(); + + const showToast = ({showingTime = DEFAULT_TIME, isAlwaysOn = false, ...toastProps}: ShowToast) => { + setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); + }; + + const closeToast = () => { + setCurrentToast(null); + }; + + useEffect(() => { + if (hasError) { + showToast({ + message: errorMessage || SERVER_ERROR_MESSAGES.UNHANDLED, + showingTime: DEFAULT_TIME, // TODO: (@weadie) 나중에 토스트 프로바이더를 제거한 토스트를 만들 것이기 때문에 많이 리펙터링 안함 + isAlwaysOn: false, + position: 'bottom', + bottom: '6.25rem', + }); + + clearError(DEFAULT_TIME); + } + }, [errorMessage, hasError]); + + useEffect(() => { + if (!currentToast) return; + + if (!currentToast.isAlwaysOn) { + const timer = setTimeout(() => { + setCurrentToast(null); + }, currentToast.showingTime); + + return () => clearTimeout(timer); + } + + return; + }, [currentToast]); + + return ( + <ToastContext.Provider value={{showToast}}> + {currentToast && <Toast onClose={closeToast} {...currentToast} />} + {children} + </ToastContext.Provider> + ); +}; + +const useToast = () => { + const context = useContext(ToastContext); + + if (!context) { + throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); + } + + return context; +}; + +export {ToastProvider, useToast}; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index 08820665d..a5fc21046 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -1,4 +1,41 @@ -const ERROR_MESSAGE = { +type ErrorMessage = Record<string, string>; + +const SERVER_ERROR_MESSAGES: ErrorMessage = { + EVENT_NOT_FOUND: '존재하지 않는 행사입니다.', + EVENT_NAME_LENGTH_INVALID: '행사 이름은 2자 이상 30자 이하만 입력 가능합니다.', + EVENT_NAME_CONSECUTIVE_SPACES: '행사 이름에는 공백 문자가 연속될 수 없습니다.', + EVENT_PASSWORD_FORMAT_INVALID: '비밀번호는 4자리 숫자만 가능합니다.', + + ACTION_NOT_FOUND: '존재하지 않는 액션입니다.', + + MEMBER_NAME_LENGTH_INVALID: '멤버 이름은 1자 이상 4자 이하만 입력 가능합니다.', + MEMBER_NAME_DUPLICATE: '중복된 행사 참여 인원 이름이 존재합니다.', + MEMBER_NOT_EXIST: '현재 참여하고 있지 않은 인원이 존재합니다.', + MEMBER_ALREADY_EXIST: '현재 참여하고 있는 인원이 존재합니다.', + + MEMBER_ACTION_NOT_FOUND: '존재하지 않는 멤버 액션입니다.', + MEMBER_ACTION_STATUS_INVALID: '유효하지 않은 멤버 액션 상태입니다.', + + BILL_ACTION_NOT_FOUND: '존재하지 않는 지출 액션입니다.', + BILL_ACTION_TITLE_INVALID: '앞뒤 공백을 제거한 지출 내역 제목은 %d자 ~ %d자여야 합니다.', + BILL_ACTION_PRICE_INVALID: '지출 금액은 10,000,000 이하의 자연수여야 합니다.', + + REQUEST_EMPTY: '입력 값은 공백일 수 없습니다.', + MESSAGE_NOT_READABLE: '읽을 수 없는 요청입니다.', + NO_RESOURCE_REQUEST: '존재하지 않는 자원입니다.', + + INTERNAL_SERVER_ERROR: '서버 내부에 에러가 발생했습니다.', + + PASSWORD_INVALID: '비밀번호가 일치하지 않습니다.', + TOKEN_NOT_FOUND: '토큰이 존재하지 않습니다.', + TOKEN_EXPIRED: '만료된 토큰입니다.', + TOKEN_INVALID: '유효하지 않은 토큰입니다.', + FORBIDDEN: '접근할 수 없는 행사입니다.', + + UNHANDLED: '알 수 없는 에러입니다.', +}; + +export const ERROR_MESSAGE = { eventName: '행사 이름은 30자 이하만 가능해요', eventPasswordType: '비밀번호는 숫자만 입력이 가능해요', memberName: '참여자 이름은 8자 이하의 한글, 영어만 가능해요', @@ -7,4 +44,6 @@ const ERROR_MESSAGE = { preventEmpty: '값은 비어있을 수 없어요', }; -export default ERROR_MESSAGE; +export const UNHANDLED_ERROR = 'UNHANDLED'; + +export default SERVER_ERROR_MESSAGES; diff --git a/client/src/hooks/useEvent.tsx b/client/src/hooks/useEvent.tsx new file mode 100644 index 000000000..fddbbc073 --- /dev/null +++ b/client/src/hooks/useEvent.tsx @@ -0,0 +1,15 @@ +import {ResponsePostNewEvent, requestPostNewEvent} from '@apis/request/event'; + +import {useFetch} from '@apis/useFetch'; + +const useEvent = () => { + const {fetch} = useFetch(); + + const createNewEvent = async ({eventName}: {eventName: string}) => { + return await fetch<ResponsePostNewEvent>(() => requestPostNewEvent({eventName})); + }; + + return {createNewEvent}; +}; + +export default useEvent; diff --git a/client/src/index.tsx b/client/src/index.tsx index eeffe86f4..47c693d44 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -4,8 +4,15 @@ import {RouterProvider} from 'react-router-dom'; import router from './router'; -ReactDOM.createRoot(document.getElementById('root')!).render( - <React.StrictMode> - <RouterProvider router={router} /> - </React.StrictMode>, -); +async function enableMocking() { + const {worker} = await import('./mocks/browser'); + return worker.start(); +} + +enableMocking().then(() => { + ReactDOM.createRoot(document.getElementById('root')!).render( + <React.StrictMode> + <RouterProvider router={router} /> + </React.StrictMode>, + ); +}); diff --git a/client/src/mocks/browser.ts b/client/src/mocks/browser.ts new file mode 100644 index 000000000..dd8d73b6c --- /dev/null +++ b/client/src/mocks/browser.ts @@ -0,0 +1,5 @@ +import {setupWorker} from 'msw/browser'; + +import {handlers} from './handlers'; + +export const worker = setupWorker(...handlers); diff --git a/client/src/mocks/handlers.ts b/client/src/mocks/handlers.ts new file mode 100644 index 000000000..c5b88a98b --- /dev/null +++ b/client/src/mocks/handlers.ts @@ -0,0 +1,12 @@ +import {http, HttpResponse} from 'msw'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +export const handlers = [ + http.post(`${process.env.API_BASE_URL!}${TEMP_PREFIX}`, ({request}) => { + return HttpResponse.json( + {errorCode: 'ACTION_NOT_FOUND', message: 'msw모킹함수의 에러메세지입니다.'}, + {status: 404}, + ); + }), +]; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index 01f3304b8..0326180eb 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -1,10 +1,11 @@ import {useState} from 'react'; import {useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, LabelInput, Input, Title, TopNav, Back} from 'haengdong-design'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; -import {requestPostNewEvent} from '@apis/request/event'; import validateEventName from '@utils/validate/validateEventName'; +import useEvent from '@hooks/useEvent'; + import {ROUTER_URLS} from '@constants/routerUrls'; const SetEventNamePage = () => { @@ -12,9 +13,11 @@ const SetEventNamePage = () => { const [errorMessage, setErrorMessage] = useState(''); const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); + const {createNewEvent} = useEvent(); const submitEventName = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); + const {eventId} = await createNewEvent({eventName}); navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); }; @@ -33,6 +36,7 @@ const SetEventNamePage = () => { setErrorMessage(validation.errorMessage ?? ''); } }; + return ( <MainLayout> <TopNav> diff --git a/client/src/pages/ErrorPage/ErrorPage.tsx b/client/src/pages/ErrorPage/ErrorPage.tsx new file mode 100644 index 000000000..f71f5da8e --- /dev/null +++ b/client/src/pages/ErrorPage/ErrorPage.tsx @@ -0,0 +1,12 @@ +import {MainLayout, Title} from 'haengdong-design'; + +// TODO: (@weadie) 임시 에러 페이지입니다. +const ErrorPage = () => { + return ( + <MainLayout> + <Title title="알 수 없는 오류입니다." description="오류가 난 상황에 대해 {메일}로 연락주시면 소정의 상품을..." /> + </MainLayout> + ); +}; + +export default ErrorPage; diff --git a/client/src/router.tsx b/client/src/router.tsx index 6daa7d260..6419908aa 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -2,6 +2,7 @@ import {createBrowserRouter} from 'react-router-dom'; import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; +import ErrorPage from '@pages/ErrorPage/ErrorPage'; import SetEventPasswordPage from '@pages/CreateEventPage/SetEventPasswordPage'; import {CompleteCreateEventPage, SetEventNamePage} from '@pages/CreateEventPage'; @@ -42,6 +43,10 @@ const router = createBrowserRouter([ {path: ROUTER_URLS.home, element: <HomePage />}, ], }, + { + path: '*', + element: <ErrorPage />, + }, ], }, ]); diff --git a/client/webpack.config.js b/client/webpack.config.js index 43890bb68..1a32c0ccd 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -67,5 +67,8 @@ export default { port: 3000, hot: true, historyApiFallback: true, + client: { + overlay: false, + }, }, }; From d40e9465d299f7b68715092b7962724dded5aeb4 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:06:39 +0900 Subject: [PATCH 124/273] =?UTF-8?q?chore:=20=EB=B9=8C=EB=93=9C=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=20prod=EC=99=80=20dev=EB=A1=9C=20=EA=B5=AC=EB=B6=84?= =?UTF-8?q?=20(#217)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 --- client/.gitignore | 2 +- client/package-lock.json | 27 +++++++++++---- client/package.json | 8 +++-- .../{webpack.config.js => webpack.common.mjs} | 18 ---------- client/webpack.dev.mjs | 33 +++++++++++++++++++ client/webpack.prod.mjs | 25 ++++++++++++++ 6 files changed, 85 insertions(+), 28 deletions(-) rename client/{webpack.config.js => webpack.common.mjs} (80%) create mode 100644 client/webpack.dev.mjs create mode 100644 client/webpack.prod.mjs diff --git a/client/.gitignore b/client/.gitignore index afd0485d1..2df1bb71c 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -5,7 +5,7 @@ npm-debug.log* node_modules dist -.env +.env.* *storybook.log .DS_Store diff --git a/client/package-lock.json b/client/package-lock.json index e7b17303d..b580a840e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -46,7 +46,8 @@ "typescript-eslint": "^7.16.0", "webpack": "^5.93.0", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.0.4" + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^6.0.1" }, "engines": { "node": ">=20.15.1", @@ -11255,6 +11256,20 @@ } } }, + "node_modules/webpack-cli/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/webpack-dev-middleware": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.3.0.tgz", @@ -11469,17 +11484,17 @@ } }, "node_modules/webpack-merge": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", - "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", "dev": true, "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", - "wildcard": "^2.0.0" + "wildcard": "^2.0.1" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" } }, "node_modules/webpack-sources": { diff --git a/client/package.json b/client/package.json index 6b1025048..27516c179 100644 --- a/client/package.json +++ b/client/package.json @@ -4,8 +4,10 @@ "description": "", "type": "module", "scripts": { - "start": "webpack serve ", - "build": "webpack --mode production", + "prod": "NODE_ENV=production webpack server --open --config webpack.prod.mjs", + "dev": "NODE_ENV=development webpack server --open --config webpack.dev.mjs", + "build": "NODE_ENV=production webpack --config webpack.prod.mjs", + "build-dev": "NODE_ENV=development webpack --config webpack.dev.mjs", "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" }, @@ -56,4 +58,4 @@ "npm": ">=10.7.0", "node": ">=20.15.1" } -} +} \ No newline at end of file diff --git a/client/webpack.config.js b/client/webpack.common.mjs similarity index 80% rename from client/webpack.config.js rename to client/webpack.common.mjs index 1a32c0ccd..fc39ac87b 100644 --- a/client/webpack.config.js +++ b/client/webpack.common.mjs @@ -3,15 +3,11 @@ import HtmlWebpackPlugin from 'html-webpack-plugin'; import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import {ModifySourcePlugin, ConcatOperation} from 'modify-source-webpack-plugin'; import {fileURLToPath} from 'url'; -import Dotenv from 'dotenv-webpack'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -// dotenv.config({path: path.join(__dirname, '.env')}); - export default { - mode: 'development', entry: './src/index.tsx', resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'], @@ -26,11 +22,6 @@ export default { '@utils': path.resolve(__dirname, 'src/utils/'), }, }, - output: { - path: path.join(__dirname, 'dist'), - filename: '[name].[hash].js', - publicPath: '/', - }, module: { rules: [ { @@ -61,14 +52,5 @@ export default { }, ], }), - new Dotenv(), ], - devServer: { - port: 3000, - hot: true, - historyApiFallback: true, - client: { - overlay: false, - }, - }, }; diff --git a/client/webpack.dev.mjs b/client/webpack.dev.mjs new file mode 100644 index 000000000..5ad42ed45 --- /dev/null +++ b/client/webpack.dev.mjs @@ -0,0 +1,33 @@ +import path from 'path'; +import {merge} from 'webpack-merge'; +import Dotenv from 'dotenv-webpack'; +import common from './webpack.common.mjs'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default merge(common, { + mode: 'development', + output: { + filename: '[name].js', + chunkFilename: '[id].chunk.js', + path: path.resolve(__dirname, 'dist'), + clean: true, + publicPath: '/', + }, + devtool: 'eval-source-map', + devServer: { + port: 3000, + historyApiFallback: true, + hot: true, + client: { + overlay: false, + }, + }, + plugins: [ + new Dotenv({ + path: '.env.dev', + }), + ], +}); diff --git a/client/webpack.prod.mjs b/client/webpack.prod.mjs new file mode 100644 index 000000000..5df1f7c4c --- /dev/null +++ b/client/webpack.prod.mjs @@ -0,0 +1,25 @@ +import path from 'path'; +import {merge} from 'webpack-merge'; +import Dotenv from 'dotenv-webpack'; +import common from './webpack.common.mjs'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default merge(common, { + mode: 'production', + output: { + filename: '[name].[hash].js', + chunkFilename: '[id].[hash].chunk.js', + path: path.resolve(__dirname, 'dist'), + clean: true, + publicPath: '/', + }, + devtool: 'source-map', + plugins: [ + new Dotenv({ + path: '.env.prod', + }), + ], +}); From 335b5ded2128eb35c4e19c0fd69e03af65d158b3 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:44:04 +0900 Subject: [PATCH 125/273] =?UTF-8?q?fix:=20merge=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=B4=20=EB=B0=9C=EC=83=9D=ED=95=9C=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20(#246)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 --- client/src/apis/fetcher.ts | 11 +++++++++-- client/src/apis/request/event.ts | 2 +- client/src/components/StepList/BillStepItem.tsx | 6 +++--- client/src/hooks/useEvent.tsx | 6 +++--- client/src/index.tsx | 15 ++++++++------- .../pages/CreateEventPage/SetEventNamePage.tsx | 1 - .../CreateEventPage/SetEventPasswordPage.tsx | 14 +++++--------- 7 files changed, 29 insertions(+), 26 deletions(-) diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index c5eea59e5..2692cc185 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -54,8 +54,13 @@ export const requestPut = ({headers = {}, ...args}: RequestProps) => { export const requestPost = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { const response = await fetcher({method: 'POST', headers, ...args}); - const data: T = await response!.json(); - return data; + const contentType = response!.headers.get('Content-Type'); + if (contentType && contentType.includes('application/json')) { + const data: T = await response!.json(); + return data; + } + + return; }; export const requestDelete = ({headers = {}, ...args}: RequestProps) => { @@ -63,6 +68,8 @@ export const requestDelete = ({headers = {}, ...args}: RequestProps) => { }; const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: FetcherProps) => { + console.log('fetcher'); + console.log(JSON.stringify(body)); // const token = generateBasicToken(USER_ID, USER_PASSWORD); const options = { method, diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index 0663474b5..f9f4d6984 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -2,7 +2,7 @@ import {TEMP_PREFIX} from '@apis/tempPrefix'; import {requestGet, requestPost} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; -type RequestPostNewEvent = { +export type RequestPostNewEvent = { eventName: string; password: number; }; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 9a0474e5d..90d99062a 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -11,14 +11,14 @@ interface BillStepItemProps { setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; } -const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, setOpenBottomSheet}) => { +const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { const [clickedIndex, setClickedIndex] = useState(-1); const totalPrice = step.actions.reduce((acc, cur) => acc + cur.price, 0); const handleDragHandleItemClick = (index: number) => { setClickedIndex(index); - setOpenBottomSheet(true); + setIsOpenBottomSheet(true); }; return ( @@ -42,7 +42,7 @@ const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, set <PutAndDeleteBillActionModal billAction={action} isBottomSheetOpened={isOpenBottomSheet} - setIsBottomSheetOpened={setOpenBottomSheet} + setIsBottomSheetOpened={setIsOpenBottomSheet} /> )} </Fragment> diff --git a/client/src/hooks/useEvent.tsx b/client/src/hooks/useEvent.tsx index fddbbc073..c5cdcf933 100644 --- a/client/src/hooks/useEvent.tsx +++ b/client/src/hooks/useEvent.tsx @@ -1,12 +1,12 @@ -import {ResponsePostNewEvent, requestPostNewEvent} from '@apis/request/event'; +import {RequestPostNewEvent, ResponsePostNewEvent, requestPostNewEvent} from '@apis/request/event'; import {useFetch} from '@apis/useFetch'; const useEvent = () => { const {fetch} = useFetch(); - const createNewEvent = async ({eventName}: {eventName: string}) => { - return await fetch<ResponsePostNewEvent>(() => requestPostNewEvent({eventName})); + const createNewEvent = async ({eventName, password}: RequestPostNewEvent) => { + return await fetch<ResponsePostNewEvent>(() => requestPostNewEvent({eventName, password})); }; return {createNewEvent}; diff --git a/client/src/index.tsx b/client/src/index.tsx index 47c693d44..30d939fee 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -9,10 +9,11 @@ async function enableMocking() { return worker.start(); } -enableMocking().then(() => { - ReactDOM.createRoot(document.getElementById('root')!).render( - <React.StrictMode> - <RouterProvider router={router} /> - </React.StrictMode>, - ); -}); +// MSW 모킹을 사용하려면 아래 주석을 해제하고 save해주세요. +// enableMocking().then(() => { +ReactDOM.createRoot(document.getElementById('root')!).render( + <React.StrictMode> + <RouterProvider router={router} /> + </React.StrictMode>, +); +// }); diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index 0326180eb..ef0417d8a 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -17,7 +17,6 @@ const SetEventNamePage = () => { const submitEventName = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); - const {eventId} = await createNewEvent({eventName}); navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); }; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 682b7eda8..04c8dd760 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -5,6 +5,8 @@ import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdon import validateEventPassword from '@utils/validate/validateEventPassword'; import {requestPostNewEvent} from '@apis/request/event'; +import useEvent from '@hooks/useEvent'; + import RULE from '@constants/rule'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -13,7 +15,7 @@ const SetEventPasswordPage = () => { const [password, setPassword] = useState(''); const [errorMessage, setErrorMessage] = useState(''); const [canSubmit, setCanSubmit] = useState(false); - + const {createNewEvent} = useEvent(); const navigate = useNavigate(); const location = useLocation(); @@ -28,15 +30,9 @@ const SetEventPasswordPage = () => { const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); - const response = await requestPostNewEvent({eventName, password: parseInt(password)}); + const {eventId} = await createNewEvent({eventName, password: parseInt(password)}); - if (response) { - const {eventId} = response; - navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`); - } else { - // TODO: (@weadie) - alert('오류님'); - } + navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`); }; const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { From 81503ccd8ffe7ae21ca6ab6720fb60f71682121c Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:07:36 +0900 Subject: [PATCH 126/273] =?UTF-8?q?fix:=20input=20value=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=9D=B4=20=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20(#253)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- HDesign/package-lock.json | 4 ++-- HDesign/package.json | 2 +- HDesign/src/components/Input/useInput.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index f465f5c3a..15010d3c1 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.60", + "version": "0.1.61", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.60", + "version": "0.1.61", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index 737f07b5b..d58060383 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.60", + "version": "0.1.61", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/Input/useInput.ts b/HDesign/src/components/Input/useInput.ts index 0ff7206c4..f6929897c 100644 --- a/HDesign/src/components/Input/useInput.ts +++ b/HDesign/src/components/Input/useInput.ts @@ -19,7 +19,7 @@ export const useInput = <T>({propsValue, onChange, onBlur, onFocus, inputRef}: U useEffect(() => { setValue(propsValue); - }, [value]); + }, [propsValue]); const handleClickDelete = (event: React.MouseEvent) => { event.preventDefault(); From 2ac2efa5a2e43a5c4040081caeed10e5f10e1a8d Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 8 Aug 2024 19:55:44 +0900 Subject: [PATCH 127/273] =?UTF-8?q?fix:=20useToast=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EB=B0=94=EC=9A=B4=EB=8D=94=EB=A6=AC=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20(#264)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx index 1e3965820..3e68d5b99 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx @@ -1,8 +1,8 @@ import type {MemberAction} from 'types/serviceType'; import {useState} from 'react'; -import {useToast} from 'haengdong-design'; +import {useToast} from '@components/Toast/ToastProvider'; import useEventId from '@hooks/useEventId/useEventId'; import {requestDeleteMemberAction} from '@apis/request/member'; import {useStepList} from '@hooks/useStepList/useStepList'; From b47e080e27ae1585e6d0da48a362383ddbba96b1 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 8 Aug 2024 20:00:13 +0900 Subject: [PATCH 128/273] =?UTF-8?q?fix:=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20Text=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20color=20prop=20=EB=B0=9B=EB=8F=84=EB=A1=9D?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20(#257)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 --- HDesign/package-lock.json | 4 ++-- HDesign/package.json | 2 +- .../DragHandleItem/DragHandleItem.style.ts | 5 ----- .../DragHandleItem/DragHandleItem.tsx | 10 +++------ .../DragHandleItemContainer.style.ts | 22 ------------------- .../DragHandleItemContainer.tsx | 16 +++++--------- .../ExpenseList/ExpenseList.style.ts | 5 ----- .../components/ExpenseList/ExpenseList.tsx | 8 +++---- .../components/ListButton/ListButton.style.ts | 5 ----- .../src/components/ListButton/ListButton.tsx | 6 ++--- HDesign/src/components/Text/Text.style.ts | 8 ++++--- HDesign/src/components/Text/Text.tsx | 7 ++++-- HDesign/src/components/Text/Text.type.ts | 9 ++++++++ .../components/TextButton/TextButton.style.ts | 9 ++------ .../src/components/TextButton/TextButton.tsx | 3 +-- HDesign/src/components/Title/Title.style.ts | 20 ----------------- HDesign/src/components/Title/Title.tsx | 19 +++++----------- 17 files changed, 44 insertions(+), 114 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 15010d3c1..fb66c857d 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.61", + "version": "0.1.63", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.61", + "version": "0.1.63", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index d58060383..821ec31c4 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.61", + "version": "0.1.63", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts index 117ae93c2..c23166272 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts @@ -18,8 +18,3 @@ export const dragHandlerStyle = css({ gap: '0.25rem', width: '100%', }); - -export const textStyle = (theme: Theme) => - css({ - color: theme.colors.black, - }); diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx index 1a2df5471..df6ac2b27 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx @@ -9,7 +9,7 @@ import {useTheme} from '@theme/HDesignProvider'; import IconButton from '../IconButton/IconButton'; -import {dragHandleItemStyle, dragHandlerStyle, textStyle} from './DragHandleItem.style'; +import {dragHandleItemStyle, dragHandlerStyle} from './DragHandleItem.style'; import {DragHandleItemProps} from './DragHandleItem.type'; export const DragHandleItem = ({ @@ -31,12 +31,8 @@ export const DragHandleItem = ({ </IconButton> )} <Flex justifyContent="spaceBetween" width="100%"> - <Text css={textStyle(theme)} size="bodyBold"> - {prefix} - </Text> - <Text css={textStyle(theme)} size="body"> - {suffix} - </Text> + <Text size="bodyBold">{prefix}</Text> + <Text>{suffix}</Text> </Flex> </div> </div> diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts index d1a74247f..0054817fa 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts @@ -13,25 +13,3 @@ export const containerStyle = (theme: Theme, backgroundColor: ColorKeys) => borderRadius: '0.75rem', backgroundColor: theme.colors[backgroundColor], }); - -export const topLeftStyle = (theme: Theme) => - css({ - color: theme.colors.gray, - }); - -//TODO: (@todari) : 추후 클릭 기능을 넣었을 때 underline -export const topRightStyle = (theme: Theme) => - css({ - color: theme.colors.gray, - // textDecoration: 'underline', - }); - -export const bottomLeftTextStyle = (theme: Theme) => - css({ - color: theme.colors.gray, - }); - -export const bottomRightTextStyle = (theme: Theme) => - css({ - color: theme.colors.gray, - }); diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx index b255f3391..c439b98c2 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx @@ -4,13 +4,7 @@ import {useTheme} from '@theme/HDesignProvider'; import Text from '../Text/Text'; import Flex from '../Flex/Flex'; -import { - bottomLeftTextStyle, - bottomRightTextStyle, - containerStyle, - topLeftStyle, - topRightStyle, -} from './DragHandleItemContainer.style'; +import {containerStyle} from './DragHandleItemContainer.style'; import {DragHandleItemContainerProps} from './DragHandleItemContainer.type'; export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ({ @@ -27,19 +21,19 @@ export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ( return ( <div css={containerStyle(theme, backgroundColor)} {...htmlProps}> <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> - <Text css={topLeftStyle(theme)} size="captionBold"> + <Text textColor="gray" size="captionBold"> {topLeftText} </Text> - <Text css={topRightStyle(theme)} size="caption"> + <Text textColor="gray" size="caption"> {topRightText} </Text> </Flex> {children} <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> - <Text css={bottomLeftTextStyle(theme)} size="captionBold"> + <Text textColor="gray" size="captionBold"> {bottomLeftText} </Text> - <Text css={bottomRightTextStyle(theme)} size="caption"> + <Text textColor="gray" size="caption"> {bottomRightText} </Text> </Flex> diff --git a/HDesign/src/components/ExpenseList/ExpenseList.style.ts b/HDesign/src/components/ExpenseList/ExpenseList.style.ts index dd05c067f..8dbd227aa 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.style.ts +++ b/HDesign/src/components/ExpenseList/ExpenseList.style.ts @@ -19,11 +19,6 @@ export const expenseItemLeftStyle = () => gap: '1rem', }); -export const TextStyle = (theme: Theme) => - css({ - color: theme.colors.onTertiary, - }); - export const expenseListStyle = (theme: Theme) => css({ width: '100%', diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx index 3cc5e8354..1f57810e5 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.tsx +++ b/HDesign/src/components/ExpenseList/ExpenseList.tsx @@ -6,7 +6,7 @@ import Icon from '@components/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; -import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle, TextStyle} from './ExpenseList.style'; +import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle} from './ExpenseList.style'; // TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 // TODO: (@todari) : 추후 클릭 시 상호작용이 생기면 iconButton으로 변경할 수 있음 @@ -14,11 +14,9 @@ function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { const {theme} = useTheme(); return ( <button css={expenseItemStyle} {...buttonProps}> - <Text size="bodyBold" css={TextStyle(theme)}> - {name} - </Text> + <Text size="bodyBold">{name}</Text> <div css={expenseItemLeftStyle}> - <Text css={TextStyle(theme)}>{price.toLocaleString('ko-kr')}원</Text> + <Text>{price.toLocaleString('ko-kr')}원</Text> <Icon iconType="rightChevron" /> </div> </button> diff --git a/HDesign/src/components/ListButton/ListButton.style.ts b/HDesign/src/components/ListButton/ListButton.style.ts index ca6a686ff..fcca0ca01 100644 --- a/HDesign/src/components/ListButton/ListButton.style.ts +++ b/HDesign/src/components/ListButton/ListButton.style.ts @@ -14,8 +14,3 @@ export const listButtonStyle = (theme: Theme) => boxShadow: `0 1px 0 0 ${theme.colors.grayContainer} inset `, }); - -export const textStyle = (theme: Theme) => - css({ - color: theme.colors.gray, - }); diff --git a/HDesign/src/components/ListButton/ListButton.tsx b/HDesign/src/components/ListButton/ListButton.tsx index c90bbd122..10c417310 100644 --- a/HDesign/src/components/ListButton/ListButton.tsx +++ b/HDesign/src/components/ListButton/ListButton.tsx @@ -9,7 +9,7 @@ import Icon from '@components/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; import {ListButtonProps} from './ListButton.type'; -import {listButtonStyle, textStyle} from './ListButton.style'; +import {listButtonStyle} from './ListButton.style'; export const ListButton: React.FC<ListButtonProps> = forwardRef<HTMLButtonElement, ListButtonProps>(function Button( {prefix, suffix, ...htmlProps}: ListButtonProps, @@ -18,11 +18,11 @@ export const ListButton: React.FC<ListButtonProps> = forwardRef<HTMLButtonElemen const {theme} = useTheme(); return ( <button css={listButtonStyle(theme)} ref={ref} {...htmlProps}> - <Text size="caption" css={textStyle(theme)}> + <Text size="caption" textColor="gray"> {prefix} </Text> <Flex gap="0.5rem" alignItems="center"> - <Text size="caption" css={textStyle(theme)}> + <Text size="caption" textColor="gray"> {suffix} </Text> <IconButton variants="none"> diff --git a/HDesign/src/components/Text/Text.style.ts b/HDesign/src/components/Text/Text.style.ts index 8767cdb0f..6560c8274 100644 --- a/HDesign/src/components/Text/Text.style.ts +++ b/HDesign/src/components/Text/Text.style.ts @@ -1,11 +1,11 @@ -import type {TextProps} from './Text.type'; +import type {TextStylePropsWithTheme} from './Text.type'; import {css} from '@emotion/react'; // TODO: (@todari) themeProvider 이용하도록 변경 import TYPOGRAPHY from '@token/typography'; -export const getSizeStyling = (size: Required<TextProps>['size']) => { +export const getSizeStyling = ({size, textColor, theme}: Required<TextStylePropsWithTheme>) => { const style = { head: css(TYPOGRAPHY.head), title: css(TYPOGRAPHY.title), @@ -19,5 +19,7 @@ export const getSizeStyling = (size: Required<TextProps>['size']) => { tiny: css(TYPOGRAPHY.tiny), }; - return style[size]; + const colorStyle = css({color: theme.colors[textColor]}); + + return [style[size], colorStyle]; }; diff --git a/HDesign/src/components/Text/Text.tsx b/HDesign/src/components/Text/Text.tsx index e0e2a8ec8..9b7853aa8 100644 --- a/HDesign/src/components/Text/Text.tsx +++ b/HDesign/src/components/Text/Text.tsx @@ -3,11 +3,14 @@ import type {TextProps} from '@components/Text/Text.type'; import React from 'react'; +import {useTheme} from '@theme/HDesignProvider'; + import {getSizeStyling} from './Text.style'; -const Text: React.FC<TextProps> = ({size = 'body', children, ...attributes}: TextProps) => { +const Text: React.FC<TextProps> = ({size = 'body', textColor = 'black', children, ...attributes}: TextProps) => { + const {theme} = useTheme(); return ( - <p css={getSizeStyling(size)} {...attributes}> + <p css={getSizeStyling({size, textColor, theme})} {...attributes}> {children} </p> ); diff --git a/HDesign/src/components/Text/Text.type.ts b/HDesign/src/components/Text/Text.type.ts index db75b09be..157591abf 100644 --- a/HDesign/src/components/Text/Text.type.ts +++ b/HDesign/src/components/Text/Text.type.ts @@ -1,3 +1,7 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + export type TextSize = | 'head' | 'title' @@ -12,6 +16,11 @@ export type TextSize = export interface TextStyleProps { size?: TextSize; + textColor?: ColorKeys; +} + +export interface TextStylePropsWithTheme extends TextStyleProps { + theme: Theme; } export interface TextCustomProps {} diff --git a/HDesign/src/components/TextButton/TextButton.style.ts b/HDesign/src/components/TextButton/TextButton.style.ts index c9ec31a4e..c8d8738fe 100644 --- a/HDesign/src/components/TextButton/TextButton.style.ts +++ b/HDesign/src/components/TextButton/TextButton.style.ts @@ -2,14 +2,9 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; -import {TextColor} from './TextButton.type'; +import {ColorKeys} from '@token/colors'; interface TextButtonStyleProps { - textColor: TextColor; + textColor: ColorKeys; theme: Theme; } - -export const textButtonStyle = ({textColor, theme}: TextButtonStyleProps) => - css({ - color: theme.colors[textColor], - }); diff --git a/HDesign/src/components/TextButton/TextButton.tsx b/HDesign/src/components/TextButton/TextButton.tsx index c211f05e4..9e73667d5 100644 --- a/HDesign/src/components/TextButton/TextButton.tsx +++ b/HDesign/src/components/TextButton/TextButton.tsx @@ -6,7 +6,6 @@ import {useTheme} from '@theme/HDesignProvider'; import Text from '../Text/Text'; import {TextButtonProps} from './TextButton.type'; -import {textButtonStyle} from './TextButton.style'; export const TextButton: React.FC<TextButtonProps> = forwardRef<HTMLButtonElement, TextButtonProps>(function Button( {textColor, textSize, children, ...htmlProps}: TextButtonProps, @@ -16,7 +15,7 @@ export const TextButton: React.FC<TextButtonProps> = forwardRef<HTMLButtonElemen return ( <button ref={ref} {...htmlProps}> - <Text size={textSize} css={textButtonStyle({textColor, theme})}> + <Text size={textSize} textColor={textColor}> {children} </Text> </button> diff --git a/HDesign/src/components/Title/Title.style.ts b/HDesign/src/components/Title/Title.style.ts index 700128c02..ab347a214 100644 --- a/HDesign/src/components/Title/Title.style.ts +++ b/HDesign/src/components/Title/Title.style.ts @@ -12,28 +12,8 @@ export const titleContainerStyle = (theme: Theme) => padding: '1rem', }); -export const titleStyle = (theme: Theme) => - css({ - color: theme.colors.black, - }); - -export const descriptionStyle = (theme: Theme) => - css({ - color: theme.colors.darkGray, - }); - export const priceContainerStyle = css({ display: 'flex', justifyContent: 'space-between', alignItems: 'end', }); - -export const priceTitleStyle = (theme: Theme) => - css({ - color: theme.colors.gray, - }); - -export const priceStyle = (theme: Theme) => - css({ - color: theme.colors.black, - }); diff --git a/HDesign/src/components/Title/Title.tsx b/HDesign/src/components/Title/Title.tsx index ee7847a0e..759588b5e 100644 --- a/HDesign/src/components/Title/Title.tsx +++ b/HDesign/src/components/Title/Title.tsx @@ -1,13 +1,6 @@ /** @jsxImportSource @emotion/react */ import Text from '@components/Text/Text'; -import { - descriptionStyle, - priceContainerStyle, - priceStyle, - priceTitleStyle, - titleContainerStyle, - titleStyle, -} from '@components/Title/Title.style'; +import {priceContainerStyle, titleContainerStyle} from '@components/Title/Title.style'; import {TitleProps} from '@components/Title/Title.type'; import {useTheme} from '@theme/HDesignProvider'; @@ -16,20 +9,18 @@ export const Title: React.FC<TitleProps> = ({title, description, price}: TitlePr const {theme} = useTheme(); return ( <div css={titleContainerStyle(theme)}> - <Text css={titleStyle(theme)} size="subTitle"> - {title} - </Text> + <Text size="subTitle">{title}</Text> {description && ( - <Text css={descriptionStyle(theme)} size="caption"> + <Text textColor="darkGray" size="caption"> {description} </Text> )} {price !== undefined && ( <div css={priceContainerStyle}> - <Text css={priceTitleStyle(theme)} size="caption"> + <Text textColor="gray" size="caption"> 전체 지출 금액 </Text> - <Text css={priceStyle(theme)}>{price.toLocaleString('ko-kr')}원</Text> + <Text>{price.toLocaleString('ko-kr')}원</Text> </div> )} </div> From 66c1d22ec6018ba16903eec05b9b8402f94dc251 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 9 Aug 2024 01:55:28 +0900 Subject: [PATCH 129/273] =?UTF-8?q?fix:=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20Input=20value=20=EB=8F=99?= =?UTF-8?q?=EA=B8=B0=ED=99=94=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#266)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish --- HDesign/package-lock.json | 4 ++-- HDesign/package.json | 2 +- .../src/components/Input/Input.stories.tsx | 22 ++++++++++++++----- HDesign/src/components/Input/Input.tsx | 2 +- HDesign/src/components/Input/useInput.ts | 11 ++++++---- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index fb66c857d..0faaccf1d 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.63", + "version": "0.1.65", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.63", + "version": "0.1.65", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index 821ec31c4..b0ad0c465 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.63", + "version": "0.1.65", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/Input/Input.stories.tsx b/HDesign/src/components/Input/Input.stories.tsx index 31a226771..dc46e022f 100644 --- a/HDesign/src/components/Input/Input.stories.tsx +++ b/HDesign/src/components/Input/Input.stories.tsx @@ -3,6 +3,8 @@ import type {Meta, StoryObj} from '@storybook/react'; import React, {useEffect, useState} from 'react'; import Input from '@components/Input/Input'; +import Flex from '@components/Flex/Flex'; +import Button from '@components/Button/Button'; const meta = { title: 'Components/Input', @@ -26,21 +28,29 @@ type Story = StoryObj<typeof meta>; export const Playground: Story = { render: ({...args}) => { + const regex = /^[ㄱ-ㅎ가-힣]*$/; const [value, setValue] = useState(''); const [isError, setIsError] = useState(false); + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { - if (event.target.value.length < 4) { - setValue(event.target.value); + const newValue = event.target.value; + if (regex.test(newValue)) { + setValue(newValue); setIsError(false); } else { - event.target.value = value; setIsError(true); } }; - const handleBlur = () => { - console.log('blur'); + + const changeRandomValue = () => { + setValue('외부에서 값 변경됨'); }; - return <Input value={value} onChange={e => handleChange(e)} isError={isError} onBlur={handleBlur} {...args} />; + return ( + <div style={{display: 'flex', flexDirection: 'column', gap: '1rem'}}> + <Button onClick={changeRandomValue}>input 값 변경</Button> + <Input value={value} onChange={handleChange} isError={isError} {...args} /> + </div> + ); }, }; diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx index a1b495afd..37945e434 100644 --- a/HDesign/src/components/Input/Input.tsx +++ b/HDesign/src/components/Input/Input.tsx @@ -13,7 +13,6 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro {value: propsValue, onChange, onFocus, onBlur, inputType, isError, placeholder, autoFocus, ...htmlProps}: InputProps, ref, ) { - useImperativeHandle(ref, () => inputRef.current!); const {theme} = useTheme(); const inputRef = useRef<HTMLInputElement>(null); const {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown} = useInput({ @@ -24,6 +23,7 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro inputRef, autoFocus, }); + useImperativeHandle(ref, () => inputRef.current!); return ( <div css={inputBoxStyle(theme, inputType, hasFocus, isError)}> diff --git a/HDesign/src/components/Input/useInput.ts b/HDesign/src/components/Input/useInput.ts index f6929897c..a9e531a07 100644 --- a/HDesign/src/components/Input/useInput.ts +++ b/HDesign/src/components/Input/useInput.ts @@ -9,17 +9,20 @@ interface UseInputProps<T> { autoFocus?: boolean; } -export const useInput = <T>({propsValue, onChange, onBlur, onFocus, inputRef}: UseInputProps<T>) => { +export const useInput = <T>({propsValue, onChange, onBlur, onFocus, autoFocus, inputRef}: UseInputProps<T>) => { const [value, setValue] = useState<T>(propsValue); const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); useEffect(() => { - setHasFocus(inputRef.current === document.activeElement); - }, []); + if (autoFocus && inputRef.current) { + inputRef.current.focus(); + setHasFocus(true); + } + }, [autoFocus, inputRef]); useEffect(() => { setValue(propsValue); - }, [propsValue]); + }, [propsValue, value]); const handleClickDelete = (event: React.MouseEvent) => { event.preventDefault(); From c5eb658e0ffc867c6788b23622dd4cc33e7d6498 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 9 Aug 2024 01:55:59 +0900 Subject: [PATCH 130/273] =?UTF-8?q?fix:=20=ED=96=89=EB=8F=99=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20Search=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B8=B0=EB=8A=A5=20=EC=A0=9C=EA=B1=B0=20(#260)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 --- .../src/components/Search/Search.stories.tsx | 23 +++++------ HDesign/src/components/Search/Search.style.ts | 10 +++-- HDesign/src/components/Search/Search.tsx | 29 ++++++-------- HDesign/src/components/Search/useSearch.ts | 39 ------------------- 4 files changed, 27 insertions(+), 74 deletions(-) delete mode 100644 HDesign/src/components/Search/useSearch.ts diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx index 2ce93f3a5..6b5d821cd 100644 --- a/HDesign/src/components/Search/Search.stories.tsx +++ b/HDesign/src/components/Search/Search.stories.tsx @@ -11,20 +11,17 @@ const meta = { parameters: { // layout: 'centered', }, - argTypes: { - value: { - description: '', - control: {type: 'text'}, - }, - inputType: { - control: {type: 'radio'}, - }, - }, + decorators: [ + Story => ( + <div style={{minHeight: '10rem'}}> + <Story /> + </div> + ), + ], args: { - disabled: false, - placeholder: 'placeholder', - searchTerms: ['todari', 'cookie'], - setState: keyword => console.log(keyword), + isShowTargetInput: true, + matchItems: ['todari', 'cookie'], + onMatchItemClick: keyword => alert(keyword), }, } satisfies Meta<typeof Search>; diff --git a/HDesign/src/components/Search/Search.style.ts b/HDesign/src/components/Search/Search.style.ts index 0c5203aed..d75e8fe25 100644 --- a/HDesign/src/components/Search/Search.style.ts +++ b/HDesign/src/components/Search/Search.style.ts @@ -12,21 +12,23 @@ export const searchTermsStyle = (theme: Theme) => css({ position: 'absolute', top: '3.5rem', + zIndex: 1, - width: 'calc(100% - 2rem)', - margin: '0 1rem', - padding: '0.5rem 0', + width: '100%', + padding: '0.5rem 1rem', borderRadius: '1rem', backgroundColor: theme.colors.white, + + boxShadow: '0 0.25rem 0.5rem 0 rgba(0, 0, 0, 0.12)', }); export const searchTermStyle = (theme: Theme) => css( { width: '100%', - padding: '0.5rem 1rem', + padding: '0.5rem', color: theme.colors.onTertiary, diff --git a/HDesign/src/components/Search/Search.tsx b/HDesign/src/components/Search/Search.tsx index cecdffa52..410a0bc97 100644 --- a/HDesign/src/components/Search/Search.tsx +++ b/HDesign/src/components/Search/Search.tsx @@ -3,34 +3,27 @@ import Flex from '@components/Flex/Flex'; import {useTheme} from '@theme/HDesignProvider'; -import Input from '../Input/Input'; -import {InputProps} from '../Input/Input.type'; - import {searchStyle, searchTermsStyle, searchTermStyle} from './Search.style'; -import useSearch from './useSearch'; -export interface SearchProps extends InputProps { - searchTerms: string[]; - setState: React.Dispatch<React.SetStateAction<string>>; +export interface SearchProps { + isShowTargetInput: boolean; + matchItems: string[]; + onMatchItemClick: (term: string) => void; } -const Search: React.FC<SearchProps> = ({searchTerms, setState, ...inputProps}: SearchProps) => { +const Search = ({isShowTargetInput, matchItems, onMatchItemClick, children}: React.PropsWithChildren<SearchProps>) => { const {theme} = useTheme(); - const {value, showSearchTerms, handleOnChange, handleOnClick, filterSearchTerms} = useSearch({ - searchTerms, - setState, - }); return ( <fieldset css={searchStyle}> - <Input inputType="search" value={value} onChange={handleOnChange} {...inputProps} /> - {showSearchTerms && ( + {children} + {matchItems.length > 0 && isShowTargetInput && ( <ul css={searchTermsStyle(theme)}> <Flex flexDirection="column" gap="0.5rem"> - {filterSearchTerms(value).map((searchTerm, index) => ( - <li key={`${searchTerm}-${index}`}> - <button type="button" css={searchTermStyle(theme)} onClick={() => handleOnClick(searchTerm)}> - {searchTerm} + {matchItems.map((matchItem, index) => ( + <li key={`${matchItems}-${index}`}> + <button type="button" css={searchTermStyle(theme)} onClick={() => onMatchItemClick(matchItem)}> + {matchItems} </button> </li> ))} diff --git a/HDesign/src/components/Search/useSearch.ts b/HDesign/src/components/Search/useSearch.ts deleted file mode 100644 index fbb9cf4c3..000000000 --- a/HDesign/src/components/Search/useSearch.ts +++ /dev/null @@ -1,39 +0,0 @@ -import {useState} from 'react'; - -interface UseSearchProps { - searchTerms: string[]; - setState: React.Dispatch<React.SetStateAction<string>>; -} - -const useSearch = ({searchTerms, setState}: UseSearchProps) => { - const [value, setValue] = useState(''); - const [showSearchTerms, setShowSearchTerms] = useState(false); - - const handleOnClick = (searchTerm: string) => { - setValue(searchTerm); - setState(searchTerm); - setShowSearchTerms(false); - }; - - const handleOnChange = (event: React.ChangeEvent<HTMLInputElement>) => { - const {value} = event.target; - setValue(value); - setShowSearchTerms(value.trim() !== '' && filterSearchTerms(value).length !== 0); - }; - - const filterSearchTerms = (keyword: string) => { - if (keyword.trim() === '') return []; - - return searchTerms.filter(terms => terms.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1); - }; - - return { - value, - showSearchTerms, - handleOnClick, - handleOnChange, - filterSearchTerms, - }; -}; - -export default useSearch; From 255ed4fe5f5c30843426a902e08e4b11d5d52b21 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 9 Aug 2024 01:56:40 +0900 Subject: [PATCH 131/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=99=84=EB=A3=8C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=EC=B9=9C=ED=99=94=EC=A0=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#271)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 --- client/package-lock.json | 36 ++++++++++++++--- client/package.json | 6 ++- .../CompleteCreateEventPage.tsx | 40 +++++++++++++++---- 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index b580a840e..e5fabe2d9 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,8 +10,9 @@ "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", - "haengdong-design": "^0.1.60", + "haengdong-design": "^0.1.65", "react": "^18.3.1", + "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", "react-error-boundary": "^4.0.13", "react-router-dom": "^6.24.1" @@ -4708,6 +4709,14 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, + "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==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/core-js-compat": { "version": "3.38.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", @@ -6847,9 +6856,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.60", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.60.tgz", - "integrity": "sha512-XZ8Dtsg9s3WAiQ3XCGNbSjMUOkH0yw1HYvjkmp/BgwErMhwVOH5QlpM9O7jsiSf9p08foS+K2w9Xqtg2pMWZFg==", + "version": "0.1.65", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.65.tgz", + "integrity": "sha512-zRLb6U2dbN9eBABl9e+7ggSdbAqy/4Bh863BZ0NiLM7ESTktrg8bkJYDUi0j42W4e+1owctA34eNc60FevlKZg==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", @@ -8614,7 +8623,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -9156,7 +9164,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -9294,6 +9301,18 @@ "node": ">=0.10.0" } }, + "node_modules/react-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -10630,6 +10649,11 @@ "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==" + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", diff --git a/client/package.json b/client/package.json index 27516c179..4792f3fef 100644 --- a/client/package.json +++ b/client/package.json @@ -44,12 +44,14 @@ "typescript-eslint": "^7.16.0", "webpack": "^5.93.0", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.0.4" + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^6.0.1" }, "dependencies": { "@emotion/react": "^11.11.4", - "haengdong-design": "^0.1.60", + "haengdong-design": "^0.1.65", "react": "^18.3.1", + "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", "react-error-boundary": "^4.0.13", "react-router-dom": "^6.24.1" diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 0f30c1f04..808bf4319 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -1,20 +1,23 @@ import {useEffect, useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; +import {Button, FixedButton, Input, MainLayout, Text, Title, TopNav} from 'haengdong-design'; +import {CopyToClipboard} from 'react-copy-to-clipboard'; +import {css} from '@emotion/react'; + +import {useToast} from '@components/Toast/ToastProvider'; import {ROUTER_URLS} from '@constants/routerUrls'; const CompleteCreateEventPage = () => { - const [url, setUrl] = useState(''); const navigate = useNavigate(); const location = useLocation(); + const [url, setUrl] = useState(''); useEffect(() => { const getUrl = async () => { // TODO: (@weadie) eventId를 location에서 불러오는 로직 함수로 분리해서 재사용 const params = new URLSearchParams(location.search); const eventId = params.get('eventId'); - // TODO: (@weadie) eventId가 없는 경우에 대한 처리 필요 setUrl(eventId ?? ''); }; @@ -22,14 +25,35 @@ const CompleteCreateEventPage = () => { getUrl(); }, []); + const {showToast} = useToast(); + return ( <MainLayout> <TopNav children={<></>} /> - <Title - title="행사 개시" - description="행사가 성공적으로 개시됐어요 :) 행사 링크를 통해서 참여자 관리가 가능해요. 관리를 위해서 행사 관리 링크를 보관해 - 주세요." - /> + <Title title="행사 개시" description="행사가 성공적으로 개시됐어요 :)" /> + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem', margin: '0 1rem'})}> + <Text textColor="gray">행사 링크를 통해서 지출 내역 공유와 참여자 관리가 가능해요.</Text> + <Text textColor="primary">관리를 위해서 행사 링크를 복사 후 보관해 주세요.</Text> + <Input value={`haengdong.pro${ROUTER_URLS.event}/${url}/home`} disabled /> + + <CopyToClipboard + text={`haengdong.pro${ROUTER_URLS.event}/${url}/home`} + onCopy={() => + showToast({ + showingTime: 3000, + message: '링크가 복사되었어요 :) \n링크를 절대 분실하지 마세요!', + type: 'confirm', + position: 'top', + top: '2rem', + }) + } + > + <Button size="large" variants="tertiary"> + 행사 링크 복사하기 + </Button> + </CopyToClipboard> + </div> + <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${url}/admin`)}>관리 페이지로 이동</FixedButton> </MainLayout> ); From 9968cb88bb1be252744c2b5ec94b9b62bd443d2d Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 9 Aug 2024 01:58:37 +0900 Subject: [PATCH 132/273] =?UTF-8?q?feat:=20=EC=9D=B8=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=EC=A3=BC=20=EC=8B=9C=20=EC=9D=B8=EC=9B=90=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20(#270)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> --- client/package.json | 2 +- client/src/apis/request/member.ts | 13 +++- .../AddMemberActionListModalContent.style.ts | 28 ++++--- .../AddMemberActionListModalContent.tsx | 29 ++------ .../InMember.tsx | 27 +++++++ .../OutMember.tsx | 49 ++++++++++++ client/src/hooks/useDynamicInput.tsx | 26 ++++++- client/src/hooks/useSearchInMemberList.ts | 74 +++++++++++++++++++ 8 files changed, 206 insertions(+), 42 deletions(-) create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx create mode 100644 client/src/hooks/useSearchInMemberList.ts diff --git a/client/package.json b/client/package.json index 4792f3fef..8ed891c0e 100644 --- a/client/package.json +++ b/client/package.json @@ -60,4 +60,4 @@ "npm": ">=10.7.0", "node": ">=20.15.1" } -} \ No newline at end of file +} diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 2552de857..f0e3625a1 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -2,7 +2,7 @@ import type {MemberType} from 'types/serviceType'; import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestPost, requestDelete} from '@apis/fetcher'; +import {requestPost, requestDelete, requestGet} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; type RequestPostMemberList = { @@ -31,3 +31,14 @@ export const requestDeleteMemberAction = async ({eventId, actionId}: WithEventId endpoint: `${TEMP_PREFIX}/${eventId}/member-actions/${actionId}`, }); }; + +export type ResponseGetCurrentInMemberList = { + members: Array<{name: string}>; +}; + +export const requestGetCurrentInMemberList = async (eventId: string) => { + return await requestGet<ResponseGetCurrentInMemberList>({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/current`, + }); +}; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts index 6162d55b5..7fad2e001 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts @@ -1,21 +1,19 @@ import {css} from '@emotion/react'; -const container = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - height: '100%', - }); +const container = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + height: '100%', +}); -const inputGroup = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - overflow: 'auto', - paddingBottom: '14rem', - }); +const inputGroup = css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '14rem', +}); const addMemberActionListModalContentStyle = { container, diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index b88befbb5..8d84993ab 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -8,6 +8,8 @@ import validateMemberName from '@utils/validate/validateMemberName'; import useDynamicInput from '@hooks/useDynamicInput'; import style from './AddMemberActionListModalContent.style'; +import InMember from './InMember'; +import OutMember from './OutMember'; interface AddMemberActionListModalContentProps { inOutAction: MemberType; @@ -15,16 +17,8 @@ interface AddMemberActionListModalContentProps { } const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: AddMemberActionListModalContentProps) => { - const { - inputList, - inputRefList, - handleInputChange, - deleteEmptyInputElementOnBlur, - getFilledInputList, - errorMessage, - canSubmit, - focusNextInputOnEnter, - } = useDynamicInput(validateMemberName); + const dynamicProps = useDynamicInput(validateMemberName); + const {inputList, getFilledInputList, errorMessage, canSubmit} = dynamicProps; const {updateMemberList} = useStepList(); @@ -36,21 +30,8 @@ const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: Ad return ( <div css={style.container}> <div css={style.inputGroup}> - {/* TODO: (@soha) Search로 변경하기 */} <LabelGroupInput labelText="이름" errorText={errorMessage}> - {inputList.map(({value, index}) => ( - <LabelGroupInput.Element - key={`${index}`} - elementKey={`${index}`} - type="text" - value={`${value}`} - ref={el => (inputRefList.current[index] = el)} - onChange={e => handleInputChange(index, e)} - onBlur={() => deleteEmptyInputElementOnBlur()} - onKeyDown={e => focusNextInputOnEnter(e, index)} - placeholder="이름" - /> - ))} + {inOutAction === 'IN' ? <InMember dynamicProps={dynamicProps} /> : <OutMember dynamicProps={dynamicProps} />} </LabelGroupInput> </div> <FixedButton diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx new file mode 100644 index 000000000..23654524a --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx @@ -0,0 +1,27 @@ +import {LabelGroupInput} from 'haengdong-design'; + +import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; + +interface InMemberProps { + dynamicProps: ReturnUseDynamicInput; +} + +const InMember = ({dynamicProps}: InMemberProps) => { + const {inputList, inputRefList, handleInputChange, deleteEmptyInputElementOnBlur, focusNextInputOnEnter} = + dynamicProps; + return inputList.map(({value, index}) => ( + <LabelGroupInput.Element + key={index} + elementKey={`${index}`} + type="text" + value={value} + ref={el => (inputRefList.current[index] = el)} + onChange={e => handleInputChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + placeholder="이름" + /> + )); +}; + +export default InMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx new file mode 100644 index 000000000..fa2ac61d1 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -0,0 +1,49 @@ +import {LabelGroupInput, Search} from 'haengdong-design'; + +import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; +import useSearchInMemberList from '@hooks/useSearchInMemberList'; + +interface OutMemberProps { + dynamicProps: ReturnUseDynamicInput; +} + +const OutMember = ({dynamicProps}: OutMemberProps) => { + const { + inputList, + inputRefList, + deleteEmptyInputElementOnBlur, + focusNextInputOnEnter, + handleInputChange, + setInputValueTargetIndex, + } = dynamicProps; + const {currentInputIndex, filteredInMemberList, handleCurrentInputIndex, searchCurrentInMember, chooseMember} = + useSearchInMemberList(setInputValueTargetIndex); + + const validationAndSearchOnChange = (inputIndex: number, event: React.ChangeEvent<HTMLInputElement>) => { + handleCurrentInputIndex(inputIndex); + handleInputChange(inputIndex, event); + searchCurrentInMember(event); + }; + + return inputList.map(({value, index}) => ( + <Search + isShowTargetInput={currentInputIndex === index} + matchItems={filteredInMemberList} + onMatchItemClick={(term: string) => chooseMember(currentInputIndex, term)} + > + <LabelGroupInput.Element + key={index} + elementKey={`${index}`} + type="text" + value={value} + ref={el => (inputRefList.current[index] = el)} + onChange={e => validationAndSearchOnChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + placeholder="이름" + /> + </Search> + )); +}; + +export default OutMember; diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index 8588c2c40..12fdd4319 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -7,7 +7,19 @@ type InputValue = { index: number; }; -const useDynamicInput = (validateFunc: (name: string) => ValidateResult) => { +export type ReturnUseDynamicInput = { + inputList: InputValue[]; + inputRefList: React.MutableRefObject<(HTMLInputElement | null)[]>; + handleInputChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; + deleteEmptyInputElementOnBlur: () => void; + errorMessage: string; + getFilledInputList: (list?: InputValue[]) => InputValue[]; + focusNextInputOnEnter: (e: React.KeyboardEvent<HTMLInputElement>, index: number) => void; + canSubmit: boolean; + setInputValueTargetIndex: (index: number, value: string) => void; +}; + +const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { const [inputList, setInputList] = useState<InputValue[]>([{value: '', index: 0}]); const inputRefList = useRef<(HTMLInputElement | null)[]>([]); const [errorMessage, setErrorMessage] = useState(''); @@ -98,6 +110,17 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult) => { } }; + const setInputValueTargetIndex = (index: number, value: string) => { + setInputList(prevInputs => { + const updatedInputList = [...prevInputs]; + const targetInput = findInputByIndex(index, updatedInputList); + + targetInput.value = value; + + return updatedInputList; + }); + }; + const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => { if (e.nativeEvent.isComposing) return; @@ -132,6 +155,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult) => { getFilledInputList, focusNextInputOnEnter, canSubmit, + setInputValueTargetIndex, // TODO: (@weadie) 네이밍 수정 }; }; diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts new file mode 100644 index 000000000..bd1fe180e --- /dev/null +++ b/client/src/hooks/useSearchInMemberList.ts @@ -0,0 +1,74 @@ +import {useEffect, useState} from 'react'; + +import {requestGetCurrentInMemberList} from '@apis/request/member'; + +import {useFetch} from '@apis/useFetch'; + +import useEventId from './useEventId/useEventId'; + +export type ReturnUseSearchInMemberList = { + currentInputIndex: number; + handleCurrentInputIndex: (inputIndex: number) => void; + filteredInMemberList: string[]; + searchCurrentInMember: (event: React.ChangeEvent<HTMLInputElement>) => void; + chooseMember: (inputIndex: number, name: string) => void; +}; + +const useSearchInMemberList = ( + setInputValueTargetIndex: (index: number, value: string) => void, +): ReturnUseSearchInMemberList => { + const {eventId} = useEventId(); + + const {fetch} = useFetch(); + const [currentInputIndex, setCurrentInputIndex] = useState(-1); + + // 서버에서 가져온 전체 리스트 + const [currentInMemberList, setCurrentInMemberList] = useState<Array<{name: string}>>([]); + + // 검색된 리스트 (따로 둔 이유는 검색 후 클릭했을 때 리스트를 비워주어야하기 때문) + const [filteredInMemberList, setFilteredInMemberList] = useState<Array<string>>([]); + + useEffect(() => { + if (eventId === '') return; + + const getCurrentInMembers = async () => { + const currentInMemberListFromServer = await fetch(() => requestGetCurrentInMemberList(eventId)); + setCurrentInMemberList(currentInMemberListFromServer.members); + }; + + getCurrentInMembers(); + }, [eventId]); + + const filterMatchItems = (keyword: string) => { + if (keyword.trim() === '') return []; + + const MatchItems = currentInMemberList.map(({name}) => name); + return MatchItems.filter( + matchItem => matchItem.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1, + ).slice(0, 3); + }; + + const chooseMember = (inputIndex: number, name: string) => { + setFilteredInMemberList([]); + setInputValueTargetIndex(inputIndex, name); + }; + + const searchCurrentInMember = (event: React.ChangeEvent<HTMLInputElement>) => { + const {value} = event.target; + setFilteredInMemberList(filterMatchItems(value)); + }; + + const handleCurrentInputIndex = (inputIndex: number) => { + setCurrentInputIndex(inputIndex); + }; + + return { + currentInputIndex, + handleCurrentInputIndex, + filteredInMemberList, + searchCurrentInMember, + chooseMember, + }; +}; + +export default useSearchInMemberList; From 09a204cf4ef3a1dbb41c926343aae984a242c97d Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:01:46 +0900 Subject: [PATCH 133/273] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=ED=95=98=EA=B3=A0=20=EC=B6=9C=EB=A0=A5=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20(#250)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> --- client/src/apis/request/member.ts | 8 +++++++ .../InputAndDeleteButton.tsx | 8 +++++-- .../ModalBasedOnMemberCount.tsx | 7 +++--- .../SetAllMemberListModal.tsx | 8 +++++-- client/src/components/Modal/index.ts | 1 + client/src/hooks/useStepList/useStepList.tsx | 23 +++++++++---------- .../pages/EventPage/AdminPage/AdminPage.tsx | 12 +++++----- 7 files changed, 42 insertions(+), 25 deletions(-) diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index f0e3625a1..cf16894a5 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -32,6 +32,14 @@ export const requestDeleteMemberAction = async ({eventId, actionId}: WithEventId }); }; +type ResponseGetAllMemberList = { + memberNames: string[]; +}; + +export const requestGetAllMemberList = async ({eventId}: WithEventId) => { + return requestGet<ResponseGetAllMemberList>({ + endpoint: `${TEMP_PREFIX}/${eventId}/members`, + export type ResponseGetCurrentInMemberList = { members: Array<{name: string}>; }; diff --git a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx index 5ce491099..20034e394 100644 --- a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx +++ b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx @@ -2,11 +2,15 @@ import {Icon, IconButton, LabelGroupInput} from 'haengdong-design'; import {InputAndDeleteButtonContainer} from './InputAndDeleteButton.style'; -const InputAndDeleteButton = () => { +interface InputDeleteButtonProps { + propsValue: string; +} + +const InputAndDeleteButton = ({propsValue}: InputDeleteButtonProps) => { return ( <div css={InputAndDeleteButtonContainer}> <div css={{flexGrow: 1}}> - <LabelGroupInput.Element elementKey="e" /> + <LabelGroupInput.Element elementKey="e" value={propsValue} /> </div> <IconButton variants="tertiary" size="medium"> <Icon iconType="trash" iconColor="onTertiary" /> diff --git a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx index 83e6c58f1..4799a92c2 100644 --- a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx +++ b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx @@ -1,7 +1,7 @@ import {SetAllMemberListModal, SetInitialMemberListModal, SetActionListModal} from '@components/Modal/index'; interface ModalBasedOnMemberCountProps { - memberNameList: string[]; + allMemberList: string[]; isOpenBottomSheet: boolean; isOpenAllMemberListButton: boolean; setOrder: React.Dispatch<React.SetStateAction<number>>; @@ -10,7 +10,7 @@ interface ModalBasedOnMemberCountProps { } const ModalBasedOnMemberCount = ({ - memberNameList, + allMemberList, isOpenBottomSheet, isOpenAllMemberListButton, setOrder, @@ -20,13 +20,14 @@ const ModalBasedOnMemberCount = ({ if (isOpenAllMemberListButton) { return ( <SetAllMemberListModal + allMemberList={allMemberList} setIsOpenBottomSheet={setIsOpenBottomSheet} isOpenBottomSheet={isOpenBottomSheet} setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} /> ); } - switch (memberNameList.length) { + switch (allMemberList.length) { case 0: return ( <SetInitialMemberListModal setIsOpenBottomSheet={setIsOpenBottomSheet} isOpenBottomSheet={isOpenBottomSheet} /> diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx index 7eb4ab1fb..f1e7c3f37 100644 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx @@ -10,12 +10,14 @@ import { interface SetAllMemberListModalProps { isOpenBottomSheet: boolean; + allMemberList: string[]; setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; setIsOpenAllMemberListButton: React.Dispatch<React.SetStateAction<boolean>>; } const SetAllMemberListModal = ({ isOpenBottomSheet, + allMemberList, setIsOpenBottomSheet, setIsOpenAllMemberListButton, }: SetAllMemberListModalProps) => { @@ -31,12 +33,14 @@ const SetAllMemberListModal = ({ <Text size="bodyBold">전체 참여자 수정하기</Text> {/* TODO: (@soha): 인원 텍스트 색 수정 필요 */} <Text size="bodyBold" color="sematic"> - 총 N명 + 총 {allMemberList.length}명 </Text> </div> <div css={allMemberListModalLabelGroupInputStyle}> <LabelGroupInput labelText="이름"> - <InputAndDeleteButton /> + {allMemberList.map((member, index) => ( + <InputAndDeleteButton key={index} propsValue={member} /> + ))} </LabelGroupInput> </div> <FixedButton children="수정 완료" /> diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts index 7a9d0eaa4..180063b03 100644 --- a/client/src/components/Modal/index.ts +++ b/client/src/components/Modal/index.ts @@ -1,3 +1,4 @@ export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; export {default as SetAllMemberListModal} from './SetAllMemberListModal/SetAllMemberListModal'; +export {default as ModalBasedOnMemberCount} from './ModalBasedOnMemberCount/ModalBasedOnMemberCount'; diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx index f2aa12b66..33d50f243 100644 --- a/client/src/hooks/useStepList/useStepList.tsx +++ b/client/src/hooks/useStepList/useStepList.tsx @@ -4,15 +4,15 @@ import {PropsWithChildren, createContext, useContext, useEffect, useState} from import useEventId from '@hooks/useEventId/useEventId'; import {requestPostBillList} from '@apis/request/bill'; -import {requestPostMemberList} from '@apis/request/member'; +import {requestGetAllMemberList, requestPostMemberList} from '@apis/request/member'; import {requestGetStepList} from '@apis/request/stepList'; interface StepListContextProps { stepList: (BillStep | MemberStep)[]; + allMemberList: string[]; getTotalPrice: () => number; addBill: (billList: Bill[]) => Promise<void>; updateMemberList: ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => Promise<void>; - memberNameList: string[]; refreshStepList: () => Promise<void>; } @@ -20,7 +20,7 @@ export const StepListContext = createContext<StepListContextProps | null>(null); const StepListProvider = ({children}: PropsWithChildren) => { const [stepList, setStepList] = useState<(BillStep | MemberStep)[]>([]); - const [memberNameList, setNameMemberList] = useState<string[]>([]); + const [allMemberList, setAllMemberList] = useState<string[]>([]); const {eventId} = useEventId(); @@ -35,10 +35,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { const refreshStepList = async () => { const stepList = await requestGetStepList({eventId}); - if (stepList.length !== 0) { - setNameMemberList(stepList[stepList.length - 1].members); - } - + getAllMemberList(); setStepList(stepList); }; @@ -46,16 +43,18 @@ const StepListProvider = ({children}: PropsWithChildren) => { try { await requestPostMemberList({eventId, type, memberNameList}); - // TODO: (@weadie) 클라이언트 단에서 멤버 목록을 관리하기 위한 로직. 개선이 필요하다. - if (type === 'IN') setNameMemberList(prev => [...prev, ...memberNameList]); - if (type === 'OUT') setNameMemberList(prev => prev.filter(name => !memberNameList.includes(name))); - refreshStepList(); } catch (error) { alert(error); } }; + const getAllMemberList = async () => { + const allMembers = await requestGetAllMemberList({eventId}); + + setAllMemberList(allMembers.memberNames); + }; + const addBill = async (billList: Bill[]) => { // TODO: (@weadie) 에러 처리 await requestPostBillList({eventId, billList}); @@ -83,7 +82,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { getTotalPrice, updateMemberList, stepList, - memberNameList, + allMemberList, refreshStepList, }} > diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 0918aa1da..d7b7563dc 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -5,7 +5,7 @@ import StepList from '@components/StepList/StepList'; import {useStepList} from '@hooks/useStepList/useStepList'; import {requestGetEventName} from '@apis/request/event'; import useEventId from '@hooks/useEventId/useEventId'; -import ModalBasedOnMemberCount from '@components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount'; +import {ModalBasedOnMemberCount} from '@components/Modal/index'; import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; @@ -16,7 +16,7 @@ const AdminPage = () => { // TODO: (@weadie) eventName이 새로고침시 공간이 없다가 생겨나 레이아웃이 움직이는 문제 const [eventName, setEventName] = useState(' '); - const {getTotalPrice, memberNameList} = useStepList(); + const {getTotalPrice, allMemberList} = useStepList(); const {eventId} = useEventId(); // TODO: (@weadie) 아래 로직을 훅으로 분리합니다. @@ -45,10 +45,10 @@ const AdminPage = () => { description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." price={getTotalPrice()} /> - {memberNameList.length !== 0 && ( + {allMemberList.length !== 0 && ( <ListButton prefix="전체 참여자" - suffix={`${memberNameList.length}명`} + suffix={`${allMemberList.length}명`} onClick={handleOpenAllMemberListButton} /> )} @@ -56,12 +56,12 @@ const AdminPage = () => { <section css={receiptStyle}> <StepList /> <FixedButton - children={memberNameList.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} + children={allMemberList.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} onClick={() => setIsOpenFixedBottomBottomSheet(prev => !prev)} /> {isOpenFixedButtonBottomSheet && ( <ModalBasedOnMemberCount - memberNameList={memberNameList} + allMemberList={allMemberList} setOrder={setOrder} setIsOpenBottomSheet={setIsOpenFixedBottomBottomSheet} isOpenBottomSheet={isOpenFixedButtonBottomSheet} From 03117e81a92fa9b651f7559d2a051e7646f595aa Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:06:33 +0900 Subject: [PATCH 134/273] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EC=82=AD=EC=A0=9C=20(#276)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- client/src/apis/fetcher.ts | 2 - client/src/apis/request/member.ts | 33 ++++- .../InputAndDeleteButton.style.ts | 9 -- .../InputAndDeleteButton.tsx | 22 --- .../SetAllMemberListModal.style.ts | 8 ++ .../SetAllMemberListModal.tsx | 45 ++++++- client/src/components/Toast/ToastProvider.tsx | 2 + client/src/constants/rule.ts | 2 +- client/src/hooks/useSetAllMemberList.tsx | 127 ++++++++++++++++++ .../src/utils/validate/validateMemberName.ts | 2 +- 10 files changed, 208 insertions(+), 44 deletions(-) delete mode 100644 client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts delete mode 100644 client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx create mode 100644 client/src/hooks/useSetAllMemberList.tsx diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 2692cc185..1735386f0 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -68,8 +68,6 @@ export const requestDelete = ({headers = {}, ...args}: RequestProps) => { }; const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: FetcherProps) => { - console.log('fetcher'); - console.log(JSON.stringify(body)); // const token = generateBasicToken(USER_ID, USER_PASSWORD); const options = { method, diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index cf16894a5..4bd6e1833 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -2,7 +2,7 @@ import type {MemberType} from 'types/serviceType'; import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestPost, requestDelete, requestGet} from '@apis/fetcher'; +import {requestPost, requestDelete, requestGet, requestPut} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; type RequestPostMemberList = { @@ -39,14 +39,35 @@ type ResponseGetAllMemberList = { export const requestGetAllMemberList = async ({eventId}: WithEventId) => { return requestGet<ResponseGetAllMemberList>({ endpoint: `${TEMP_PREFIX}/${eventId}/members`, + }); +}; + +export type MemberChange = { + before: string; + after: string; +}; -export type ResponseGetCurrentInMemberList = { - members: Array<{name: string}>; +type RequestPutAllMemberList = { + members: MemberChange[]; }; -export const requestGetCurrentInMemberList = async (eventId: string) => { - return await requestGet<ResponseGetCurrentInMemberList>({ +export const requestPutAllMemberList = async ({eventId, members}: WithEventId<RequestPutAllMemberList>) => { + await requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/nameChange`, + body: { + members, + }, + }); +}; + +type RequestDeleteAllMemberList = { + memberName: string; +}; + +export const requestDeleteAllMemberList = async ({eventId, memberName}: WithEventId<RequestDeleteAllMemberList>) => { + await requestDelete({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/members/current`, + endpoint: `${TEMP_PREFIX}/${eventId}/members/${memberName}`, }); }; diff --git a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts deleted file mode 100644 index ff9f6cf6e..000000000 --- a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.style.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {css} from '@emotion/react'; - -export const InputAndDeleteButtonContainer = () => - css({ - display: 'flex', - alignItems: 'center', - width: '100%', - gap: '1rem', - }); diff --git a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx b/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx deleted file mode 100644 index 20034e394..000000000 --- a/client/src/components/InputAndDeleteButton/InputAndDeleteButton.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import {Icon, IconButton, LabelGroupInput} from 'haengdong-design'; - -import {InputAndDeleteButtonContainer} from './InputAndDeleteButton.style'; - -interface InputDeleteButtonProps { - propsValue: string; -} - -const InputAndDeleteButton = ({propsValue}: InputDeleteButtonProps) => { - return ( - <div css={InputAndDeleteButtonContainer}> - <div css={{flexGrow: 1}}> - <LabelGroupInput.Element elementKey="e" value={propsValue} /> - </div> - <IconButton variants="tertiary" size="medium"> - <Icon iconType="trash" iconColor="onTertiary" /> - </IconButton> - </div> - ); -}; - -export default InputAndDeleteButton; diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts index b703e43de..f54166c08 100644 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts @@ -26,3 +26,11 @@ export const allMemberListModalLabelGroupInputStyle = () => overflow: 'auto', }); + +export const InputAndDeleteButtonContainer = () => + css({ + display: 'flex', + alignItems: 'center', + width: '100%', + gap: '1rem', + }); diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx index f1e7c3f37..d09327ccc 100644 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx @@ -1,11 +1,14 @@ -import {BottomSheet, Text, LabelGroupInput, FixedButton} from 'haengdong-design'; +import {BottomSheet, Text, LabelGroupInput, FixedButton, IconButton, Icon} from 'haengdong-design'; -import InputAndDeleteButton from '@components/InputAndDeleteButton/InputAndDeleteButton'; +import validateMemberName from '@utils/validate/validateMemberName'; + +import useSetAllMemberList from '@hooks/useSetAllMemberList'; import { allMemberListModalLabelGroupInputStyle, allMemberListModalStyle, allMemberListModalTitleStyle, + InputAndDeleteButtonContainer, } from './SetAllMemberListModal.style'; interface SetAllMemberListModalProps { @@ -26,24 +29,60 @@ const SetAllMemberListModal = ({ setIsOpenBottomSheet(false); }; + const { + editedAllMemberList, + canSubmit, + errorMessage, + errorIndexList, + handleNameChange, + handleClickDeleteButton, + handlePutAllMemberList, + } = useSetAllMemberList({ + validateFunc: validateMemberName, + allMemberList, + handleCloseAllMemberListModal, + }); + return ( <BottomSheet isOpened={isOpenBottomSheet} onClose={handleCloseAllMemberListModal}> <div css={allMemberListModalStyle}> <div css={allMemberListModalTitleStyle}> <Text size="bodyBold">전체 참여자 수정하기</Text> {/* TODO: (@soha): 인원 텍스트 색 수정 필요 */} +<<<<<<< HEAD + <Text size="bodyBold" textColor="gray"> +======= <Text size="bodyBold" color="sematic"> +>>>>>>> fe-dev 총 {allMemberList.length}명 </Text> </div> <div css={allMemberListModalLabelGroupInputStyle}> +<<<<<<< HEAD + <LabelGroupInput labelText="이름" errorText={errorMessage}> + {editedAllMemberList.map((member, index) => ( + <div css={InputAndDeleteButtonContainer} key={index}> + <div css={{flexGrow: 1}}> + <LabelGroupInput.Element + elementKey="e" + value={member} + isError={errorIndexList.includes(index)} + onChange={e => handleNameChange(index, e)} + /> + </div> + <IconButton variants="tertiary" size="medium" onClick={() => handleClickDeleteButton(index)}> + <Icon iconType="trash" iconColor="onTertiary" /> + </IconButton> + </div> +======= <LabelGroupInput labelText="이름"> {allMemberList.map((member, index) => ( <InputAndDeleteButton key={index} propsValue={member} /> +>>>>>>> fe-dev ))} </LabelGroupInput> </div> - <FixedButton children="수정 완료" /> + <FixedButton children="수정 완료" disabled={!canSubmit} onClick={handlePutAllMemberList} /> </div> </BottomSheet> ); diff --git a/client/src/components/Toast/ToastProvider.tsx b/client/src/components/Toast/ToastProvider.tsx index 974361dd7..3107e37ac 100644 --- a/client/src/components/Toast/ToastProvider.tsx +++ b/client/src/components/Toast/ToastProvider.tsx @@ -41,6 +41,8 @@ const ToastProvider = ({children}: React.PropsWithChildren) => { isAlwaysOn: false, position: 'bottom', bottom: '6.25rem', + // TODO: (@soha&weadie) zIndex의 값 추후에 꼭!!! 수정 + style: {zIndex: '1000'}, }); clearError(DEFAULT_TIME); diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts index d6d53cd55..4b78031b9 100644 --- a/client/src/constants/rule.ts +++ b/client/src/constants/rule.ts @@ -1,7 +1,7 @@ const RULE = { maxEventNameLength: 30, maxEventPasswordLength: 4, - maxMemberNameLength: 8, + maxMemberNameLength: 4, maxPrice: 10000000, }; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx new file mode 100644 index 000000000..51d50fa53 --- /dev/null +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -0,0 +1,127 @@ +import {useEffect, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; +import {MemberChange, requestDeleteAllMemberList, requestPutAllMemberList} from '@apis/request/member'; + +import {useFetch} from '@apis/useFetch'; + +import useEventId from './useEventId/useEventId'; +import {useStepList} from './useStepList/useStepList'; + +interface UseSetAllMemberListProps { + validateFunc: (name: string) => ValidateResult; + allMemberList: string[]; + handleCloseAllMemberListModal: () => void; +} + +const useSetAllMemberList = ({ + validateFunc, + allMemberList, + handleCloseAllMemberListModal, +}: UseSetAllMemberListProps) => { + const [editedAllMemberList, setEditedAllMemberList] = useState<string[]>(allMemberList); + const [errorMessage, setErrorMessage] = useState(''); + const [errorIndexList, setErrorIndexList] = useState<number[]>([]); + const [canSubmit, setCanSubmit] = useState(false); + + const {refreshStepList} = useStepList(); + const {eventId} = useEventId(); + const {fetch} = useFetch(); + + useEffect(() => { + if (arraysEqual(editedAllMemberList, allMemberList)) { + setCanSubmit(false); + } else { + setCanSubmit(true); + } + }, [editedAllMemberList]); + + const arraysEqual = (arr1: string[], arr2: string[]) => { + if (arr1.length !== arr2.length) return false; + for (let i = 0; i < arr1.length; i++) { + if (arr1[i] !== arr2[i]) return false; + } + return true; + }; + + const handleNameChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { + const {value} = event.target; + const {isValid, errorMessage: validationResultMessage} = validateFunc(value); + + if (isValid && value.length !== 0) { + setErrorMessage(''); + + setEditedAllMemberList(prev => { + const newList = [...prev]; + newList[index] = value; + return newList; + }); + + setErrorIndexList(prev => prev.filter(i => i !== index)); + + setCanSubmit(true); + } else if (value.length === 0) { + setErrorMessage(''); + + setEditedAllMemberList(prev => { + const newList = [...prev]; + newList[index] = value; + return newList; + }); + + changeErrorIndex(index); + } else { + setErrorMessage(validationResultMessage ?? ''); + + changeErrorIndex(index); + } + }; + + const handleClickDeleteButton = async (index: number) => { + const memberToDelete = editedAllMemberList[index]; + + await fetch(() => requestDeleteAllMemberList({eventId, memberName: memberToDelete})); + + setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + + refreshStepList(); + }; + + const handlePutAllMemberList = async () => { + const editedMemberName: MemberChange[] = allMemberList + .map((originalName, index) => { + if (editedAllMemberList[index] !== originalName) { + return {before: originalName, after: editedAllMemberList[index]}; + } + return null; // 조건에 맞지 않으면 null을 반환 + }) + .filter(item => item !== null); // null인 항목을 필터링하여 제거 + + await fetch(() => requestPutAllMemberList({eventId, members: editedMemberName})); + + refreshStepList(); + + handleCloseAllMemberListModal(); + }; + + const changeErrorIndex = (index: number) => { + setErrorIndexList(prev => { + if (!prev.includes(index)) { + return [...prev, index]; + } + return prev; + }); + }; + + return { + editedAllMemberList, + canSubmit, + errorMessage, + errorIndexList, + handleNameChange, + handleClickDeleteButton, + handlePutAllMemberList, + }; +}; + +export default useSetAllMemberList; diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts index 0e7483358..06c7416dd 100644 --- a/client/src/utils/validate/validateMemberName.ts +++ b/client/src/utils/validate/validateMemberName.ts @@ -1,5 +1,5 @@ import REGEXP from '@constants/regExp'; -import ERROR_MESSAGE from '@constants/errorMessage'; +import {ERROR_MESSAGE} from '@constants/errorMessage'; import RULE from '@constants/rule'; import {ValidateResult} from './type'; From cd6e6c8d651093922cde968500c7edcfed8f77b9 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 9 Aug 2024 02:08:06 +0900 Subject: [PATCH 135/273] =?UTF-8?q?feat:=20sentry=20=EC=A0=81=EC=9A=A9=20(?= =?UTF-8?q?#262)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> --- client/.gitignore | 3 + client/package-lock.json | 484 +++++++++++++++++++ client/package.json | 2 + client/public/mockServiceWorker.js | 151 +++--- client/src/ErrorProvider.tsx | 7 +- client/src/apis/fetcher.ts | 61 ++- client/src/apis/useFetch.ts | 63 ++- client/src/constants/errorMessage.ts | 2 +- client/src/errors/FetchError.ts | 23 + client/src/hooks/useStepList/useStepList.tsx | 9 +- client/src/index.tsx | 21 +- client/src/types/fetchErrorType.ts | 11 + client/src/utils/sendLogToSentry.ts | 56 +++ client/tsconfig.json | 3 +- client/webpack.common.mjs | 1 + client/webpack.dev.mjs | 8 +- client/webpack.prod.mjs | 6 + 17 files changed, 800 insertions(+), 111 deletions(-) create mode 100644 client/src/errors/FetchError.ts create mode 100644 client/src/types/fetchErrorType.ts create mode 100644 client/src/utils/sendLogToSentry.ts diff --git a/client/.gitignore b/client/.gitignore index 2df1bb71c..cf03bec6b 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -9,3 +9,6 @@ dist *storybook.log .DS_Store + +# Sentry Config File +.env.sentry-build-plugin diff --git a/client/package-lock.json b/client/package-lock.json index e5fabe2d9..e041d7df0 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", + "@sentry/react": "^8.24.0", "haengdong-design": "^0.1.65", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", @@ -20,6 +21,7 @@ "devDependencies": { "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", + "@sentry/webpack-plugin": "^2.22.0", "@svgr/webpack": "^8.1.0", "@types/dotenv-webpack": "^7.0.7", "@types/react": "^18.3.3", @@ -2514,6 +2516,370 @@ "node": ">=14.0.0" } }, + "node_modules/@sentry-internal/browser-utils": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.24.0.tgz", + "integrity": "sha512-U5dVZ4JM+UeN3YWBUHZcNLF038C3ccTTsTICIw+zfCQbpPhPms8DOEDVpd0So18XoNDzYmLo07hC1BwByRAfGw==", + "dependencies": { + "@sentry/core": "8.24.0", + "@sentry/types": "8.24.0", + "@sentry/utils": "8.24.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.24.0.tgz", + "integrity": "sha512-0tWRp8SOSTSPTViRJnB6+HHixFgkEWjKPciuLsAZkobRhi+VVedPj3zVztORy5AvARGr6AgyVSdnviilcrKl6g==", + "dependencies": { + "@sentry/core": "8.24.0", + "@sentry/types": "8.24.0", + "@sentry/utils": "8.24.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.24.0.tgz", + "integrity": "sha512-+3d+3Ln7iDOZo2wOBv7EWojVHigEskjKsz8vR3WFdxYyue8e3zPQ/xg/t9A6BtEVRPQsEyhM3oN6LyjqFv2nfg==", + "dependencies": { + "@sentry-internal/browser-utils": "8.24.0", + "@sentry/core": "8.24.0", + "@sentry/types": "8.24.0", + "@sentry/utils": "8.24.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.24.0.tgz", + "integrity": "sha512-MI+j9tUab1d5oer2xKQ2lxdXSzBeZ1DF2dwlVxQDOfSAQqRfZJpmLcmSPb6M+GJsf2xHg6n4dAQvWQuM0qGQPQ==", + "dependencies": { + "@sentry-internal/replay": "8.24.0", + "@sentry/core": "8.24.0", + "@sentry/types": "8.24.0", + "@sentry/utils": "8.24.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", + "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.24.0.tgz", + "integrity": "sha512-WdCLUoMAE0ZWsZDb3G/FQI5YgkH59VVEpnPqrWI08m2KuqLz8eU724JZvNzaDv/L2yzksgS4HDDUXkNRzDeCrQ==", + "dependencies": { + "@sentry-internal/browser-utils": "8.24.0", + "@sentry-internal/feedback": "8.24.0", + "@sentry-internal/replay": "8.24.0", + "@sentry-internal/replay-canvas": "8.24.0", + "@sentry/core": "8.24.0", + "@sentry/types": "8.24.0", + "@sentry/utils": "8.24.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", + "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "2.22.0", + "@sentry/cli": "^2.33.1", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/cli": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.24.0.tgz", + "integrity": "sha512-nyy7po78Ef5KNzehHJCCyLGGR/FceHyw2IRzDQUVD6M4tos8G1OML1gcnALChWhyeq1SIoDsC1ofxFlbkIWuog==", + "dependencies": { + "@sentry/types": "8.24.0", + "@sentry/utils": "8.24.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/react": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.24.0.tgz", + "integrity": "sha512-UaNmGEtYUFMoE1lKlsedOYGvQX72/A+/CiDg5umQwwS33XfGY4geh3zMo3jjEKTjhR1T5gofBz74sXnTCyrW4A==", + "dependencies": { + "@sentry/browser": "8.24.0", + "@sentry/core": "8.24.0", + "@sentry/types": "8.24.0", + "@sentry/utils": "8.24.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/types": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.24.0.tgz", + "integrity": "sha512-5QWXARoFrvTvnS19ip+ha0x4nWIv/RvoCTnqCsgrNTjypbk1+KMSMQQhGMo8OuEBFhdGyTs1BqfxVV82URHh3w==", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/utils": { + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.24.0.tgz", + "integrity": "sha512-AGo5PldxCJYn3g0IYXeBkeALNa+NieJaaCDpYyzrKAFdxoA6Qp+Z/wmN9m5BYZ9eHx9N+xMOoz2aIh4hG48VbQ==", + "dependencies": { + "@sentry/types": "8.24.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/webpack-plugin": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", + "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "dev": true, + "dependencies": { + "@sentry/bundler-plugin-core": "2.22.0", + "unplugin": "1.0.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "webpack": ">=4.40.0" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@storybook/addon-webpack5-compiler-swc": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", @@ -3704,6 +4070,18 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -6610,6 +6988,12 @@ "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", "dev": true }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -7241,6 +7625,19 @@ } } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -8175,6 +8572,18 @@ "yallist": "^3.0.2" } }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -8573,6 +8982,26 @@ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -9160,6 +9589,15 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -9192,6 +9630,12 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -10687,6 +11131,12 @@ "node": ">= 4.0.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "node_modules/tree-dump": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", @@ -11079,6 +11529,18 @@ "node": ">= 0.8" } }, + "node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "dev": true, + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", @@ -11188,6 +11650,12 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, "node_modules/webpack": { "version": "5.93.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", @@ -11530,6 +11998,12 @@ "node": ">=10.13.0" } }, + "node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "dev": true + }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -11575,6 +12049,16 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/client/package.json b/client/package.json index 8ed891c0e..739d0df4c 100644 --- a/client/package.json +++ b/client/package.json @@ -17,6 +17,7 @@ "devDependencies": { "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", + "@sentry/webpack-plugin": "^2.22.0", "@svgr/webpack": "^8.1.0", "@types/dotenv-webpack": "^7.0.7", "@types/react": "^18.3.3", @@ -49,6 +50,7 @@ }, "dependencies": { "@emotion/react": "^11.11.4", + "@sentry/react": "^8.24.0", "haengdong-design": "^0.1.65", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", diff --git a/client/public/mockServiceWorker.js b/client/public/mockServiceWorker.js index 15751fa19..3abd19a06 100644 --- a/client/public/mockServiceWorker.js +++ b/client/public/mockServiceWorker.js @@ -8,42 +8,42 @@ * - Please do NOT serve this file on production. */ -const PACKAGE_VERSION = '2.3.5' -const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423' -const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') -const activeClientIds = new Set() +const PACKAGE_VERSION = '2.3.5'; +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'; +const IS_MOCKED_RESPONSE = Symbol('isMockedResponse'); +const activeClientIds = new Set(); self.addEventListener('install', function () { - self.skipWaiting() -}) + self.skipWaiting(); +}); self.addEventListener('activate', function (event) { - event.waitUntil(self.clients.claim()) -}) + event.waitUntil(self.clients.claim()); +}); self.addEventListener('message', async function (event) { - const clientId = event.source.id + const clientId = event.source.id; if (!clientId || !self.clients) { - return + return; } - const client = await self.clients.get(clientId) + const client = await self.clients.get(clientId); if (!client) { - return + return; } const allClients = await self.clients.matchAll({ type: 'window', - }) + }); switch (event.data) { case 'KEEPALIVE_REQUEST': { sendToClient(client, { type: 'KEEPALIVE_RESPONSE', - }) - break + }); + break; } case 'INTEGRITY_CHECK_REQUEST': { @@ -53,78 +53,78 @@ self.addEventListener('message', async function (event) { packageVersion: PACKAGE_VERSION, checksum: INTEGRITY_CHECKSUM, }, - }) - break + }); + break; } case 'MOCK_ACTIVATE': { - activeClientIds.add(clientId) + activeClientIds.add(clientId); sendToClient(client, { type: 'MOCKING_ENABLED', payload: true, - }) - break + }); + break; } case 'MOCK_DEACTIVATE': { - activeClientIds.delete(clientId) - break + activeClientIds.delete(clientId); + break; } case 'CLIENT_CLOSED': { - activeClientIds.delete(clientId) + activeClientIds.delete(clientId); - const remainingClients = allClients.filter((client) => { - return client.id !== clientId - }) + const remainingClients = allClients.filter(client => { + return client.id !== clientId; + }); // Unregister itself when there are no more clients if (remainingClients.length === 0) { - self.registration.unregister() + self.registration.unregister(); } - break + break; } } -}) +}); self.addEventListener('fetch', function (event) { - const { request } = event + const {request} = event; // Bypass navigation requests. if (request.mode === 'navigate') { - return + return; } // Opening the DevTools triggers the "only-if-cached" request // that cannot be handled by the worker. Bypass such requests. if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { - return + return; } // Bypass all requests when there are no active clients. // Prevents the self-unregistered worked from handling requests // after it's been deleted (still remains active until the next reload). if (activeClientIds.size === 0) { - return + return; } // Generate unique request ID. - const requestId = crypto.randomUUID() - event.respondWith(handleRequest(event, requestId)) -}) + const requestId = crypto.randomUUID(); + event.respondWith(handleRequest(event, requestId)); +}); async function handleRequest(event, requestId) { - const client = await resolveMainClient(event) - const response = await getResponse(event, client, requestId) + const client = await resolveMainClient(event); + const response = await getResponse(event, client, requestId); // Send back the response clone for the "response:*" life-cycle events. // Ensure MSW is active and ready to handle the message, otherwise // this message will pend indefinitely. if (client && activeClientIds.has(client.id)) { - ;(async function () { - const responseClone = response.clone() + (async function () { + const responseClone = response.clone(); sendToClient( client, @@ -141,11 +141,11 @@ async function handleRequest(event, requestId) { }, }, [responseClone.body], - ) - })() + ); + })(); } - return response + return response; } // Resolve the main client for the given event. @@ -153,49 +153,49 @@ async function handleRequest(event, requestId) { // that registered the worker. It's with the latter the worker should // communicate with during the response resolving phase. async function resolveMainClient(event) { - const client = await self.clients.get(event.clientId) + const client = await self.clients.get(event.clientId); if (client?.frameType === 'top-level') { - return client + return client; } const allClients = await self.clients.matchAll({ type: 'window', - }) + }); return allClients - .filter((client) => { + .filter(client => { // Get only those clients that are currently visible. - return client.visibilityState === 'visible' + return client.visibilityState === 'visible'; }) - .find((client) => { + .find(client => { // Find the client ID that's recorded in the // set of clients that have registered the worker. - return activeClientIds.has(client.id) - }) + return activeClientIds.has(client.id); + }); } async function getResponse(event, client, requestId) { - const { request } = event + const {request} = event; // Clone the request because it might've been already used // (i.e. its body has been read and sent to the client). - const requestClone = request.clone() + const requestClone = request.clone(); function passthrough() { - const headers = Object.fromEntries(requestClone.headers.entries()) + const headers = Object.fromEntries(requestClone.headers.entries()); // Remove internal MSW request header so the passthrough request // complies with any potential CORS preflight checks on the server. // Some servers forbid unknown request headers. - delete headers['x-msw-intention'] + delete headers['x-msw-intention']; - return fetch(requestClone, { headers }) + return fetch(requestClone, {headers}); } // Bypass mocking when the client is not active. if (!client) { - return passthrough() + return passthrough(); } // Bypass initial page load requests (i.e. static assets). @@ -203,11 +203,11 @@ async function getResponse(event, client, requestId) { // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet // and is not ready to handle requests. if (!activeClientIds.has(client.id)) { - return passthrough() + return passthrough(); } // Notify the client that a request has been intercepted. - const requestBuffer = await request.arrayBuffer() + const requestBuffer = await request.arrayBuffer(); const clientMessage = await sendToClient( client, { @@ -230,38 +230,35 @@ async function getResponse(event, client, requestId) { }, }, [requestBuffer], - ) + ); switch (clientMessage.type) { case 'MOCK_RESPONSE': { - return respondWithMock(clientMessage.data) + return respondWithMock(clientMessage.data); } case 'PASSTHROUGH': { - return passthrough() + return passthrough(); } } - return passthrough() + return passthrough(); } function sendToClient(client, message, transferrables = []) { return new Promise((resolve, reject) => { - const channel = new MessageChannel() + const channel = new MessageChannel(); - channel.port1.onmessage = (event) => { + channel.port1.onmessage = event => { if (event.data && event.data.error) { - return reject(event.data.error) + return reject(event.data.error); } - resolve(event.data) - } + resolve(event.data); + }; - client.postMessage( - message, - [channel.port2].concat(transferrables.filter(Boolean)), - ) - }) + client.postMessage(message, [channel.port2].concat(transferrables.filter(Boolean))); + }); } async function respondWithMock(response) { @@ -270,15 +267,15 @@ async function respondWithMock(response) { // instance will have status code set to 0. Since it's not possible to create // a Response instance with status code 0, handle that use-case separately. if (response.status === 0) { - return Response.error() + return Response.error(); } - const mockedResponse = new Response(response.body, response) + const mockedResponse = new Response(response.body, response); Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { value: true, enumerable: true, - }) + }); - return mockedResponse + return mockedResponse; } diff --git a/client/src/ErrorProvider.tsx b/client/src/ErrorProvider.tsx index b63610047..ef0714c7f 100644 --- a/client/src/ErrorProvider.tsx +++ b/client/src/ErrorProvider.tsx @@ -1,6 +1,6 @@ -import React, {createContext, useState, useContext, useEffect, ReactNode} from 'react'; +import {createContext, useState, useContext, useEffect, ReactNode} from 'react'; -import SERVER_ERROR_MESSAGES, {UNHANDLED_ERROR} from '@constants/errorMessage'; +import SERVER_ERROR_MESSAGES from '@constants/errorMessage'; // 에러 컨텍스트 생성 interface ErrorContextType { @@ -31,7 +31,8 @@ export const ErrorProvider = ({children, callback}: ErrorProviderProps) => { useEffect(() => { if (error) { if (isUnhandledError(error.errorCode)) { - throw new Error(UNHANDLED_ERROR); + // 에러바운더리로 보내기 + throw error; } setHasError(true); diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 1735386f0..04f50b128 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -1,4 +1,10 @@ -type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; +import {ServerError} from 'ErrorProvider'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; + +import FetchError from '../errors/FetchError'; + +export type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; type Body = ReadableStream | XMLHttpRequestBodyInit; type HeadersType = [string, string][] | Record<string, string> | Headers; @@ -11,7 +17,6 @@ type RequestProps = { headers?: HeadersType; body?: Body | object | null; queryParams?: ObjectQueryParams; - // errorMessage: string; }; type FetcherProps = RequestProps & { @@ -24,6 +29,12 @@ type Options = { body?: Body | null; }; +type ErrorHandlerProps = { + url: string; + options: Options; + body: string; +}; + const API_BASE_URL = process.env.API_BASE_URL; const objectToQueryString = (params: ObjectQueryParams): string => { @@ -54,13 +65,12 @@ export const requestPut = ({headers = {}, ...args}: RequestProps) => { export const requestPost = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { const response = await fetcher({method: 'POST', headers, ...args}); - const contentType = response!.headers.get('Content-Type'); - if (contentType && contentType.includes('application/json')) { - const data: T = await response!.json(); - return data; - } + // const contentType = response!.headers.get('Content-Type'); - return; + // if (contentType && contentType.includes('application/json')) { + const data: T = await response!.json(); + return data; + // } }; export const requestDelete = ({headers = {}, ...args}: RequestProps) => { @@ -68,13 +78,11 @@ export const requestDelete = ({headers = {}, ...args}: RequestProps) => { }; const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: FetcherProps) => { - // const token = generateBasicToken(USER_ID, USER_PASSWORD); const options = { method, credentials: 'include', headers: { 'Content-Type': 'application/json', - // Authorization: token, ...headers, }, body: body ? JSON.stringify(body) : null, @@ -84,14 +92,33 @@ const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, query if (queryParams) url += `?${objectToQueryString(queryParams)}`; - return errorHandler(url, options); + return errorHandler({url, options, body: JSON.stringify(body)}); }; -const errorHandler = async (url: string, options: Options) => { - const response = await fetch(url, options); - if (!response.ok) { - const serverErrorMessage = await response.text(); - throw new Error(serverErrorMessage || ''); // 받은 에러 메세지가 없는 경우는 서버에게.. +const errorHandler = async ({url, options, body}: ErrorHandlerProps) => { + try { + const response: Response = await fetch(url, options); + + if (!response.ok) { + const serverErrorBody: ServerError = await response.json(); + + throw new FetchError({ + status: response.status, + requestBody: body, + endpoint: response.url, + errorBody: serverErrorBody, + name: serverErrorBody.errorCode, + message: serverErrorBody.message || '', + method: options.method, + }); + } + + return response; + } catch (error) { + if (error instanceof Error) { + throw error; + } + + throw new Error(UNKNOWN_ERROR); } - return response; }; diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts index 2a52b583e..945887478 100644 --- a/client/src/apis/useFetch.ts +++ b/client/src/apis/useFetch.ts @@ -1,12 +1,17 @@ import {useState} from 'react'; +import {NavigateFunction, useNavigate} from 'react-router-dom'; -import {UNHANDLED_ERROR} from '@constants/errorMessage'; +import sendLogToSentry from '@utils/sendLogToSentry'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; import {ServerError, useError} from '../ErrorProvider'; +import FetchError from '../errors/FetchError'; export const useFetch = () => { const {setError, clearError} = useError(); const [loading, setLoading] = useState(false); + const navigate = useNavigate(); const fetch = async <T>(queryFunction: () => Promise<T>): Promise<T> => { setLoading(true); @@ -14,20 +19,70 @@ export const useFetch = () => { try { const result = await queryFunction(); + return result; } catch (error) { if (error instanceof Error) { - const errorBody: ServerError = await JSON.parse(error.message); + const errorBody = + error instanceof FetchError ? error.errorBody : {errorCode: error.name, message: error.message}; setError(errorBody); - throw new Error(errorBody.message); + + captureError(error, navigate); } else { - throw new Error(UNHANDLED_ERROR); + setError({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); + + captureError(new Error(UNKNOWN_ERROR), navigate); + + // 에러를 throw 해 에러 바운더리로 보냅니다. 따라서 에러 이름은 중요하지 않음 + throw new Error(UNKNOWN_ERROR); } } finally { setLoading(false); } + + return {} as T; }; return {loading, fetch}; }; + +const captureError = async (error: Error, navigate: NavigateFunction) => { + const errorBody: ServerError = + error instanceof FetchError ? error.errorBody : {message: error.message, errorCode: error.name}; + + switch (errorBody?.errorCode) { + case 'INTERNAL_SERVER_ERROR': + sendLogToSentry({error, errorBody, level: 'fatal'}); + break; + + case 'TOKEN_INVALID': + sendLogToSentry({error, errorBody}); + break; + + case 'TOKEN_EXPIRED': + sendLogToSentry({error, errorBody}); + // TODO: (@weadie) 여기에 토스트를 띄울지 말지 + navigate('/'); // TODO: (@weadie) 루트 경로 상수화 + + break; + + case 'TOKEN_NOT_FOUND': + sendLogToSentry({error, errorBody}); + break; + + // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 + case 'PASSWORD_INVALID': + sendLogToSentry({error, errorBody, level: 'debug'}); + break; + + // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 + case 'BILL_ACTION_PRICE_INVALID': + sendLogToSentry({error, errorBody, level: 'debug'}); + break; + + default: + sendLogToSentry({error, errorBody, level: 'fatal'}); + break; + } +}; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index a5fc21046..cfe0fb751 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -44,6 +44,6 @@ export const ERROR_MESSAGE = { preventEmpty: '값은 비어있을 수 없어요', }; -export const UNHANDLED_ERROR = 'UNHANDLED'; +export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; export default SERVER_ERROR_MESSAGES; diff --git a/client/src/errors/FetchError.ts b/client/src/errors/FetchError.ts new file mode 100644 index 000000000..f7bf21fe9 --- /dev/null +++ b/client/src/errors/FetchError.ts @@ -0,0 +1,23 @@ +import {FetchErrorType} from '../types/fetchErrorType'; + +class FetchError extends Error { + requestBody; + status; + endpoint; + errorBody; + method; + + constructor({requestBody, status, endpoint, errorBody, method, name, message}: FetchErrorType) { + super(errorBody.errorCode); + + this.requestBody = requestBody; + this.status = status; + this.endpoint = endpoint; + this.errorBody = errorBody; + this.method = method; + this.name = name; + this.message = message; + } +} + +export default FetchError; diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx index 33d50f243..6ca12e22b 100644 --- a/client/src/hooks/useStepList/useStepList.tsx +++ b/client/src/hooks/useStepList/useStepList.tsx @@ -7,6 +7,8 @@ import {requestPostBillList} from '@apis/request/bill'; import {requestGetAllMemberList, requestPostMemberList} from '@apis/request/member'; import {requestGetStepList} from '@apis/request/stepList'; +import {useFetch} from '@apis/useFetch'; + interface StepListContextProps { stepList: (BillStep | MemberStep)[]; allMemberList: string[]; @@ -19,6 +21,7 @@ interface StepListContextProps { export const StepListContext = createContext<StepListContextProps | null>(null); // TODO: (@weadie) 인자를 어떻게 줘야 하는지 고민하기. const StepListProvider = ({children}: PropsWithChildren) => { + const {fetch} = useFetch(); const [stepList, setStepList] = useState<(BillStep | MemberStep)[]>([]); const [allMemberList, setAllMemberList] = useState<string[]>([]); @@ -33,7 +36,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { }, [eventId]); const refreshStepList = async () => { - const stepList = await requestGetStepList({eventId}); + const stepList = await fetch(() => requestGetStepList({eventId})); getAllMemberList(); setStepList(stepList); @@ -41,7 +44,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { const updateMemberList = async ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => { try { - await requestPostMemberList({eventId, type, memberNameList}); + await fetch(() => requestPostMemberList({eventId, type, memberNameList})); refreshStepList(); } catch (error) { @@ -57,7 +60,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { const addBill = async (billList: Bill[]) => { // TODO: (@weadie) 에러 처리 - await requestPostBillList({eventId, billList}); + await fetch(() => requestPostBillList({eventId, billList})); refreshStepList(); }; diff --git a/client/src/index.tsx b/client/src/index.tsx index 30d939fee..d4885b7d2 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -1,13 +1,26 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import {RouterProvider} from 'react-router-dom'; +import * as Sentry from '@sentry/react'; import router from './router'; -async function enableMocking() { - const {worker} = await import('./mocks/browser'); - return worker.start(); -} +// async function enableMocking() { +// const {worker} = await import('./mocks/browser'); +// return worker.start(); +// } + +Sentry.init({ + dsn: 'https://81685591a3234c689be8c48959b04c88@o4507739935997952.ingest.us.sentry.io/4507739943272448', + integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], + // Performance Monitoring + tracesSampleRate: 1.0, // Capture 100% of the transactions + // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled + tracePropagationTargets: ['localhost', /^https:\/\/yourserver\.io\/api/], + // Session Replay + replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production. + replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur. +}); // MSW 모킹을 사용하려면 아래 주석을 해제하고 save해주세요. // enableMocking().then(() => { diff --git a/client/src/types/fetchErrorType.ts b/client/src/types/fetchErrorType.ts new file mode 100644 index 000000000..2ab327e19 --- /dev/null +++ b/client/src/types/fetchErrorType.ts @@ -0,0 +1,11 @@ +import {ServerError} from 'ErrorProvider'; + +import {Method} from '@apis/fetcher'; + +export type FetchErrorType = Error & { + requestBody: string; + status: number; + endpoint: string; + errorBody: ServerError; + method: Method; +}; diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts new file mode 100644 index 000000000..692670dda --- /dev/null +++ b/client/src/utils/sendLogToSentry.ts @@ -0,0 +1,56 @@ +import * as Sentry from '@sentry/react'; + +import {ServerError} from 'ErrorProvider'; + +import FetchError from '../errors/FetchError'; +/** + * level은 아래와 같은 용도에 맞게 지정해줍니다. + * + * fatal: 앱이 종료될 수 있는 치명적인 오류 + * error: 특정 기능 실패로 앱 종료까지는 아닌 오류 + * warning: 잠재적으로 문제가 될 수 있는 오류. 현재는 심각하지 않은 오류 + * info: 시스템의 정상적인 동작을 나타냄. 중요한 이벤트나 상태 변화 기록용 + * debug: 디버깅 목적으로 사용됨 + * log: 일반적인 로그 메세지 + */ + +type SentryLevel = 'fatal' | 'error' | 'warning' | 'info' | 'debug' | 'log'; +type SendLogToSentry = { + level?: SentryLevel; + error: Error; + errorBody: ServerError; +}; + +const sendLogToSentry = ({level = 'error', error, errorBody}: SendLogToSentry) => { + Sentry.withScope(scope => { + const {errorCode, message} = errorBody; + scope.setLevel(level); + + scope.setTag('environment', process.env.NODE_ENV); + + if (error instanceof FetchError) { + scope.setTags({ + endpoint: error.endpoint, + url: window.location.href, + errorCode, + errorMessage: message, + status: error.status, + requestBody: JSON.stringify(error.requestBody), + method: error.status, + }); + + Sentry.captureMessage(`${errorCode}`); + } else { + scope.setTags({ + url: window.location.href, + errorCode, + message: error.message, + name: error.name, + }); + + Sentry.captureMessage(`${errorCode}`); + } + }); +}; + +export default sendLogToSentry; diff --git a/client/tsconfig.json b/client/tsconfig.json index b049bf464..a80c56bbd 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -42,7 +42,8 @@ "@hooks/*": ["hooks/*"], "@mocks/*": ["mocks/*"], "@pages/*": ["pages/*"], - "@utils/*": ["utils/*"] + "@utils/*": ["utils/*"], + "@errors/*": ["errors/*"] }, "outDir": "./dist" }, diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs index fc39ac87b..252a5b0ca 100644 --- a/client/webpack.common.mjs +++ b/client/webpack.common.mjs @@ -20,6 +20,7 @@ export default { '@mocks': path.resolve(__dirname, 'src/mocks/'), '@pages': path.resolve(__dirname, 'src/pages/'), '@utils': path.resolve(__dirname, 'src/utils/'), + '@errors': path.resolve(__dirname, 'src/errors/'), }, }, module: { diff --git a/client/webpack.dev.mjs b/client/webpack.dev.mjs index 5ad42ed45..bfe53d51b 100644 --- a/client/webpack.dev.mjs +++ b/client/webpack.dev.mjs @@ -3,6 +3,7 @@ import {merge} from 'webpack-merge'; import Dotenv from 'dotenv-webpack'; import common from './webpack.common.mjs'; import {fileURLToPath} from 'url'; +import {sentryWebpackPlugin} from '@sentry/webpack-plugin'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -16,7 +17,7 @@ export default merge(common, { clean: true, publicPath: '/', }, - devtool: 'eval-source-map', + devtool: 'source-map', devServer: { port: 3000, historyApiFallback: true, @@ -29,5 +30,10 @@ export default merge(common, { new Dotenv({ path: '.env.dev', }), + sentryWebpackPlugin({ + authToken: process.env.SENTRY_AUTH_TOKEN, + org: 'wtc-o6', + project: 'javascript-react', + }), ], }); diff --git a/client/webpack.prod.mjs b/client/webpack.prod.mjs index 5df1f7c4c..1cf3bc7d1 100644 --- a/client/webpack.prod.mjs +++ b/client/webpack.prod.mjs @@ -3,6 +3,7 @@ import {merge} from 'webpack-merge'; import Dotenv from 'dotenv-webpack'; import common from './webpack.common.mjs'; import {fileURLToPath} from 'url'; +import {sentryWebpackPlugin} from '@sentry/webpack-plugin'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -21,5 +22,10 @@ export default merge(common, { new Dotenv({ path: '.env.prod', }), + sentryWebpackPlugin({ + authToken: process.env.SENTRY_AUTH_TOKEN, + org: 'wtc-o6', + project: 'javascript-react', + }), ], }); From ff951e55f2f0ef3f8e091738a388802f30d69f6d Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 9 Aug 2024 03:12:38 +0900 Subject: [PATCH 136/273] =?UTF-8?q?feat:=203=EC=B0=A8=20=EB=8D=B0=EB=AA=A8?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=20merge=20=EC=A4=91=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=9C=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95=20(#280)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- HDesign/package-lock.json | 4 +- HDesign/package.json | 2 +- client/package-lock.json | 18 ++++- client/package.json | 3 +- client/src/apis/fetcher.ts | 10 +-- client/src/apis/request/auth.ts | 31 ++++++++ client/src/apis/request/member.ts | 11 +++ .../SetAllMemberListModal.tsx | 11 --- client/src/hooks/useAuth.tsx | 18 +++++ client/src/index.tsx | 2 +- .../EventPage/AdminPage/EventLoginPage.tsx | 75 +++++++++++++++++++ client/src/utils/sendLogToSentry.ts | 23 ++++-- 12 files changed, 178 insertions(+), 30 deletions(-) create mode 100644 client/src/apis/request/auth.ts create mode 100644 client/src/hooks/useAuth.tsx create mode 100644 client/src/pages/EventPage/AdminPage/EventLoginPage.tsx diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 0faaccf1d..5164bd450 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.65", + "version": "0.1.66", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.65", + "version": "0.1.66", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index b0ad0c465..96ebc49e5 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.65", + "version": "0.1.66", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/client/package-lock.json b/client/package-lock.json index e041d7df0..21e5093d9 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.24.0", - "haengdong-design": "^0.1.65", + "haengdong-design": "^0.1.66", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -25,6 +25,7 @@ "@svgr/webpack": "^8.1.0", "@types/dotenv-webpack": "^7.0.7", "@types/react": "^18.3.3", + "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", @@ -3547,6 +3548,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-copy-to-clipboard": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz", + "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-dom": { "version": "18.3.0", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", @@ -7240,9 +7250,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.65", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.65.tgz", - "integrity": "sha512-zRLb6U2dbN9eBABl9e+7ggSdbAqy/4Bh863BZ0NiLM7ESTktrg8bkJYDUi0j42W4e+1owctA34eNc60FevlKZg==", + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.66.tgz", + "integrity": "sha512-wNrL/N2SLxQg+oATqVIsnB4YFZGwPFv5x/H22N79w6XCWVpG+q1TvxF3GCle7eEJIV6atdRF6lH1kSW0h4b+gw==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index 739d0df4c..a6f7e4425 100644 --- a/client/package.json +++ b/client/package.json @@ -21,6 +21,7 @@ "@svgr/webpack": "^8.1.0", "@types/dotenv-webpack": "^7.0.7", "@types/react": "^18.3.3", + "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", @@ -51,7 +52,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.24.0", - "haengdong-design": "^0.1.65", + "haengdong-design": "^0.1.66", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 04f50b128..b8f186627 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -65,12 +65,12 @@ export const requestPut = ({headers = {}, ...args}: RequestProps) => { export const requestPost = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { const response = await fetcher({method: 'POST', headers, ...args}); - // const contentType = response!.headers.get('Content-Type'); + const contentType = response!.headers.get('Content-Type'); - // if (contentType && contentType.includes('application/json')) { - const data: T = await response!.json(); - return data; - // } + if (contentType && contentType.includes('application/json')) { + const data: T = await response!.json(); + return data; + } }; export const requestDelete = ({headers = {}, ...args}: RequestProps) => { diff --git a/client/src/apis/request/auth.ts b/client/src/apis/request/auth.ts new file mode 100644 index 000000000..151915ca3 --- /dev/null +++ b/client/src/apis/request/auth.ts @@ -0,0 +1,31 @@ +import type {MemberReport} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestPost} from '@apis/fetcher'; + +export type RequestAuthentication = { + eventId: string; +}; + +export type RequestToken = { + eventId: string; + password: string; +}; + +export const requestAuthentication = async ({eventId}: RequestAuthentication) => { + await requestPost({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/auth`, + }); +}; + +export const requestToken = async ({eventId, password}: RequestToken) => { + return await requestPost({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/login`, + body: { + password: password, + }, + }); +}; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 4bd6e1833..6acca591e 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -71,3 +71,14 @@ export const requestDeleteAllMemberList = async ({eventId, memberName}: WithEven endpoint: `${TEMP_PREFIX}/${eventId}/members/${memberName}`, }); }; + +export type ResponseGetCurrentInMemberList = { + members: Array<{name: string}>; +}; + +export const requestGetCurrentInMemberList = async (eventId: string) => { + return await requestGet<ResponseGetCurrentInMemberList>({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/current`, + }); +}; diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx index d09327ccc..58e86b917 100644 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx @@ -48,17 +48,11 @@ const SetAllMemberListModal = ({ <div css={allMemberListModalStyle}> <div css={allMemberListModalTitleStyle}> <Text size="bodyBold">전체 참여자 수정하기</Text> - {/* TODO: (@soha): 인원 텍스트 색 수정 필요 */} -<<<<<<< HEAD <Text size="bodyBold" textColor="gray"> -======= - <Text size="bodyBold" color="sematic"> ->>>>>>> fe-dev 총 {allMemberList.length}명 </Text> </div> <div css={allMemberListModalLabelGroupInputStyle}> -<<<<<<< HEAD <LabelGroupInput labelText="이름" errorText={errorMessage}> {editedAllMemberList.map((member, index) => ( <div css={InputAndDeleteButtonContainer} key={index}> @@ -74,11 +68,6 @@ const SetAllMemberListModal = ({ <Icon iconType="trash" iconColor="onTertiary" /> </IconButton> </div> -======= - <LabelGroupInput labelText="이름"> - {allMemberList.map((member, index) => ( - <InputAndDeleteButton key={index} propsValue={member} /> ->>>>>>> fe-dev ))} </LabelGroupInput> </div> diff --git a/client/src/hooks/useAuth.tsx b/client/src/hooks/useAuth.tsx new file mode 100644 index 000000000..36f634ad2 --- /dev/null +++ b/client/src/hooks/useAuth.tsx @@ -0,0 +1,18 @@ +import {RequestAuthentication, requestAuthentication, RequestToken, requestToken} from '@apis/request/auth'; +import {useFetch} from '@apis/useFetch'; + +const useAuth = () => { + const {fetch} = useFetch(); + + const postAuthentication = async ({eventId}: RequestAuthentication) => { + return await fetch(() => requestAuthentication({eventId})); + }; + + const postLogin = async ({eventId, password}: RequestToken) => { + return await fetch(() => requestToken({eventId, password})); + }; + + return {postAuthentication, postLogin}; +}; + +export default useAuth; diff --git a/client/src/index.tsx b/client/src/index.tsx index d4885b7d2..17f98655f 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -16,7 +16,7 @@ Sentry.init({ // Performance Monitoring tracesSampleRate: 1.0, // Capture 100% of the transactions // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled - tracePropagationTargets: ['localhost', /^https:\/\/yourserver\.io\/api/], + tracePropagationTargets: ['localhost', /^https:\/\/api\.haengdong\.pro/], // Session Replay replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production. replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur. diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx new file mode 100644 index 000000000..1b1ab2b52 --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -0,0 +1,75 @@ +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; +import {requestPostNewEvent} from '@apis/request/event'; + +import useEvent from '@hooks/useEvent'; + +import RULE from '@constants/rule'; +import {ROUTER_URLS} from '@constants/routerUrls'; +import useEventId from '@hooks/useEventId/useEventId'; +import useAuth from '@hooks/useAuth'; + +const EventLoginPage = () => { + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const navigate = useNavigate(); + const {eventId} = useEventId(); + const {postLogin} = useAuth(); + + const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + try { + await postLogin({eventId, password}); + navigate(`${ROUTER_URLS.event}/${eventId}/admin`); + } catch (error) { + setErrorMessage('잘못된 비밀번호에요'); + } + }; + + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (validation.isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + return ( + <MainLayout> + <TopNav> + <Back /> + </TopNav> + <Title + title="행사 비밀번호 입력" + description="관리를 위해선 비밀번호가 필요해요. \n행사 생성 시 설정한 4 자리의 숫자 비밀번호를 입력해 주세요." + /> + <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <LabelInput + labelText="비밀번호" + errorText={errorMessage} + value={password} + type="secret" + maxLength={RULE.maxEventPasswordLength} + placeholder="비밀번호" + onChange={e => handleChange(e)} + isError={!!errorMessage} + autoFocus + ></LabelInput> + <FixedButton disabled={!canSubmit}>관리 페이지로</FixedButton> + </form> + </MainLayout> + ); +}; + +export default EventLoginPage; diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts index 692670dda..ea12c72e9 100644 --- a/client/src/utils/sendLogToSentry.ts +++ b/client/src/utils/sendLogToSentry.ts @@ -3,6 +3,9 @@ import * as Sentry from '@sentry/react'; import {ServerError} from 'ErrorProvider'; import FetchError from '../errors/FetchError'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; + /** * level은 아래와 같은 용도에 맞게 지정해줍니다. * @@ -29,25 +32,35 @@ const sendLogToSentry = ({level = 'error', error, errorBody}: SendLogToSentry) = scope.setTag('environment', process.env.NODE_ENV); if (error instanceof FetchError) { + console.log('fetchError'); scope.setTags({ endpoint: error.endpoint, url: window.location.href, errorCode, errorMessage: message, status: error.status, - requestBody: JSON.stringify(error.requestBody), - method: error.status, + // requestBody: JSON.stringify(error.requestBody), + method: error.method, }); Sentry.captureMessage(`${errorCode}`); - } else { + } else if (error instanceof Error) { + console.log('error'); + scope.setTags({ url: window.location.href, errorCode, - message: error.message, - name: error.name, + errorMessage: message, }); + Sentry.captureMessage(`${errorCode}`); + } else { + scope.setTags({ + url: window.location.href, + errorCode, + message: UNKNOWN_ERROR, + name: UNKNOWN_ERROR, + }); Sentry.captureMessage(`${errorCode}`); } }); From a393fb8af82e511768d144e0138135b58c48d8ca Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 9 Aug 2024 03:21:05 +0900 Subject: [PATCH 137/273] =?UTF-8?q?feat:=20requestPost=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=B4=20response=EA=B0=80=20=EC=9E=88=EB=8A=94=20p?= =?UTF-8?q?ost=EC=99=80=20=EC=97=86=EB=8A=94=20post=EB=A1=9C=20=EB=B6=84?= =?UTF-8?q?=EA=B8=B0=ED=95=B4=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=ED=95=A8=20(#281)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- client/src/apis/fetcher.ts | 14 +++++++------- client/src/apis/request/auth.ts | 8 +++----- client/src/apis/request/bill.ts | 4 ++-- client/src/apis/request/event.ts | 5 ++--- client/src/apis/request/member.ts | 4 ++-- client/src/hooks/useAuth.tsx | 1 + .../pages/EventPage/AdminPage/EventLoginPage.tsx | 4 ++-- client/src/utils/sendLogToSentry.ts | 6 ++---- 8 files changed, 21 insertions(+), 25 deletions(-) diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index b8f186627..8ca83aab8 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -62,15 +62,15 @@ export const requestPut = ({headers = {}, ...args}: RequestProps) => { return fetcher({method: 'PUT', headers, ...args}); }; -export const requestPost = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { - const response = await fetcher({method: 'POST', headers, ...args}); +export const requestPostWithoutResponse = async ({headers = {}, ...args}: RequestProps) => { + await fetcher({method: 'POST', headers, ...args}); +}; - const contentType = response!.headers.get('Content-Type'); +export const requestPostWithResponse = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { + const response = await fetcher({method: 'POST', headers, ...args}); - if (contentType && contentType.includes('application/json')) { - const data: T = await response!.json(); - return data; - } + const data: T = await response!.json(); + return data; }; export const requestDelete = ({headers = {}, ...args}: RequestProps) => { diff --git a/client/src/apis/request/auth.ts b/client/src/apis/request/auth.ts index 151915ca3..efaf610de 100644 --- a/client/src/apis/request/auth.ts +++ b/client/src/apis/request/auth.ts @@ -1,8 +1,6 @@ -import type {MemberReport} from 'types/serviceType'; - import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestPost} from '@apis/fetcher'; +import {requestPostWithResponse, requestPostWithoutResponse} from '@apis/fetcher'; export type RequestAuthentication = { eventId: string; @@ -14,14 +12,14 @@ export type RequestToken = { }; export const requestAuthentication = async ({eventId}: RequestAuthentication) => { - await requestPost({ + await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/auth`, }); }; export const requestToken = async ({eventId, password}: RequestToken) => { - return await requestPost({ + return await requestPostWithResponse({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/login`, body: { diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 6996ac01c..dbf2fdd45 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -2,7 +2,7 @@ import type {Bill} from 'types/serviceType'; import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestPost, requestDelete, requestPut} from '@apis/fetcher'; +import {requestDelete, requestPostWithoutResponse, requestPut} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; type RequestPostBillList = { @@ -10,7 +10,7 @@ type RequestPostBillList = { }; export const requestPostBillList = async ({eventId, billList}: WithEventId<RequestPostBillList>) => { - await requestPost({ + await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions`, body: { diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index f9f4d6984..c9299c813 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -1,5 +1,5 @@ import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestGet, requestPost} from '@apis/fetcher'; +import {requestGet, requestPostWithResponse} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; export type RequestPostNewEvent = { @@ -12,8 +12,7 @@ export type ResponsePostNewEvent = { }; export const requestPostNewEvent = async ({eventName, password}: RequestPostNewEvent) => { - // TODO: (@weadie) 뼈대만 둔 것. header값을 꺼내오는 로직이 필요하다. 또는 바디에 달라고 부탁할 수 있다. - return requestPost<ResponsePostNewEvent>({ + return await requestPostWithResponse<ResponsePostNewEvent>({ endpoint: TEMP_PREFIX, body: { eventName: eventName, diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 6acca591e..48329e78f 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -2,7 +2,7 @@ import type {MemberType} from 'types/serviceType'; import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestPost, requestDelete, requestGet, requestPut} from '@apis/fetcher'; +import {requestDelete, requestGet, requestPut, requestPostWithoutResponse} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; type RequestPostMemberList = { @@ -11,7 +11,7 @@ type RequestPostMemberList = { }; export const requestPostMemberList = async ({eventId, type, memberNameList}: WithEventId<RequestPostMemberList>) => { - await requestPost({ + await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/member-actions`, body: { diff --git a/client/src/hooks/useAuth.tsx b/client/src/hooks/useAuth.tsx index 36f634ad2..a2295a41f 100644 --- a/client/src/hooks/useAuth.tsx +++ b/client/src/hooks/useAuth.tsx @@ -1,4 +1,5 @@ import {RequestAuthentication, requestAuthentication, RequestToken, requestToken} from '@apis/request/auth'; + import {useFetch} from '@apis/useFetch'; const useAuth = () => { diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index 1b1ab2b52..a23341d4f 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -4,13 +4,13 @@ import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdon import validateEventPassword from '@utils/validate/validateEventPassword'; import {requestPostNewEvent} from '@apis/request/event'; +import useEventId from '@hooks/useEventId/useEventId'; import useEvent from '@hooks/useEvent'; +import useAuth from '@hooks/useAuth'; import RULE from '@constants/rule'; import {ROUTER_URLS} from '@constants/routerUrls'; -import useEventId from '@hooks/useEventId/useEventId'; -import useAuth from '@hooks/useAuth'; const EventLoginPage = () => { const [password, setPassword] = useState(''); diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts index ea12c72e9..aa1bc263f 100644 --- a/client/src/utils/sendLogToSentry.ts +++ b/client/src/utils/sendLogToSentry.ts @@ -2,10 +2,10 @@ import * as Sentry from '@sentry/react'; import {ServerError} from 'ErrorProvider'; -import FetchError from '../errors/FetchError'; - import {UNKNOWN_ERROR} from '@constants/errorMessage'; +import FetchError from '../errors/FetchError'; + /** * level은 아래와 같은 용도에 맞게 지정해줍니다. * @@ -45,8 +45,6 @@ const sendLogToSentry = ({level = 'error', error, errorBody}: SendLogToSentry) = Sentry.captureMessage(`${errorCode}`); } else if (error instanceof Error) { - console.log('error'); - scope.setTags({ url: window.location.href, errorCode, From f5df73817d9926727da9a79b762109bf0ffa75e0 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:48:29 +0900 Subject: [PATCH 138/273] =?UTF-8?q?feat:=20=ED=99=88=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=95=A1=EC=85=98=20=EC=88=98=EC=A0=95=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20=ED=99=9C=EC=84=B1?= =?UTF-8?q?=ED=99=94=20=EB=B2=84=EA=B7=B8=20(#285)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 --- .../AddMemberActionListModalContent/OutMember.tsx | 2 +- client/src/components/StepList/BillStepItem.tsx | 6 ++++-- client/src/components/StepList/MemberStepItem.tsx | 6 +++++- client/src/components/StepList/StepList.tsx | 2 +- client/src/pages/EventPage/EventPageLayout.tsx | 7 +++++-- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx index fa2ac61d1..a3757aec3 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -27,12 +27,12 @@ const OutMember = ({dynamicProps}: OutMemberProps) => { return inputList.map(({value, index}) => ( <Search + key={`${value}-${index}`} isShowTargetInput={currentInputIndex === index} matchItems={filteredInMemberList} onMatchItemClick={(term: string) => chooseMember(currentInputIndex, term)} > <LabelGroupInput.Element - key={index} elementKey={`${index}`} type="text" value={value} diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 90d99062a..aeff34a2c 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -2,6 +2,7 @@ import type {BillStep} from 'types/serviceType'; import {DragHandleItem, DragHandleItemContainer} from 'haengdong-design'; import {Fragment, useState} from 'react'; +import {useOutletContext} from 'react-router-dom'; import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; @@ -12,6 +13,7 @@ interface BillStepItemProps { } const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { + const isAdmin = useOutletContext<boolean>(); const [clickedIndex, setClickedIndex] = useState(-1); const totalPrice = step.actions.reduce((acc, cur) => acc + cur.price, 0); @@ -32,13 +34,13 @@ const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, set {step.actions.map((action, index) => ( <Fragment key={action.actionId}> <DragHandleItem - hasDragHandler={true} + hasDragHandler={isAdmin} prefix={action.name} suffix={`${action.price.toLocaleString('ko-kr')} 원`} backgroundColor="lightGrayContainer" onClick={() => handleDragHandleItemClick(index)} /> - {isOpenBottomSheet && clickedIndex === index && ( + {isOpenBottomSheet && clickedIndex === index && isAdmin && ( <PutAndDeleteBillActionModal billAction={action} isBottomSheetOpened={isOpenBottomSheet} diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx index 9a482c665..fa94eeaa6 100644 --- a/client/src/components/StepList/MemberStepItem.tsx +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -1,6 +1,7 @@ import type {MemberStep} from 'types/serviceType'; import {DragHandleItem} from 'haengdong-design'; +import {useOutletContext} from 'react-router-dom'; import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMemberActionModal'; @@ -11,14 +12,17 @@ interface MemberStepItemProps { } const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { + const isAdmin = useOutletContext<boolean>(); + return ( <> <DragHandleItem + hasDragHandler={isAdmin} backgroundColor="white" prefix={`${step.actions.map(({name}) => name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} onClick={() => setIsOpenBottomSheet(prev => !prev)} /> - {isOpenBottomSheet && ( + {isOpenBottomSheet && isAdmin && ( <DeleteMemberActionModal memberActionType={step.type} memberActionList={step.actions} diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index ccd6afd94..1aeb7888e 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -11,7 +11,7 @@ const StepList = () => { return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> {stepList.map((step, index) => ( - <Step step={step} key={`${step.stepName}${index}`}></Step> + <Step step={step} key={`${step.stepName}${index}`} /> ))} </Flex> ); diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 3f68b4ba1..1aa7797c3 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,12 +1,15 @@ import {MainLayout, TopNav, Switch} from 'haengdong-design'; -import {Outlet} from 'react-router-dom'; +import {Outlet, useMatch} from 'react-router-dom'; import StepListProvider from '@hooks/useStepList/useStepList'; import useNavSwitch from '@hooks/useNavSwitch'; +import {ROUTER_URLS} from '@constants/routerUrls'; + const EventPageLayout = () => { const {nav, paths, onChange} = useNavSwitch(); + const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; return ( <StepListProvider> @@ -14,7 +17,7 @@ const EventPageLayout = () => { <TopNav> <Switch value={nav} values={paths} onChange={onChange} /> </TopNav> - <Outlet /> + <Outlet context={isAdmin} /> </MainLayout> </StepListProvider> ); From 80c89833d8efdadde5817cc739416131c8e1d233 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:55:18 +0900 Subject: [PATCH 139/273] =?UTF-8?q?feat:=20cookie=EA=B0=80=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20(#286)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 --- client/src/apis/request/auth.ts | 2 +- client/src/apis/useFetch.ts | 27 +++++++++++++------ client/src/constants/routerUrls.ts | 1 + .../CompleteCreateEventPage.tsx | 17 +++++++----- .../pages/EventPage/AdminPage/AdminPage.tsx | 17 +++++++++++- .../EventPage/AdminPage/EventLoginPage.tsx | 14 +++++----- client/src/router.tsx | 5 ++++ client/webpack.dev.mjs | 1 - 8 files changed, 61 insertions(+), 23 deletions(-) diff --git a/client/src/apis/request/auth.ts b/client/src/apis/request/auth.ts index efaf610de..94fb2c55f 100644 --- a/client/src/apis/request/auth.ts +++ b/client/src/apis/request/auth.ts @@ -19,7 +19,7 @@ export const requestAuthentication = async ({eventId}: RequestAuthentication) => }; export const requestToken = async ({eventId, password}: RequestToken) => { - return await requestPostWithResponse({ + await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/login`, body: { diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts index 945887478..253f92951 100644 --- a/client/src/apis/useFetch.ts +++ b/client/src/apis/useFetch.ts @@ -1,9 +1,12 @@ import {useState} from 'react'; import {NavigateFunction, useNavigate} from 'react-router-dom'; +import useEventId from '@hooks/useEventId/useEventId'; + import sendLogToSentry from '@utils/sendLogToSentry'; import {UNKNOWN_ERROR} from '@constants/errorMessage'; +import {ROUTER_URLS} from '@constants/routerUrls'; import {ServerError, useError} from '../ErrorProvider'; import FetchError from '../errors/FetchError'; @@ -12,6 +15,7 @@ export const useFetch = () => { const {setError, clearError} = useError(); const [loading, setLoading] = useState(false); const navigate = useNavigate(); + const {eventId} = useEventId(); const fetch = async <T>(queryFunction: () => Promise<T>): Promise<T> => { setLoading(true); @@ -27,12 +31,12 @@ export const useFetch = () => { error instanceof FetchError ? error.errorBody : {errorCode: error.name, message: error.message}; setError(errorBody); - - captureError(error, navigate); + console.log('???'); + captureError(error, navigate, eventId); } else { setError({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); - - captureError(new Error(UNKNOWN_ERROR), navigate); + console.log('!!!'); + captureError(new Error(UNKNOWN_ERROR), navigate, eventId); // 에러를 throw 해 에러 바운더리로 보냅니다. 따라서 에러 이름은 중요하지 않음 throw new Error(UNKNOWN_ERROR); @@ -47,33 +51,40 @@ export const useFetch = () => { return {loading, fetch}; }; -const captureError = async (error: Error, navigate: NavigateFunction) => { +const captureError = async (error: Error, navigate: NavigateFunction, eventId: string) => { const errorBody: ServerError = error instanceof FetchError ? error.errorBody : {message: error.message, errorCode: error.name}; + console.log(errorBody); switch (errorBody?.errorCode) { case 'INTERNAL_SERVER_ERROR': sendLogToSentry({error, errorBody, level: 'fatal'}); break; + case 'FORBIDDEN': + sendLogToSentry({error, errorBody}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; + case 'TOKEN_INVALID': sendLogToSentry({error, errorBody}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; case 'TOKEN_EXPIRED': sendLogToSentry({error, errorBody}); - // TODO: (@weadie) 여기에 토스트를 띄울지 말지 - navigate('/'); // TODO: (@weadie) 루트 경로 상수화 - + navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; case 'TOKEN_NOT_FOUND': sendLogToSentry({error, errorBody}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 case 'PASSWORD_INVALID': sendLogToSentry({error, errorBody, level: 'debug'}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index f9587b530..6a3634c3b 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -4,6 +4,7 @@ export const ROUTER_URLS = { eventCreatePassword: '/event/create/password', eventCreateComplete: '/event/create/complete', event: '/event', // TODO: (@weadie) baseurl을 어떻게 관리할 것인가? + eventLogin: '/event/:eventId/login', eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', }; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 808bf4319..2abcbda9b 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -1,6 +1,6 @@ import {useEffect, useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; -import {Button, FixedButton, Input, MainLayout, Text, Title, TopNav} from 'haengdong-design'; +import {Button, FixedButton, Flex, Input, MainLayout, Text, Title, TopNav} from 'haengdong-design'; import {CopyToClipboard} from 'react-copy-to-clipboard'; import {css} from '@emotion/react'; @@ -30,10 +30,15 @@ const CompleteCreateEventPage = () => { return ( <MainLayout> <TopNav children={<></>} /> - <Title title="행사 개시" description="행사가 성공적으로 개시됐어요 :)" /> + <Title + title="행사 개시" + description="행사가 성공적으로 개시됐어요 :) 행사 링크를 통해서 지출 내역 공유와 참여자 관리가 가능해요." + /> <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem', margin: '0 1rem'})}> - <Text textColor="gray">행사 링크를 통해서 지출 내역 공유와 참여자 관리가 가능해요.</Text> - <Text textColor="primary">관리를 위해서 행사 링크를 복사 후 보관해 주세요.</Text> + <Flex flexDirection="column"> + <Text textColor="gray">링크가 없으면 페이지에 접근할 수 없어요.</Text> + <Text textColor="primary">관리를 위해서 행사 링크를 복사 후 보관해 주세요.</Text> + </Flex> <Input value={`haengdong.pro${ROUTER_URLS.event}/${url}/home`} disabled /> <CopyToClipboard @@ -43,8 +48,8 @@ const CompleteCreateEventPage = () => { showingTime: 3000, message: '링크가 복사되었어요 :) \n링크를 절대 분실하지 마세요!', type: 'confirm', - position: 'top', - top: '2rem', + position: 'bottom', + bottom: '14rem', }) } > diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index d7b7563dc..3d1b3ddfe 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -8,6 +8,9 @@ import useEventId from '@hooks/useEventId/useEventId'; import {ModalBasedOnMemberCount} from '@components/Modal/index'; import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; +import {useNavigate} from 'react-router-dom'; +import useAuth from '@hooks/useAuth'; +import {ROUTER_URLS} from '@constants/routerUrls'; const AdminPage = () => { const [isOpenFixedButtonBottomSheet, setIsOpenFixedBottomBottomSheet] = useState(false); @@ -18,17 +21,29 @@ const AdminPage = () => { const [eventName, setEventName] = useState(' '); const {getTotalPrice, allMemberList} = useStepList(); const {eventId} = useEventId(); + const {postAuthentication} = useAuth(); + const navigate = useNavigate(); // TODO: (@weadie) 아래 로직을 훅으로 분리합니다. useEffect(() => { if (eventId === '') return; + const postAuth = async () => { + try { + await postAuthentication({eventId: eventId}); + } catch (error) { + console.log(error); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + } + }; + const getEventName = async () => { - const {eventName} = await requestGetEventName({eventId: eventId ?? ''}); + const {eventName} = await requestGetEventName({eventId: eventId}); setEventName(eventName); }; + postAuth(); getEventName(); }, [eventId]); diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index a23341d4f..d40503703 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,19 +1,19 @@ -import {useEffect, useState} from 'react'; +import {useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back, Switch} from 'haengdong-design'; import validateEventPassword from '@utils/validate/validateEventPassword'; -import {requestPostNewEvent} from '@apis/request/event'; import useEventId from '@hooks/useEventId/useEventId'; -import useEvent from '@hooks/useEvent'; import useAuth from '@hooks/useAuth'; +import useNavSwitch from '@hooks/useNavSwitch'; import RULE from '@constants/rule'; import {ROUTER_URLS} from '@constants/routerUrls'; const EventLoginPage = () => { const [password, setPassword] = useState(''); + const {nav, paths, onChange} = useNavSwitch(); const [errorMessage, setErrorMessage] = useState(''); const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); @@ -45,14 +45,16 @@ const EventLoginPage = () => { setErrorMessage(validation.errorMessage ?? ''); } }; + return ( <MainLayout> <TopNav> - <Back /> + <Switch value={nav} values={paths} onChange={onChange} /> + {/* <Back /> */} </TopNav> <Title title="행사 비밀번호 입력" - description="관리를 위해선 비밀번호가 필요해요. \n행사 생성 시 설정한 4 자리의 숫자 비밀번호를 입력해 주세요." + description="관리를 위해선 비밀번호가 필요해요. 행사 생성 시 설정한 4 자리의 숫자 비밀번호를 입력해 주세요." /> <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> <LabelInput diff --git a/client/src/router.tsx b/client/src/router.tsx index 6419908aa..52d6da760 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -4,6 +4,7 @@ import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import SetEventPasswordPage from '@pages/CreateEventPage/SetEventPasswordPage'; +import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; import {CompleteCreateEventPage, SetEventNamePage} from '@pages/CreateEventPage'; import {MainPage} from '@pages/MainPage'; @@ -35,6 +36,10 @@ const router = createBrowserRouter([ path: ROUTER_URLS.eventCreateComplete, element: <CompleteCreateEventPage />, }, + { + path: ROUTER_URLS.eventLogin, + element: <EventLoginPage />, + }, { path: ROUTER_URLS.event, element: <EventPage />, diff --git a/client/webpack.dev.mjs b/client/webpack.dev.mjs index bfe53d51b..c97dc0857 100644 --- a/client/webpack.dev.mjs +++ b/client/webpack.dev.mjs @@ -3,7 +3,6 @@ import {merge} from 'webpack-merge'; import Dotenv from 'dotenv-webpack'; import common from './webpack.common.mjs'; import {fileURLToPath} from 'url'; -import {sentryWebpackPlugin} from '@sentry/webpack-plugin'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); From c2dde5d12108b205010569781831a0ab237b1c4e Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:24:29 +0900 Subject: [PATCH 140/273] =?UTF-8?q?feat:=20=EB=8D=B0=EB=AA=A8=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=EB=A5=BC=20=EC=9C=84=ED=95=B4=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=95=BD=EA=B0=84=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 --- client/src/pages/EventPage/AdminPage/AdminPage.tsx | 6 ++++-- client/src/pages/MainPage/MainPage.tsx | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 3d1b3ddfe..6f70d9d1c 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,5 +1,6 @@ import {useEffect, useState} from 'react'; import {Title, FixedButton, ListButton} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; import {useStepList} from '@hooks/useStepList/useStepList'; @@ -7,11 +8,12 @@ import {requestGetEventName} from '@apis/request/event'; import useEventId from '@hooks/useEventId/useEventId'; import {ModalBasedOnMemberCount} from '@components/Modal/index'; -import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; -import {useNavigate} from 'react-router-dom'; import useAuth from '@hooks/useAuth'; + import {ROUTER_URLS} from '@constants/routerUrls'; +import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; + const AdminPage = () => { const [isOpenFixedButtonBottomSheet, setIsOpenFixedBottomBottomSheet] = useState(false); const [order, setOrder] = useState<number>(1); diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index b216e50c6..682a9c836 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -9,7 +9,7 @@ const MainPage = () => { return ( <MainLayout> <TopNav children={<></>} /> - <Title title="행동대장" description="랜딩페이지입니다." /> + <Title title="행동대장" description="데모데이 ~~ 시연 ~~~~~! 페이지입니다." /> <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateName)}>행사 생성하기</FixedButton> </MainLayout> ); From eb286ba4ec2390216c3e46ecd900f769b8e86b6f Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 9 Aug 2024 11:16:06 +0900 Subject: [PATCH 141/273] =?UTF-8?q?fix:=20import=20=EA=B0=80=20=EC=95=88?= =?UTF-8?q?=EB=90=98=EC=96=B4=EC=9E=88=EB=8A=94=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#293)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/webpack.dev.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/client/webpack.dev.mjs b/client/webpack.dev.mjs index c97dc0857..bfe53d51b 100644 --- a/client/webpack.dev.mjs +++ b/client/webpack.dev.mjs @@ -3,6 +3,7 @@ import {merge} from 'webpack-merge'; import Dotenv from 'dotenv-webpack'; import common from './webpack.common.mjs'; import {fileURLToPath} from 'url'; +import {sentryWebpackPlugin} from '@sentry/webpack-plugin'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); From cf6e22303b44c49289266de3ba2f4705d52dd270 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Mon, 12 Aug 2024 15:48:45 +0900 Subject: [PATCH 142/273] =?UTF-8?q?fix:=20=EC=9D=B8=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=EC=A3=BC=20=EA=B2=80=EC=83=89=20=EC=9D=B8=ED=92=8B=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20(#299)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 --- HDesign/src/components/Search/Search.tsx | 4 ++-- .../AddMemberActionListModalContent/OutMember.tsx | 2 +- client/src/hooks/useSearchInMemberList.ts | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/HDesign/src/components/Search/Search.tsx b/HDesign/src/components/Search/Search.tsx index 410a0bc97..58c292cc4 100644 --- a/HDesign/src/components/Search/Search.tsx +++ b/HDesign/src/components/Search/Search.tsx @@ -21,9 +21,9 @@ const Search = ({isShowTargetInput, matchItems, onMatchItemClick, children}: Rea <ul css={searchTermsStyle(theme)}> <Flex flexDirection="column" gap="0.5rem"> {matchItems.map((matchItem, index) => ( - <li key={`${matchItems}-${index}`}> + <li key={`${matchItem}-${index}`}> <button type="button" css={searchTermStyle(theme)} onClick={() => onMatchItemClick(matchItem)}> - {matchItems} + {matchItem} </button> </li> ))} diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx index a3757aec3..f83ac9085 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -27,7 +27,7 @@ const OutMember = ({dynamicProps}: OutMemberProps) => { return inputList.map(({value, index}) => ( <Search - key={`${value}-${index}`} + key={index} isShowTargetInput={currentInputIndex === index} matchItems={filteredInMemberList} onMatchItemClick={(term: string) => chooseMember(currentInputIndex, term)} diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index bd1fe180e..a1bdf487c 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -43,6 +43,7 @@ const useSearchInMemberList = ( if (keyword.trim() === '') return []; const MatchItems = currentInMemberList.map(({name}) => name); + return MatchItems.filter( matchItem => matchItem.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1, ).slice(0, 3); From c3726619b629eb2ec127a736dc0507150c150a73 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Mon, 12 Aug 2024 15:51:22 +0900 Subject: [PATCH 143/273] =?UTF-8?q?chore:=20hooks=ED=8F=B4=EB=8D=94=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EC=A0=95=EB=A6=AC=20(#312)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 --- client/package-lock.json | 114 +++++++++--------- client/package.json | 4 +- client/src/apis/useFetch.ts | 5 +- .../MemberReportList/MemberReportList.tsx | 2 +- .../AddBillActionListModalContent.tsx | 2 +- .../AddMemberActionListModalContent.tsx | 2 +- .../DeleteMemberActionModal.tsx | 2 +- .../SetInitialMemberListModal.tsx | 2 +- client/src/components/StepList/StepList.tsx | 2 +- .../useDeleteMemberAction.tsx | 10 +- .../src/hooks/{useEventId => }/useEventId.tsx | 0 .../usePutAndDeleteBillAction.ts | 4 +- .../hooks/usePutAndDeleteBillAction/index.ts | 1 - client/src/hooks/useSearchInMemberList.ts | 2 +- .../useSearchMemberReportList.tsx | 3 +- client/src/hooks/useSetAllMemberList.tsx | 4 +- .../hooks/{useStepList => }/useStepList.tsx | 3 +- .../pages/EventPage/AdminPage/AdminPage.tsx | 4 +- .../EventPage/AdminPage/EventLoginPage.tsx | 2 +- .../src/pages/EventPage/EventPageLayout.tsx | 3 +- .../src/pages/EventPage/HomePage/HomePage.tsx | 5 +- client/src/types/serviceType.ts | 2 +- 22 files changed, 90 insertions(+), 88 deletions(-) rename client/src/hooks/{useDeleteMemberAction => }/useDeleteMemberAction.tsx (93%) rename client/src/hooks/{useEventId => }/useEventId.tsx (100%) rename client/src/hooks/{usePutAndDeleteBillAction => }/usePutAndDeleteBillAction.ts (96%) delete mode 100644 client/src/hooks/usePutAndDeleteBillAction/index.ts rename client/src/hooks/{useSearchMemberReportList => }/useSearchMemberReportList.tsx (96%) rename client/src/hooks/{useStepList => }/useStepList.tsx (98%) diff --git a/client/package-lock.json b/client/package-lock.json index 21e5093d9..6928db569 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", - "@sentry/react": "^8.24.0", + "@sentry/react": "^8.25.0", "haengdong-design": "^0.1.66", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", @@ -2518,54 +2518,54 @@ } }, "node_modules/@sentry-internal/browser-utils": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.24.0.tgz", - "integrity": "sha512-U5dVZ4JM+UeN3YWBUHZcNLF038C3ccTTsTICIw+zfCQbpPhPms8DOEDVpd0So18XoNDzYmLo07hC1BwByRAfGw==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", + "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", "dependencies": { - "@sentry/core": "8.24.0", - "@sentry/types": "8.24.0", - "@sentry/utils": "8.24.0" + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/feedback": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.24.0.tgz", - "integrity": "sha512-0tWRp8SOSTSPTViRJnB6+HHixFgkEWjKPciuLsAZkobRhi+VVedPj3zVztORy5AvARGr6AgyVSdnviilcrKl6g==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", + "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", "dependencies": { - "@sentry/core": "8.24.0", - "@sentry/types": "8.24.0", - "@sentry/utils": "8.24.0" + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.24.0.tgz", - "integrity": "sha512-+3d+3Ln7iDOZo2wOBv7EWojVHigEskjKsz8vR3WFdxYyue8e3zPQ/xg/t9A6BtEVRPQsEyhM3oN6LyjqFv2nfg==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", + "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", "dependencies": { - "@sentry-internal/browser-utils": "8.24.0", - "@sentry/core": "8.24.0", - "@sentry/types": "8.24.0", - "@sentry/utils": "8.24.0" + "@sentry-internal/browser-utils": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.24.0.tgz", - "integrity": "sha512-MI+j9tUab1d5oer2xKQ2lxdXSzBeZ1DF2dwlVxQDOfSAQqRfZJpmLcmSPb6M+GJsf2xHg6n4dAQvWQuM0qGQPQ==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", + "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", "dependencies": { - "@sentry-internal/replay": "8.24.0", - "@sentry/core": "8.24.0", - "@sentry/types": "8.24.0", - "@sentry/utils": "8.24.0" + "@sentry-internal/replay": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" }, "engines": { "node": ">=14.18" @@ -2581,17 +2581,17 @@ } }, "node_modules/@sentry/browser": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.24.0.tgz", - "integrity": "sha512-WdCLUoMAE0ZWsZDb3G/FQI5YgkH59VVEpnPqrWI08m2KuqLz8eU724JZvNzaDv/L2yzksgS4HDDUXkNRzDeCrQ==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", + "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", "dependencies": { - "@sentry-internal/browser-utils": "8.24.0", - "@sentry-internal/feedback": "8.24.0", - "@sentry-internal/replay": "8.24.0", - "@sentry-internal/replay-canvas": "8.24.0", - "@sentry/core": "8.24.0", - "@sentry/types": "8.24.0", - "@sentry/utils": "8.24.0" + "@sentry-internal/browser-utils": "8.25.0", + "@sentry-internal/feedback": "8.25.0", + "@sentry-internal/replay": "8.25.0", + "@sentry-internal/replay-canvas": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" }, "engines": { "node": ">=14.18" @@ -2803,26 +2803,26 @@ } }, "node_modules/@sentry/core": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.24.0.tgz", - "integrity": "sha512-nyy7po78Ef5KNzehHJCCyLGGR/FceHyw2IRzDQUVD6M4tos8G1OML1gcnALChWhyeq1SIoDsC1ofxFlbkIWuog==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", + "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", "dependencies": { - "@sentry/types": "8.24.0", - "@sentry/utils": "8.24.0" + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/react": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.24.0.tgz", - "integrity": "sha512-UaNmGEtYUFMoE1lKlsedOYGvQX72/A+/CiDg5umQwwS33XfGY4geh3zMo3jjEKTjhR1T5gofBz74sXnTCyrW4A==", - "dependencies": { - "@sentry/browser": "8.24.0", - "@sentry/core": "8.24.0", - "@sentry/types": "8.24.0", - "@sentry/utils": "8.24.0", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", + "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "dependencies": { + "@sentry/browser": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0", "hoist-non-react-statics": "^3.3.2" }, "engines": { @@ -2833,19 +2833,19 @@ } }, "node_modules/@sentry/types": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.24.0.tgz", - "integrity": "sha512-5QWXARoFrvTvnS19ip+ha0x4nWIv/RvoCTnqCsgrNTjypbk1+KMSMQQhGMo8OuEBFhdGyTs1BqfxVV82URHh3w==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", + "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", "engines": { "node": ">=14.18" } }, "node_modules/@sentry/utils": { - "version": "8.24.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.24.0.tgz", - "integrity": "sha512-AGo5PldxCJYn3g0IYXeBkeALNa+NieJaaCDpYyzrKAFdxoA6Qp+Z/wmN9m5BYZ9eHx9N+xMOoz2aIh4hG48VbQ==", + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", + "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", "dependencies": { - "@sentry/types": "8.24.0" + "@sentry/types": "8.25.0" }, "engines": { "node": ">=14.18" diff --git a/client/package.json b/client/package.json index a6f7e4425..7d486f6a9 100644 --- a/client/package.json +++ b/client/package.json @@ -8,7 +8,7 @@ "dev": "NODE_ENV=development webpack server --open --config webpack.dev.mjs", "build": "NODE_ENV=production webpack --config webpack.prod.mjs", "build-dev": "NODE_ENV=development webpack --config webpack.dev.mjs", - "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", + "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" }, "keywords": [], @@ -51,7 +51,7 @@ }, "dependencies": { "@emotion/react": "^11.11.4", - "@sentry/react": "^8.24.0", + "@sentry/react": "^8.25.0", "haengdong-design": "^0.1.66", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts index 253f92951..4ca483206 100644 --- a/client/src/apis/useFetch.ts +++ b/client/src/apis/useFetch.ts @@ -1,7 +1,7 @@ import {useState} from 'react'; import {NavigateFunction, useNavigate} from 'react-router-dom'; -import useEventId from '@hooks/useEventId/useEventId'; +import useEventId from '@hooks/useEventId'; import sendLogToSentry from '@utils/sendLogToSentry'; @@ -31,11 +31,9 @@ export const useFetch = () => { error instanceof FetchError ? error.errorBody : {errorCode: error.name, message: error.message}; setError(errorBody); - console.log('???'); captureError(error, navigate, eventId); } else { setError({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); - console.log('!!!'); captureError(new Error(UNKNOWN_ERROR), navigate, eventId); // 에러를 throw 해 에러 바운더리로 보냅니다. 따라서 에러 이름은 중요하지 않음 @@ -55,7 +53,6 @@ const captureError = async (error: Error, navigate: NavigateFunction, eventId: s const errorBody: ServerError = error instanceof FetchError ? error.errorBody : {message: error.message, errorCode: error.name}; - console.log(errorBody); switch (errorBody?.errorCode) { case 'INTERNAL_SERVER_ERROR': sendLogToSentry({error, errorBody, level: 'fatal'}); diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx index 1004540fa..ac4cd5e5c 100644 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -1,7 +1,7 @@ import {ExpenseList, Flex, Input} from 'haengdong-design'; import React, {useState} from 'react'; -import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; +import useSearchMemberReportList from '@hooks/useSearchMemberReportList'; const MemberReportList = () => { const [name, setName] = useState(''); diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index c59388472..b4dd7a6fb 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -1,8 +1,8 @@ import {FixedButton, LabelGroupInput} from 'haengdong-design'; -import {useStepList} from '@hooks/useStepList/useStepList'; import validatePurchase from '@utils/validate/validatePurchase'; +import {useStepList} from '@hooks/useStepList'; import useDynamicBillActionInput from '@hooks/useDynamicBillActionInput'; import style from './AddBillActionListModalContent.style'; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index 8d84993ab..5e63b4940 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -2,9 +2,9 @@ import type {MemberType} from 'types/serviceType'; import {FixedButton, LabelGroupInput} from 'haengdong-design'; -import {useStepList} from '@hooks/useStepList/useStepList'; import validateMemberName from '@utils/validate/validateMemberName'; +import {useStepList} from '@hooks/useStepList'; import useDynamicInput from '@hooks/useDynamicInput'; import style from './AddMemberActionListModalContent.style'; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx index d1c0c2556..e93354beb 100644 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -2,7 +2,7 @@ import type {MemberAction, MemberType} from 'types/serviceType'; import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; -import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; +import useDeleteMemberAction from '@hooks/useDeleteMemberAction'; import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index 070ff7cd1..be6ad6b87 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -1,8 +1,8 @@ import {Text, BottomSheet, FixedButton, LabelGroupInput} from 'haengdong-design'; -import {useStepList} from '@hooks/useStepList/useStepList'; import validateMemberName from '@utils/validate/validateMemberName'; +import {useStepList} from '@hooks/useStepList'; import useDynamicInput from '@hooks/useDynamicInput'; import { diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 1aeb7888e..9119bda97 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,6 +1,6 @@ import {Flex} from 'haengdong-design'; -import {useStepList} from '@hooks/useStepList/useStepList'; +import {useStepList} from '@hooks/useStepList'; import Step from './Step'; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction.tsx similarity index 93% rename from client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx rename to client/src/hooks/useDeleteMemberAction.tsx index 3e68d5b99..123e78daf 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction.tsx @@ -3,9 +3,10 @@ import type {MemberAction} from 'types/serviceType'; import {useState} from 'react'; import {useToast} from '@components/Toast/ToastProvider'; -import useEventId from '@hooks/useEventId/useEventId'; import {requestDeleteMemberAction} from '@apis/request/member'; -import {useStepList} from '@hooks/useStepList/useStepList'; + +import useEventId from '@hooks/useEventId'; +import {useStepList} from '@hooks/useStepList'; const useDeleteMemberAction = ( memberActionList: MemberAction[], @@ -77,7 +78,10 @@ const useDeleteMemberAction = ( // 현재 선택된 액션의 인덱스를 구해서 뒤의 동일인물의 액션이 있는지를 파악하는 기능 const isExistSameMemberFromAfterStep = (memberAction: MemberAction) => { - const memberActionList = stepList.filter(step => step.type !== 'BILL').flatMap(({actions}) => actions); + const memberActionList = stepList + .filter(step => step.type !== 'BILL') + .map(({actions}) => actions) + .flat(); const currentActionIndex = memberActionList.findIndex(action => action.actionId === memberAction.actionId); const memberActionListAfterCurrentAction = memberActionList.slice(Math.max(currentActionIndex - 1, 0)); const memberNameList = memberActionListAfterCurrentAction.map(({name}) => name); diff --git a/client/src/hooks/useEventId/useEventId.tsx b/client/src/hooks/useEventId.tsx similarity index 100% rename from client/src/hooks/useEventId/useEventId.tsx rename to client/src/hooks/useEventId.tsx diff --git a/client/src/hooks/usePutAndDeleteBillAction/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts similarity index 96% rename from client/src/hooks/usePutAndDeleteBillAction/usePutAndDeleteBillAction.ts rename to client/src/hooks/usePutAndDeleteBillAction.ts index 50052e08d..60b719964 100644 --- a/client/src/hooks/usePutAndDeleteBillAction/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -4,9 +4,9 @@ import {useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; import {requestDeleteBillAction, requestPutBillAction} from '@apis/request/bill'; -import useEventId from '@hooks/useEventId/useEventId'; -import {useStepList} from '@hooks/useStepList/useStepList'; +import useEventId from '@hooks/useEventId'; +import {useStepList} from '@hooks/useStepList'; import {BillInputType, InputPair} from '@hooks/useDynamicBillActionInput'; import ERROR_MESSAGE from '@constants/errorMessage'; diff --git a/client/src/hooks/usePutAndDeleteBillAction/index.ts b/client/src/hooks/usePutAndDeleteBillAction/index.ts deleted file mode 100644 index c8c82acf9..000000000 --- a/client/src/hooks/usePutAndDeleteBillAction/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as usePutAndDeleteBillAction} from './usePutAndDeleteBillAction'; diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index a1bdf487c..d66252b79 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -4,7 +4,7 @@ import {requestGetCurrentInMemberList} from '@apis/request/member'; import {useFetch} from '@apis/useFetch'; -import useEventId from './useEventId/useEventId'; +import useEventId from './useEventId'; export type ReturnUseSearchInMemberList = { currentInputIndex: number; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList.tsx similarity index 96% rename from client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx rename to client/src/hooks/useSearchMemberReportList.tsx index e7c0d7626..85f00c174 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList.tsx @@ -3,7 +3,8 @@ import type {MemberReport} from 'types/serviceType'; import {useEffect, useState} from 'react'; import {requestGetMemberReportList} from '@apis/request/report'; -import useEventId from '@hooks/useEventId/useEventId'; + +import useEventId from '@hooks/useEventId'; type UseSearchMemberReportListParams = { name: string; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index 51d50fa53..179b226d5 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -5,8 +5,8 @@ import {MemberChange, requestDeleteAllMemberList, requestPutAllMemberList} from import {useFetch} from '@apis/useFetch'; -import useEventId from './useEventId/useEventId'; -import {useStepList} from './useStepList/useStepList'; +import useEventId from './useEventId'; +import {useStepList} from './useStepList'; interface UseSetAllMemberListProps { validateFunc: (name: string) => ValidateResult; diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList.tsx similarity index 98% rename from client/src/hooks/useStepList/useStepList.tsx rename to client/src/hooks/useStepList.tsx index 6ca12e22b..41bb7390c 100644 --- a/client/src/hooks/useStepList/useStepList.tsx +++ b/client/src/hooks/useStepList.tsx @@ -2,11 +2,12 @@ import type {MemberType, Bill, BillAction, BillStep, MemberStep} from 'types/ser import {PropsWithChildren, createContext, useContext, useEffect, useState} from 'react'; -import useEventId from '@hooks/useEventId/useEventId'; import {requestPostBillList} from '@apis/request/bill'; import {requestGetAllMemberList, requestPostMemberList} from '@apis/request/member'; import {requestGetStepList} from '@apis/request/stepList'; +import useEventId from '@hooks/useEventId'; + import {useFetch} from '@apis/useFetch'; interface StepListContextProps { diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 6f70d9d1c..3ffadb101 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -3,11 +3,11 @@ import {Title, FixedButton, ListButton} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; -import {useStepList} from '@hooks/useStepList/useStepList'; import {requestGetEventName} from '@apis/request/event'; -import useEventId from '@hooks/useEventId/useEventId'; import {ModalBasedOnMemberCount} from '@components/Modal/index'; +import {useStepList} from '@hooks/useStepList'; +import useEventId from '@hooks/useEventId'; import useAuth from '@hooks/useAuth'; import {ROUTER_URLS} from '@constants/routerUrls'; diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index d40503703..fda0d841c 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -3,8 +3,8 @@ import {useLocation, useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back, Switch} from 'haengdong-design'; import validateEventPassword from '@utils/validate/validateEventPassword'; -import useEventId from '@hooks/useEventId/useEventId'; +import useEventId from '@hooks/useEventId'; import useAuth from '@hooks/useAuth'; import useNavSwitch from '@hooks/useNavSwitch'; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 1aa7797c3..d02fa1e70 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,8 +1,7 @@ import {MainLayout, TopNav, Switch} from 'haengdong-design'; import {Outlet, useMatch} from 'react-router-dom'; -import StepListProvider from '@hooks/useStepList/useStepList'; - +import StepListProvider from '@hooks/useStepList'; import useNavSwitch from '@hooks/useNavSwitch'; import {ROUTER_URLS} from '@constants/routerUrls'; diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 19227d404..cc989a7b3 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -3,10 +3,11 @@ import {useEffect, useState} from 'react'; import MemberReportList from '@components/MemberReportList/MemberReportList'; import StepList from '@components/StepList/StepList'; -import {useStepList} from '@hooks/useStepList/useStepList'; -import useEventId from '@hooks/useEventId/useEventId'; import {requestGetEventName} from '@apis/request/event'; +import {useStepList} from '@hooks/useStepList'; +import useEventId from '@hooks/useEventId'; + const HomePage = () => { const {getTotalPrice} = useStepList(); const {eventId} = useEventId(); diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts index 9b6fbe06f..a668ee694 100644 --- a/client/src/types/serviceType.ts +++ b/client/src/types/serviceType.ts @@ -28,7 +28,7 @@ export type BillStep = StepBase & { actions: BillAction[]; }; -// TODO: (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. +// (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. export type StepList = { steps: (MemberStep | BillStep)[]; }; From 53625873fd2c4f25877dfb4ad3939e034aa3612b Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Mon, 12 Aug 2024 15:54:19 +0900 Subject: [PATCH 144/273] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95=20(#315)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 --- client/src/hooks/useSetAllMemberList.tsx | 30 ++++++++++++------------ client/src/utils/isArraysEqual.ts | 16 +++++++++++++ 2 files changed, 31 insertions(+), 15 deletions(-) create mode 100644 client/src/utils/isArraysEqual.ts diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index 179b226d5..bb6a64ebb 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -5,6 +5,8 @@ import {MemberChange, requestDeleteAllMemberList, requestPutAllMemberList} from import {useFetch} from '@apis/useFetch'; +import isArraysEqual from '@utils/isArraysEqual'; + import useEventId from './useEventId'; import {useStepList} from './useStepList'; @@ -23,27 +25,17 @@ const useSetAllMemberList = ({ const [errorMessage, setErrorMessage] = useState(''); const [errorIndexList, setErrorIndexList] = useState<number[]>([]); const [canSubmit, setCanSubmit] = useState(false); + const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); + const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); const {refreshStepList} = useStepList(); const {eventId} = useEventId(); const {fetch} = useFetch(); useEffect(() => { - if (arraysEqual(editedAllMemberList, allMemberList)) { - setCanSubmit(false); - } else { - setCanSubmit(true); - } + setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); }, [editedAllMemberList]); - const arraysEqual = (arr1: string[], arr2: string[]) => { - if (arr1.length !== arr2.length) return false; - for (let i = 0; i < arr1.length; i++) { - if (arr1[i] !== arr2[i]) return false; - } - return true; - }; - const handleNameChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; const {isValid, errorMessage: validationResultMessage} = validateFunc(value); @@ -80,7 +72,8 @@ const useSetAllMemberList = ({ const handleClickDeleteButton = async (index: number) => { const memberToDelete = editedAllMemberList[index]; - await fetch(() => requestDeleteAllMemberList({eventId, memberName: memberToDelete})); + setDeleteMemberList(prev => [...prev, memberToDelete]); + setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); @@ -88,7 +81,14 @@ const useSetAllMemberList = ({ }; const handlePutAllMemberList = async () => { - const editedMemberName: MemberChange[] = allMemberList + // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) + if (deleteMemberList.length > 0) { + for (const deleteMember of deleteMemberList) { + await fetch(() => requestDeleteAllMemberList({eventId, memberName: deleteMember})); + } + } + + const editedMemberName: MemberChange[] = deleteInOriginal .map((originalName, index) => { if (editedAllMemberList[index] !== originalName) { return {before: originalName, after: editedAllMemberList[index]}; diff --git a/client/src/utils/isArraysEqual.ts b/client/src/utils/isArraysEqual.ts new file mode 100644 index 000000000..1f033eefc --- /dev/null +++ b/client/src/utils/isArraysEqual.ts @@ -0,0 +1,16 @@ +const isArraysEqual = (arr1: string[], arr2: string[]) => { + if (arr1.length !== arr2.length) return false; + + // 배열을 정렬한 후 비교 + const sortedArr1 = [...arr1].sort(); + const sortedArr2 = [...arr2].sort(); + + // 값은 모두 같으나 순서를 변경했을 시, false를 반환한다. + for (let i = 0; i < sortedArr1.length; i++) { + if (sortedArr1[i] !== sortedArr2[i]) return false; + } + + return true; +}; + +export default isArraysEqual; From 9a74f39e598062760d0f766bff56404b01d9f5a1 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:04:04 +0900 Subject: [PATCH 145/273] =?UTF-8?q?feat:=20=EC=B0=A8=EC=88=98=20=EB=A9=A4?= =?UTF-8?q?=EB=B2=84=20=ED=99=95=EC=9D=B8,=20useFetch=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?,=20BottomSheet=20=ED=99=9C=EC=84=B1=ED=99=94=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#311)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 --- .../DragHandleItemContainer.stories.tsx | 4 + .../DragHandleItemContainer.style.ts | 19 +++++ .../DragHandleItemContainer.tsx | 14 ++-- .../DragHandleItemContainer.type.ts | 4 + client/src/apis/useFetch.ts | 17 +++- .../MemberListInBillStep.style.ts | 10 +++ .../MemberListInBillStep.tsx | 53 ++++++++++++ .../Modal/MemberListInBillStep/index.ts | 1 + .../ModalBasedOnMemberCount.tsx | 10 +-- .../AddBillActionListModalContent.tsx | 13 ++- .../DeleteMemberActionModal.tsx | 3 +- .../SetActionModal/SetActionListModal.tsx | 7 +- .../src/components/StepList/BillStepItem.tsx | 80 ++++++++++++------- .../components/StepList/MemberStepItem.tsx | 3 +- client/src/hooks/useAuth.tsx | 4 +- client/src/hooks/useDeleteMemberAction.tsx | 30 ++++--- client/src/hooks/useEvent.tsx | 2 +- client/src/hooks/usePutAndDeleteBillAction.ts | 24 ++++-- client/src/hooks/useSearchInMemberList.ts | 2 +- .../src/hooks/useSearchMemberReportList.tsx | 6 +- client/src/hooks/useSetAllMemberList.tsx | 30 ++++--- client/src/hooks/useStepList.tsx | 18 +++-- .../pages/EventPage/AdminPage/AdminPage.tsx | 2 - .../src/pages/EventPage/EventPageLayout.tsx | 13 ++- 24 files changed, 262 insertions(+), 107 deletions(-) create mode 100644 client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts create mode 100644 client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx create mode 100644 client/src/components/Modal/MemberListInBillStep/index.ts diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx index 69d7e3b75..46c3db8a2 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx @@ -59,6 +59,10 @@ const meta = { topRightText: '8명', bottomLeftText: '총액', bottomRightText: '214,000 원', + onTopLeftTextClick: () => alert('왼쪽 위'), + onTopRightTextClick: () => alert('오른쪽 위'), + onBottomLeftTextClick: () => alert('왼쪽 아래'), + onBottomRightTextClick: () => alert('오른쪽 아래'), backgroundColor: 'white', children: ( <> diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts index 0054817fa..b5bab9422 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts @@ -13,3 +13,22 @@ export const containerStyle = (theme: Theme, backgroundColor: ColorKeys) => borderRadius: '0.75rem', backgroundColor: theme.colors[backgroundColor], }); + +export const topRightTextStyle = (theme: Theme) => + css({ + position: 'relative', + cursor: 'pointer', + + '&::after': { + position: 'absolute', + bottom: '0.125rem', + left: 0, + + width: '100%', + height: '0.03125rem', + + backgroundColor: theme.colors.gray, + + content: "''", + }, + }); diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx index c439b98c2..9bd54eacf 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx @@ -4,7 +4,7 @@ import {useTheme} from '@theme/HDesignProvider'; import Text from '../Text/Text'; import Flex from '../Flex/Flex'; -import {containerStyle} from './DragHandleItemContainer.style'; +import {containerStyle, topRightTextStyle} from './DragHandleItemContainer.style'; import {DragHandleItemContainerProps} from './DragHandleItemContainer.type'; export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ({ @@ -12,6 +12,10 @@ export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ( bottomLeftText, topRightText, bottomRightText, + onTopLeftTextClick, + onBottomLeftTextClick, + onTopRightTextClick, + onBottomRightTextClick, backgroundColor = 'white', children, ...htmlProps @@ -21,19 +25,19 @@ export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ( return ( <div css={containerStyle(theme, backgroundColor)} {...htmlProps}> <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> - <Text textColor="gray" size="captionBold"> + <Text textColor="gray" size="captionBold" onClick={onTopLeftTextClick}> {topLeftText} </Text> - <Text textColor="gray" size="caption"> + <Text textColor="gray" size="caption" onClick={onTopRightTextClick} css={topRightTextStyle(theme)}> {topRightText} </Text> </Flex> {children} <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> - <Text textColor="gray" size="captionBold"> + <Text textColor="gray" size="captionBold" onClick={onBottomLeftTextClick}> {bottomLeftText} </Text> - <Text textColor="gray" size="caption"> + <Text textColor="gray" size="caption" onClick={onBottomRightTextClick}> {bottomRightText} </Text> </Flex> diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts index c605e6e0c..1bf1129e4 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts @@ -6,9 +6,13 @@ export interface DragHandleItemContainerStyleProps { export interface DragHandleItemContainerCustomProps { topLeftText?: string; + onTopLeftTextClick?: () => void; bottomLeftText?: string; + onBottomLeftTextClick?: () => void; topRightText?: string; + onTopRightTextClick?: () => void; bottomRightText?: string; + onBottomRightTextClick?: () => void; } export type DragHandleItemContainerOptionProps = DragHandleItemContainerStyleProps & DragHandleItemContainerCustomProps; diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts index 4ca483206..12350e798 100644 --- a/client/src/apis/useFetch.ts +++ b/client/src/apis/useFetch.ts @@ -11,19 +11,29 @@ import {ROUTER_URLS} from '@constants/routerUrls'; import {ServerError, useError} from '../ErrorProvider'; import FetchError from '../errors/FetchError'; +type FetchProps<T> = { + queryFunction: () => Promise<T>; + onSuccess?: () => void; + onError?: () => void; +}; + export const useFetch = () => { const {setError, clearError} = useError(); const [loading, setLoading] = useState(false); const navigate = useNavigate(); const {eventId} = useEventId(); - const fetch = async <T>(queryFunction: () => Promise<T>): Promise<T> => { + const fetch = async <T>({queryFunction, onSuccess, onError}: FetchProps<T>): Promise<T> => { setLoading(true); clearError(); try { const result = await queryFunction(); + if (onSuccess) { + onSuccess(); + } + return result; } catch (error) { if (error instanceof Error) { @@ -31,6 +41,11 @@ export const useFetch = () => { error instanceof FetchError ? error.errorBody : {errorCode: error.name, message: error.message}; setError(errorBody); + + if (onError) { + onError(); + } + captureError(error, navigate, eventId); } else { setError({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts new file mode 100644 index 000000000..4bbefdba9 --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts @@ -0,0 +1,10 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1.5rem', +}); diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx new file mode 100644 index 000000000..e3579ab6b --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx @@ -0,0 +1,53 @@ +import type {MemberReport} from 'types/serviceType'; + +import {BottomSheet, FixedButton, Flex, Text} from 'haengdong-design'; + +import {bottomSheetStyle} from './MemberListInBillStep.style'; + +type MemberListInBillStepProps = { + stepName: string; + memberList: MemberReport[]; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; +}; + +const MemberListInBillStep = ({ + stepName, + memberList, + isOpenBottomSheet, + setIsOpenBottomSheet, +}: MemberListInBillStepProps) => { + const closeModal = () => setIsOpenBottomSheet(false); + + return ( + <BottomSheet isOpened={isOpenBottomSheet} onClose={closeModal}> + <div css={bottomSheetStyle}> + <Flex justifyContent="spaceBetween" alignItems="center" padding="0 0.5rem"> + <Text size="bodyBold" textColor="onTertiary">{`${stepName} 참석자`}</Text> + <Text size="bodyBold" textColor="gray">{`총 ${memberList.length}명`}</Text> + </Flex> + <Flex flexDirection="column" gap="0.5rem" padding="0 0.5rem"> + <ul> + {memberList.map(member => ( + <li key={member.name}> + <Flex padding="0.5rem 1rem" width="100%" justifyContent="spaceBetween"> + <Text size="bodyBold" textColor="onTertiary"> + {member.name} + </Text> + <Text size="body" textColor="black"> + {`${member.price.toLocaleString('ko-kr')} 원`} + </Text> + </Flex> + </li> + ))} + </ul> + </Flex> + </div> + <FixedButton variants="tertiary" onClick={closeModal}> + 닫기 + </FixedButton> + </BottomSheet> + ); +}; + +export default MemberListInBillStep; diff --git a/client/src/components/Modal/MemberListInBillStep/index.ts b/client/src/components/Modal/MemberListInBillStep/index.ts new file mode 100644 index 000000000..137df8c87 --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/index.ts @@ -0,0 +1 @@ +export {default as MemberListInBillStep} from './MemberListInBillStep'; diff --git a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx index 4799a92c2..51e33589b 100644 --- a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx +++ b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx @@ -4,7 +4,6 @@ interface ModalBasedOnMemberCountProps { allMemberList: string[]; isOpenBottomSheet: boolean; isOpenAllMemberListButton: boolean; - setOrder: React.Dispatch<React.SetStateAction<number>>; setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; setIsOpenAllMemberListButton: React.Dispatch<React.SetStateAction<boolean>>; } @@ -13,7 +12,6 @@ const ModalBasedOnMemberCount = ({ allMemberList, isOpenBottomSheet, isOpenAllMemberListButton, - setOrder, setIsOpenBottomSheet, setIsOpenAllMemberListButton, }: ModalBasedOnMemberCountProps) => { @@ -34,13 +32,7 @@ const ModalBasedOnMemberCount = ({ ); default: - return ( - <SetActionListModal - setOrder={setOrder} - setIsOpenBottomSheet={setIsOpenBottomSheet} - isOpenBottomSheet={isOpenBottomSheet} - /> - ); + return <SetActionListModal setIsOpenBottomSheet={setIsOpenBottomSheet} isOpenBottomSheet={isOpenBottomSheet} />; } }; diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index b4dd7a6fb..b07f02d4d 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -9,10 +9,9 @@ import style from './AddBillActionListModalContent.style'; interface AddBillActionListModalContentProps { setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; - setOrder: React.Dispatch<React.SetStateAction<number>>; } -const AddBillActionListModalContent = ({setIsOpenBottomSheet, setOrder}: AddBillActionListModalContentProps) => { +const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionListModalContentProps) => { const { inputPairList, inputRefList, @@ -24,11 +23,11 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet, setOrder}: AddBill const {addBill} = useStepList(); const handleSetPurchaseSubmit = () => { - setOrder(prev => prev + 1); - // TODO: (@weadie) 요청 실패시 오류 핸들 필요 - addBill(getFilledInputPairList().map(({title, price}) => ({title, price: Number(price)}))); // TODO: (@weadie) DTO같은게 다이내믹에 필요할까? - setIsOpenBottomSheet(false); + addBill( + getFilledInputPairList().map(({title, price}) => ({title, price: Number(price)})), + () => setIsOpenBottomSheet(false), + ); // TODO: (@weadie) DTO같은게 다이내믹에 필요할까? }; return ( @@ -62,7 +61,7 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet, setOrder}: AddBill </LabelGroupInput> </div> <FixedButton - // disabled={!(inputPairs.length - 1)} + disabled={!(inputPairList.length - 1)} variants={'primary'} children={'추가하기'} onClick={handleSetPurchaseSubmit} diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx index e93354beb..a509b5d54 100644 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -29,8 +29,7 @@ const DeleteMemberActionModal = ({ <div css={bottomSheetStyle}> <header css={bottomSheetHeaderStyle}> <Text size="bodyBold">{memberActionType === 'IN' ? '들어온' : '나간'} 인원 수정하기</Text> - {/* TODO: (@cookie): 텍스트 색 수정 필요 */} - <Text size="bodyBold">{`${aliveActionList.length}명`}</Text> + <Text size="bodyBold" textColor="gray">{`${aliveActionList.length}명`}</Text> </header> <ul css={inputGroupStyle}> {aliveActionList.map(member => ( diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx index 9b4b7facf..4a6ea10a6 100644 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -12,10 +12,9 @@ export type ActionType = '지출' | '인원'; interface SetActionModalContentProps { isOpenBottomSheet: boolean; setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; - setOrder: React.Dispatch<React.SetStateAction<number>>; } -const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet, setOrder}: SetActionModalContentProps) => { +const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetActionModalContentProps) => { const [action, setAction] = useState<ActionType>('지출'); const [inOutAction, setInOutAction] = useState<InOutType>('탈주'); @@ -37,9 +36,7 @@ const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet, setOrder}: )} </div> - {action === '지출' && ( - <AddBillActionListModalContent setIsOpenBottomSheet={setIsOpenBottomSheet} setOrder={setOrder} /> - )} + {action === '지출' && <AddBillActionListModalContent setIsOpenBottomSheet={setIsOpenBottomSheet} />} {action === '인원' && ( <AddMemberActionListModalContent inOutAction={inOutAction === '탈주' ? 'OUT' : 'IN'} diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index aeff34a2c..d819d4219 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -1,10 +1,12 @@ -import type {BillStep} from 'types/serviceType'; +import type {BillStep, MemberReport} from 'types/serviceType'; import {DragHandleItem, DragHandleItemContainer} from 'haengdong-design'; import {Fragment, useState} from 'react'; import {useOutletContext} from 'react-router-dom'; import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; +import {MemberListInBillStep} from '@components/Modal/MemberListInBillStep'; +import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; interface BillStepItemProps { step: BillStep; @@ -13,9 +15,11 @@ interface BillStepItemProps { } const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { - const isAdmin = useOutletContext<boolean>(); + const {isAdmin} = useOutletContext<EventPageContextProps>(); const [clickedIndex, setClickedIndex] = useState(-1); + const [isOpenMemberListInBillStep, setIsOpenMemberListInBillStep] = useState(false); + const stepName = `차`; const totalPrice = step.actions.reduce((acc, cur) => acc + cur.price, 0); const handleDragHandleItemClick = (index: number) => { @@ -23,33 +27,55 @@ const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, set setIsOpenBottomSheet(true); }; + const memberList: MemberReport[] = step.members.map(member => ({ + name: member, + price: totalPrice / step.members.length, + })); + + const handleTopRightTextClick = () => { + setIsOpenMemberListInBillStep(true); + }; + return ( - <DragHandleItemContainer - topLeftText={step.stepName} - topRightText={`${step.members.length}명`} - bottomLeftText="총액" - bottomRightText={`${totalPrice.toLocaleString('ko-kr')} 원`} - backgroundColor="white" - > - {step.actions.map((action, index) => ( - <Fragment key={action.actionId}> - <DragHandleItem - hasDragHandler={isAdmin} - prefix={action.name} - suffix={`${action.price.toLocaleString('ko-kr')} 원`} - backgroundColor="lightGrayContainer" - onClick={() => handleDragHandleItemClick(index)} - /> - {isOpenBottomSheet && clickedIndex === index && isAdmin && ( - <PutAndDeleteBillActionModal - billAction={action} - isBottomSheetOpened={isOpenBottomSheet} - setIsBottomSheetOpened={setIsOpenBottomSheet} + <> + <button style={{fontSize: '0.75rem'}} onClick={handleTopRightTextClick}> + 참여인원 확인 임시용 + </button> + <DragHandleItemContainer + topLeftText={stepName} + topRightText={`${step.members.length}명`} + bottomLeftText="총액" + bottomRightText={`${totalPrice.toLocaleString('ko-kr')} 원`} + backgroundColor="white" + > + {step.actions.map((action, index) => ( + <Fragment key={action.actionId}> + <DragHandleItem + hasDragHandler={isAdmin} + prefix={action.name} + suffix={`${action.price.toLocaleString('ko-kr')} 원`} + backgroundColor="lightGrayContainer" + onClick={() => handleDragHandleItemClick(index)} /> - )} - </Fragment> - ))} - </DragHandleItemContainer> + {isOpenBottomSheet && clickedIndex === index && isAdmin && ( + <PutAndDeleteBillActionModal + billAction={action} + isBottomSheetOpened={isOpenBottomSheet} + setIsBottomSheetOpened={setIsOpenBottomSheet} + /> + )} + </Fragment> + ))} + </DragHandleItemContainer> + {isOpenMemberListInBillStep && ( + <MemberListInBillStep + stepName={stepName} + memberList={memberList} + isOpenBottomSheet={isOpenMemberListInBillStep} + setIsOpenBottomSheet={setIsOpenMemberListInBillStep} + /> + )} + </> ); }; diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx index fa94eeaa6..a9abaea1a 100644 --- a/client/src/components/StepList/MemberStepItem.tsx +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -4,6 +4,7 @@ import {DragHandleItem} from 'haengdong-design'; import {useOutletContext} from 'react-router-dom'; import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMemberActionModal'; +import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; interface MemberStepItemProps { step: MemberStep; @@ -12,7 +13,7 @@ interface MemberStepItemProps { } const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { - const isAdmin = useOutletContext<boolean>(); + const {isAdmin} = useOutletContext<EventPageContextProps>(); return ( <> diff --git a/client/src/hooks/useAuth.tsx b/client/src/hooks/useAuth.tsx index a2295a41f..10ea3f973 100644 --- a/client/src/hooks/useAuth.tsx +++ b/client/src/hooks/useAuth.tsx @@ -6,11 +6,11 @@ const useAuth = () => { const {fetch} = useFetch(); const postAuthentication = async ({eventId}: RequestAuthentication) => { - return await fetch(() => requestAuthentication({eventId})); + return await fetch({queryFunction: () => requestAuthentication({eventId})}); }; const postLogin = async ({eventId, password}: RequestToken) => { - return await fetch(() => requestToken({eventId, password})); + return await fetch({queryFunction: () => requestToken({eventId, password})}); }; return {postAuthentication, postLogin}; diff --git a/client/src/hooks/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction.tsx index 123e78daf..0a2c0ac95 100644 --- a/client/src/hooks/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction.tsx @@ -8,6 +8,8 @@ import {requestDeleteMemberAction} from '@apis/request/member'; import useEventId from '@hooks/useEventId'; import {useStepList} from '@hooks/useStepList'; +import {useFetch} from '@apis/useFetch'; + const useDeleteMemberAction = ( memberActionList: MemberAction[], setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>, @@ -16,23 +18,22 @@ const useDeleteMemberAction = ( const [aliveActionList, setAliveActionList] = useState<MemberAction[]>(memberActionList); const {eventId} = useEventId(); const {showToast} = useToast(); + const {fetch} = useFetch(); const deleteMemberAction = async (actionId: number) => { - try { - await requestDeleteMemberAction({actionId, eventId}); - } catch (error) { - // TODO: (@cookie): 에러처리 백엔드에 맞게 나중에 메시지 설정 - // 원래는 백엔드가 만들어준 에러토큰을 이용해서 나눠서 보여주는 것이 맞지만 우리가 에러처리를 아무곳에서도 하지않아서 후추 - showToast({ - isClickToClose: true, - message: '멤버 삭제가 되지 않았어요 :(', - showingTime: 3000, - type: 'error', - bottom: '160px', - }); - } + await fetch({ + queryFunction: () => requestDeleteMemberAction({actionId, eventId}), + onSuccess: () => { + refreshStepList(); + setIsBottomSheetOpened(false); + }, + onError: () => { + setAliveActionList(memberActionList); + }, + }); }; + // TODO: (@cookie: 추후에 반복문으로 delete하는 것이 아니라 한 번에 모아서 delete 처리하기 (backend에 문의)) const deleteMemberActionList = async () => { const aliveActionIdList = aliveActionList.map(({actionId}) => actionId); const deleteMemberActionIdList = memberActionList @@ -42,9 +43,6 @@ const useDeleteMemberAction = ( for (const deleteMemberActionId of deleteMemberActionIdList) { await deleteMemberAction(deleteMemberActionId); } - - refreshStepList(); - setIsBottomSheetOpened(false); }; const addDeleteMemberAction = (memberAction: MemberAction) => { diff --git a/client/src/hooks/useEvent.tsx b/client/src/hooks/useEvent.tsx index c5cdcf933..13aee0b56 100644 --- a/client/src/hooks/useEvent.tsx +++ b/client/src/hooks/useEvent.tsx @@ -6,7 +6,7 @@ const useEvent = () => { const {fetch} = useFetch(); const createNewEvent = async ({eventName, password}: RequestPostNewEvent) => { - return await fetch<ResponsePostNewEvent>(() => requestPostNewEvent({eventName, password})); + return await fetch<ResponsePostNewEvent>({queryFunction: () => requestPostNewEvent({eventName, password})}); }; return {createNewEvent}; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 60b719964..445172f21 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -9,6 +9,8 @@ import useEventId from '@hooks/useEventId'; import {useStepList} from '@hooks/useStepList'; import {BillInputType, InputPair} from '@hooks/useDynamicBillActionInput'; +import {useFetch} from '@apis/useFetch'; + import ERROR_MESSAGE from '@constants/errorMessage'; const usePutAndDeleteBillAction = ( @@ -18,6 +20,7 @@ const usePutAndDeleteBillAction = ( ) => { const {eventId} = useEventId(); const {refreshStepList} = useStepList(); + const {fetch} = useFetch(); const [inputPair, setInputPair] = useState<InputPair>(initialValue); const [canSubmit, setCanSubmit] = useState(false); @@ -84,15 +87,24 @@ const usePutAndDeleteBillAction = ( event.preventDefault(); const {title, price} = inputPair; - await requestPutBillAction({eventId, actionId, title, price: Number(price)}); - refreshStepList(); - onClose(); + + await fetch({ + queryFunction: () => requestPutBillAction({eventId, actionId, title, price: Number(price)}), + onSuccess: () => { + refreshStepList(); + onClose(); + }, + }); }; const onDelete = async (actionId: number) => { - await requestDeleteBillAction({eventId, actionId}); - refreshStepList(); - onClose(); + await fetch({ + queryFunction: () => requestDeleteBillAction({eventId, actionId}), + onSuccess: () => { + refreshStepList(); + onClose(); + }, + }); }; return { diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index d66252b79..d8acfb00c 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -32,7 +32,7 @@ const useSearchInMemberList = ( if (eventId === '') return; const getCurrentInMembers = async () => { - const currentInMemberListFromServer = await fetch(() => requestGetCurrentInMemberList(eventId)); + const currentInMemberListFromServer = await fetch({queryFunction: () => requestGetCurrentInMemberList(eventId)}); setCurrentInMemberList(currentInMemberListFromServer.members); }; diff --git a/client/src/hooks/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList.tsx index 85f00c174..7dca34b68 100644 --- a/client/src/hooks/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList.tsx @@ -6,6 +6,8 @@ import {requestGetMemberReportList} from '@apis/request/report'; import useEventId from '@hooks/useEventId'; +import {useFetch} from '@apis/useFetch'; + type UseSearchMemberReportListParams = { name: string; }; @@ -14,6 +16,7 @@ const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { const [memberReportList, setMemberReportList] = useState<MemberReport[]>([]); const [memberReportSearchList, setMemberReportSearchList] = useState<MemberReport[]>([]); const {eventId} = useEventId(); + const {fetch} = useFetch(); useEffect(() => { const fetchMemberReportList = async () => { @@ -21,8 +24,7 @@ const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { // TODO: (@weadie) eventId에 의존하는 두 개의 훅에 대한 리펙토링 필요 if (eventId === '') return; - const memberReportListData = await requestGetMemberReportList({eventId}); - + const memberReportListData = await fetch({queryFunction: () => requestGetMemberReportList({eventId})}); setMemberReportList(memberReportListData); }; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index bb6a64ebb..c0c14c13a 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -72,19 +72,23 @@ const useSetAllMemberList = ({ const handleClickDeleteButton = async (index: number) => { const memberToDelete = editedAllMemberList[index]; - setDeleteMemberList(prev => [...prev, memberToDelete]); - setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - - setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - - refreshStepList(); + await fetch({ + queryFunction: () => requestDeleteAllMemberList({eventId, memberName: memberToDelete}), + onSuccess: () => { + setDeleteMemberList(prev => [...prev, memberToDelete]); + setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + + setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + refreshStepList(); + }, + }); }; const handlePutAllMemberList = async () => { // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) if (deleteMemberList.length > 0) { for (const deleteMember of deleteMemberList) { - await fetch(() => requestDeleteAllMemberList({eventId, memberName: deleteMember})); + await fetch({queryFunction: () => requestDeleteAllMemberList({eventId, memberName: deleteMember})}); } } @@ -97,11 +101,13 @@ const useSetAllMemberList = ({ }) .filter(item => item !== null); // null인 항목을 필터링하여 제거 - await fetch(() => requestPutAllMemberList({eventId, members: editedMemberName})); - - refreshStepList(); - - handleCloseAllMemberListModal(); + await fetch({ + queryFunction: () => requestPutAllMemberList({eventId, members: editedMemberName}), + onSuccess: () => { + refreshStepList(); + handleCloseAllMemberListModal(); + }, + }); }; const changeErrorIndex = (index: number) => { diff --git a/client/src/hooks/useStepList.tsx b/client/src/hooks/useStepList.tsx index 41bb7390c..d0f31abaa 100644 --- a/client/src/hooks/useStepList.tsx +++ b/client/src/hooks/useStepList.tsx @@ -14,7 +14,7 @@ interface StepListContextProps { stepList: (BillStep | MemberStep)[]; allMemberList: string[]; getTotalPrice: () => number; - addBill: (billList: Bill[]) => Promise<void>; + addBill: (billList: Bill[], onSuccess: () => void) => Promise<void>; updateMemberList: ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => Promise<void>; refreshStepList: () => Promise<void>; } @@ -37,7 +37,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { }, [eventId]); const refreshStepList = async () => { - const stepList = await fetch(() => requestGetStepList({eventId})); + const stepList = await fetch({queryFunction: () => requestGetStepList({eventId})}); getAllMemberList(); setStepList(stepList); @@ -45,7 +45,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { const updateMemberList = async ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => { try { - await fetch(() => requestPostMemberList({eventId, type, memberNameList})); + await fetch({queryFunction: () => requestPostMemberList({eventId, type, memberNameList})}); refreshStepList(); } catch (error) { @@ -59,11 +59,15 @@ const StepListProvider = ({children}: PropsWithChildren) => { setAllMemberList(allMembers.memberNames); }; - const addBill = async (billList: Bill[]) => { + const addBill = async (billList: Bill[], onSuccess: () => void) => { // TODO: (@weadie) 에러 처리 - await fetch(() => requestPostBillList({eventId, billList})); - - refreshStepList(); + await fetch({ + queryFunction: () => requestPostBillList({eventId, billList}), + onSuccess: () => { + refreshStepList(); + onSuccess(); + }, + }); }; const calculateBillSum = (actions: BillAction[]) => { diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 3ffadb101..fefc851ed 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -16,7 +16,6 @@ import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style' const AdminPage = () => { const [isOpenFixedButtonBottomSheet, setIsOpenFixedBottomBottomSheet] = useState(false); - const [order, setOrder] = useState<number>(1); const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); // TODO: (@weadie) eventName이 새로고침시 공간이 없다가 생겨나 레이아웃이 움직이는 문제 @@ -79,7 +78,6 @@ const AdminPage = () => { {isOpenFixedButtonBottomSheet && ( <ModalBasedOnMemberCount allMemberList={allMemberList} - setOrder={setOrder} setIsOpenBottomSheet={setIsOpenFixedBottomBottomSheet} isOpenBottomSheet={isOpenFixedButtonBottomSheet} isOpenAllMemberListButton={isOpenAllMemberListButton} diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index d02fa1e70..49b1145be 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,22 +1,33 @@ import {MainLayout, TopNav, Switch} from 'haengdong-design'; import {Outlet, useMatch} from 'react-router-dom'; +import {useState} from 'react'; import StepListProvider from '@hooks/useStepList'; import useNavSwitch from '@hooks/useNavSwitch'; import {ROUTER_URLS} from '@constants/routerUrls'; +export type EventPageContextProps = { + isAdmin: boolean; +}; + const EventPageLayout = () => { const {nav, paths, onChange} = useNavSwitch(); + + const [order, setOrder] = useState<number>(1); const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; + const outletContext: EventPageContextProps = { + isAdmin, + }; + return ( <StepListProvider> <MainLayout backgroundColor="gray"> <TopNav> <Switch value={nav} values={paths} onChange={onChange} /> </TopNav> - <Outlet context={isAdmin} /> + <Outlet context={outletContext} /> </MainLayout> </StepListProvider> ); From 599d921ea051d93d723e3f25145ace4e574a9bcf Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:26:47 +0900 Subject: [PATCH 146/273] =?UTF-8?q?feat:=20=EC=B0=B8=EC=97=AC=20=EC=9D=B8?= =?UTF-8?q?=EC=9B=90=20=ED=99=95=EC=9D=B8=20=EC=9E=84=EC=8B=9C=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=82=AD=EC=A0=9C=20(#318)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 --- client/package-lock.json | 8 ++++---- client/package.json | 2 +- .../PutAndDeleteBillActionModal.tsx | 2 +- client/src/components/StepList/BillStepItem.tsx | 4 +--- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 6928db569..fef8ea21d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", - "haengdong-design": "^0.1.66", + "haengdong-design": "^0.1.67", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -7250,9 +7250,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.66", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.66.tgz", - "integrity": "sha512-wNrL/N2SLxQg+oATqVIsnB4YFZGwPFv5x/H22N79w6XCWVpG+q1TvxF3GCle7eEJIV6atdRF6lH1kSW0h4b+gw==", + "version": "0.1.67", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.67.tgz", + "integrity": "sha512-ULQFB+wBUBENt3SBL3/Ve5li2YKzJtbQ5eq7Lz1I6Gp1SGBeTu1ooLQ/GqRTmVdASoulEkupaNuoMZQqsg17bg==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index 7d486f6a9..badca9598 100644 --- a/client/package.json +++ b/client/package.json @@ -52,7 +52,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", - "haengdong-design": "^0.1.66", + "haengdong-design": "^0.1.67", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index 52bab8b73..f9fa58594 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -4,7 +4,7 @@ import {BottomSheet, FixedButton, LabelGroupInput, Text} from 'haengdong-design' import validatePurchase from '@utils/validate/validatePurchase'; -import {usePutAndDeleteBillAction} from '@hooks/usePutAndDeleteBillAction'; +import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './PutAndDeltetBillActionModal.style'; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index d819d4219..7c49d8efa 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -38,15 +38,13 @@ const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, set return ( <> - <button style={{fontSize: '0.75rem'}} onClick={handleTopRightTextClick}> - 참여인원 확인 임시용 - </button> <DragHandleItemContainer topLeftText={stepName} topRightText={`${step.members.length}명`} bottomLeftText="총액" bottomRightText={`${totalPrice.toLocaleString('ko-kr')} 원`} backgroundColor="white" + onTopRightTextClick={handleTopRightTextClick} > {step.actions.map((action, index) => ( <Fragment key={action.actionId}> From 97f354ab9a08c04d9845b819dda91cfc464162ae Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:17:14 +0900 Subject: [PATCH 147/273] =?UTF-8?q?feat:=20bottomSheet=20maxWidth=20768px?= =?UTF-8?q?=20=EB=90=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20(#321)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HDesign/package-lock.json | 4 ++-- HDesign/package.json | 2 +- .../src/components/BottomSheet/BottomSheet.style.ts | 11 +++++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 5164bd450..dd407a7ac 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.66", + "version": "0.1.68", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.66", + "version": "0.1.68", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index 96ebc49e5..8576b20a9 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.66", + "version": "0.1.68", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/BottomSheet/BottomSheet.style.ts b/HDesign/src/components/BottomSheet/BottomSheet.style.ts index 2a6506d7e..08c373835 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.style.ts +++ b/HDesign/src/components/BottomSheet/BottomSheet.style.ts @@ -9,10 +9,12 @@ export const display = (visible: boolean) => export const dimmedLayerStyle = (theme: Theme, isOpened: boolean) => css({ - // TODO: (@todari) zindex foundation position: 'fixed', zIndex: '30', - inset: '0', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + maxWidth: '768px', width: '100vw', height: '100vh', backgroundColor: theme.colors.black, @@ -30,13 +32,14 @@ export const bottomSheetContainerStyle = (theme: Theme, isOpened: boolean, isDra alignItems: 'center', gap: '1.5rem', zIndex: '50', - inset: 'auto 0 0 0', + inset: 'auto 0 0 50%', + maxWidth: '768px', width: '100%', height: '80%', borderRadius: '1.5rem 1.5rem 0 0', backgroundColor: theme.colors.white, - transform: isOpened ? `translateY(${translateY}px)` : 'translateY(100%)', + transform: isOpened ? `translate(-50%, ${translateY}px)` : 'translate(-50%, 100%)', transition: isDragging ? 'none' : 'transform 0.2s ease-in-out', }); From 61e9d9d84f6a63443ed06e029b1dbc4d5b2223b9 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:17:55 +0900 Subject: [PATCH 148/273] =?UTF-8?q?feat:=20=EB=A9=94=EC=9D=B8,=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=84=A4=EB=AA=85=20?= =?UTF-8?q?=EA=B8=80=20=EC=88=98=EC=A0=95=20(#324)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 --- client/src/assets/image/dog.svg | 49 +++++++++++++++++++ .../src/components/Common/Logo/Logo.style.ts | 8 +++ client/src/components/Common/Logo/Logo.tsx | 13 +++++ client/src/components/Common/Logo/index.ts | 1 + client/src/global.d.ts | 1 + .../pages/EventPage/AdminPage/AdminPage.tsx | 12 +++-- client/src/pages/MainPage/MainPage.tsx | 5 +- 7 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 client/src/assets/image/dog.svg create mode 100644 client/src/components/Common/Logo/Logo.style.ts create mode 100644 client/src/components/Common/Logo/Logo.tsx create mode 100644 client/src/components/Common/Logo/index.ts create mode 100644 client/src/global.d.ts diff --git a/client/src/assets/image/dog.svg b/client/src/assets/image/dog.svg new file mode 100644 index 000000000..f70558ed6 --- /dev/null +++ b/client/src/assets/image/dog.svg @@ -0,0 +1,49 @@ +<svg width="287" height="234" viewBox="0 0 287 234" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M224.14 30.8149C226.74 33.1674 229.246 35.706 232.018 37.8621C233.036 38.6544 230.186 36.4868 229.886 36.2462C229.824 36.1971 228.474 35.173 228.539 35.124C229.148 34.6671 233.936 36.6161 234.823 36.7175C237.38 37.0097 237.007 35.3879 235.855 33.8223C235.42 33.2303 233.445 32.1804 234.127 32.4533C235.743 33.0996 238.789 35.0217 240.524 34.361C242.854 33.4734 235.79 32.4309 233.297 32.4309C232.102 32.4309 232.51 33.2145 231.636 33.2388C230.041 33.2831 228.531 32.8348 226.968 32.8348" stroke="#F4E8FF" stroke-width="10" stroke-linecap="round"/> +<path d="M53.1677 77C43.4725 94.2495 38.6093 111.668 40.3474 131.747C42.3069 154.384 70.3648 159.82 88.1534 161.63C115.092 164.37 143.558 165.538 170.327 160.642C184.816 157.992 200.046 152.245 204 136.055" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M128.801 200.486C130.803 197.912 134.486 196.324 137.689 196.087C139.687 195.939 144.264 195.234 145.903 196.76C147.692 198.425 145.143 200.986 143.906 201.855C141.364 203.639 137.371 203.869 134.457 202.82C132.086 201.966 128.411 200.236 133.133 199.902C137.386 199.601 141.965 199.536 146.083 200.8C150.453 202.141 148.382 203.767 145.23 204.032C144.503 204.093 137.827 203.717 141.415 203.717C142.398 203.717 150.169 204.05 149.247 202.865C147.192 200.222 141.247 200.245 138.272 200.575C136.684 200.752 133.884 202.201 135.781 204.099C138.575 206.893 147.03 206.228 150.257 204.929C153.302 203.704 151.025 201.359 148.888 200.575C143.474 198.59 135.529 199.339 130.103 200.8C128.075 201.346 125.146 203.732 128.106 205.647C131.548 207.875 138.426 205.738 141.684 204.166C143.348 203.363 147.283 201.9 148.192 200.082" stroke="#F4E8FF" stroke-width="10" stroke-linecap="round"/> +<path d="M31.8467 176.247C30.9926 176.247 31.0388 176.495 31.0388 177.347C31.0388 180.349 31.3569 182.754 33.9339 184.663C35.6364 185.924 44.774 188.957 44.774 184.327C44.774 180.243 34.3089 179.864 32.1609 182.352C27.9134 187.27 35.8143 190.889 39.9263 189.488C42.0239 188.774 44.6497 186.152 44.1007 183.721C43.3166 180.248 37.3253 178.627 34.3379 178.11C32.8275 177.848 30.3377 177.361 29.1984 178.761C28.3262 179.832 28.2094 183.165 28.8842 184.327C31.1399 188.208 39.7435 188.651 43.6743 188.748C45.379 188.79 50.3019 189.479 51.3948 187.536C53.309 184.133 47.7267 183.923 45.986 183.923" stroke="#F4E8FF" stroke-width="10" stroke-linecap="round"/> +<path d="M206.525 82C212.432 82 218.392 86.5303 223.503 89.1188C235.279 95.0824 246.906 103.623 252.708 116.139C256.356 124.008 255.793 135.02 249.987 141.861C245.098 147.621 234.475 145.675 227.911 145.715C219.167 145.769 211.205 145.65 203.651 140.563C197.892 136.684 189.982 131.516 185.561 125.932C183.312 123.091 182.928 119.657 181 116.689" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M196 77.6495C185.281 77.6495 174.143 72.4916 163.848 69.7514C150.925 66.312 137.758 62.9212 124.618 60.3299C107.348 56.924 89.0222 56 71.4669 56C64.5355 56 56.3332 58.748 49.8525 61.4926C41.5961 64.989 32.2959 71.5686 25.5458 77.6495C15.2156 86.9556 7.4009 93.4074 7.00815 108.761C6.8202 116.108 9.87482 121.338 17.1616 123.113C23.7104 124.709 30.0417 126 36.7761 126" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M76.0439 56.8563C84.0634 55.871 92.0395 56.3748 100.081 56.6977C108.468 57.0345 116.9 56.4488 125.274 57.0148C131.082 57.4074 136.777 58.5795 142.609 58.8381C150.197 59.1747 157.86 59.0926 165.414 60.0273C173.926 61.0805 181.863 64.1826 189.143 68.7474C192.938 71.127 196.401 73.8142 199.852 76.6748C200.416 77.1419 201.365 79.1832 200.854 78.6567C196.273 73.9436 189.74 71.4676 183.673 68.9852C168.12 62.6216 151.94 58.3913 135.752 54.161C119.453 49.9015 104.581 48.8962 87.8315 49.0082C67.2223 49.1459 46.3388 56.2153 28.8165 67.1619C23.0646 70.7553 16.0759 73.8629 12.7916 80.3214C9.69741 86.406 8.02708 91.2837 8.09194 98.1581C8.21869 111.591 19.2793 112.507 30.2033 112.507C32.9719 112.507 40.0148 110.746 36.9831 115.598C32.868 122.185 23.9 126.726 16.2585 125.904C11.9191 125.438 4.20183 123.023 2.85302 118.056C0.0988928 107.914 4.40527 101.509 10.1721 93.9566" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M270.598 137.465C271.016 139.672 271.48 141.141 273.919 141.415C276.512 141.707 278.081 140.639 279.216 138.318C280.484 135.726 280.322 133.066 276.927 133.066C274.912 133.066 275.445 137.851 275.445 139.26C275.445 139.87 274.569 137.442 273.426 137.061" stroke="#F4E8FF" stroke-width="10" stroke-linecap="round"/> +<path d="M39.8733 160C36.576 161.934 28.4034 165.254 26.851 169.49C25.1281 174.191 24 180.451 24 185.48C24 194.615 38.4927 195.283 44.381 194.93C54.1039 194.346 63.2474 192.02 69 183.685" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M155.754 132.536C155.754 137.639 165.674 139.48 164.964 132.006C164.505 127.181 153.664 124.501 149.636 126.884C146.489 128.745 148.383 132.762 151.117 133.595" stroke="#EBDAFF" stroke-width="26" stroke-linecap="round"/> +<path d="M66.8161 124.419C58.8713 125.726 68.9408 137.101 66.6528 126.567C65.0763 119.308 61.0907 122.386 58 124.419" stroke="#EBDAFF" stroke-width="26" stroke-linecap="round"/> +<path d="M129.162 184.834C127.254 191.226 125 196.989 125 203.712C125 207.967 126.348 208.438 130.78 209.952C137.148 212.127 146.68 213.281 152.746 209.715C157.578 206.873 162.232 202.912 166.58 199.367C172.159 194.819 174.306 187.894 177.023 181.398C177.48 180.304 178.417 176.874 179.721 176.461C183.182 175.363 187.32 175.607 190.896 174.802C200.109 172.73 209.413 168.95 217.909 164.771C227.036 160.281 237.142 156.711 245 150" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M247 157.769C252.212 157.769 258.305 158.647 263.318 156.978C270.275 154.661 278.046 147.627 280.331 140.447C283.848 129.399 272.678 130.006 265.792 130.006" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M233.372 83.0942C232.678 70.8555 233.38 55.0225 227.747 43.7251C224.865 37.945 220.961 34.0024 216.573 29.5107C213.642 26.5108 215.024 27.0352 218.929 27.0352C227.804 27.0352 236.91 26.7093 244.926 31.3873C253.783 36.5571 258 46.2544 258 56.542C258 64.1659 256.823 70.9347 254.199 78.0234C252.542 82.5004 249.101 86.705 247.738 91" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M73 134C73 139.551 73.8234 147.858 80.5136 147.858C85.2393 147.858 90.413 147.947 95.0713 147.181C97.8344 146.726 99.2012 144.233 100.442 141.791C102.325 138.088 101.866 140.227 102.086 143.116C102.284 145.708 104.639 147.318 106.782 148.104C109.929 149.26 113.61 148.967 116.878 148.967C119.319 148.967 121.722 149.278 123.658 147.427C125.537 145.631 127.002 143.438 129 141.761" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M133.499 142C135.199 142.073 138.904 141.959 138.998 144.654C139.038 145.809 138.542 146.265 137.47 146.414C134.73 146.794 131.769 147 129 147" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M70.887 138.846C60.8199 138.846 49.9998 138.273 40.045 136.484C38.3236 136.175 19.2095 132.773 21.1363 137.448C21.6497 138.693 25.2772 138.878 26.3246 139.281C28.3068 140.045 30.1252 140.791 32.2336 141.084C37.9879 141.885 43.7141 143.08 49.4705 143.881C54.4407 144.573 59.4009 144.441 64.4015 144.441C67.5818 144.441 70.9967 143.921 74 145" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M15.6643 140C13.1917 144.834 10.4766 148.832 9.64006 154.211C9.45852 155.378 8.19576 160 9.81468 160C21.3494 160 31.7467 150.955 41.7405 146.199C42.8988 145.648 43.7931 144.615 45 144.211" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M21.6657 136C19.5749 136 17.6553 135.981 15.6401 136.525C12.4061 137.399 14.552 139.18 16.9564 139.483C24.6489 140.452 32.2363 140.185 39.9766 140.865C42.1792 141.059 44.8654 140.535 46.9676 141.28C50.2103 142.429 53.2424 142.599 56.708 142.856C59.9099 143.093 63.1518 142.966 66.3607 142.966C69.5344 142.966 60.0228 142.64 56.8543 142.469C50.0811 142.103 43.2759 141.709 36.5251 141.086C34.1228 140.865 31.6671 141.213 29.3002 140.727C27.8037 140.42 26.1799 140.554 24.7371 140.008C23.8408 139.67 26.6676 139.981 27.6329 139.981C31.221 139.981 34.809 139.981 38.3971 139.981C42.541 139.981 46.6848 139.981 50.8286 139.981C51.6661 139.981 52.3554 139.77 52.7299 140.478" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M85.8979 106C84.5508 108.62 83.6255 111.089 83.2279 114.061C82.9506 116.134 84.8964 116.886 86.4771 117.276C89.4544 118.011 91.6282 116.26 91.9441 112.865C92.2611 109.457 91.2677 107.508 88.0027 107.305C85.9624 107.178 84.3807 108.166 83.7224 110.318C83.2131 111.982 82.5266 115.448 83.4681 117.058C84.0609 118.072 85.8777 118.314 86.689 117.555C88.2432 116.103 89.7037 111.996 88.7656 109.774C87.9181 107.767 86.7438 112.432 86.7172 112.834C86.5591 115.225 88.6924 114.553 89.5425 113.082C90.2325 111.888 91.0293 108.768 90.5597 107.367C90.157 106.165 89.4864 108.689 89.4719 108.904C89.4451 109.303 89.6824 110.382 89.147 110.256C88.0131 109.988 87.224 110.541 86.4064 111.312" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M119.35 109.228C116.231 110.672 114.802 118.81 117.211 121.366C120.391 124.741 126.242 120.084 125.992 116.055C125.904 114.623 124.624 113.531 123.511 112.882C121.839 111.906 120.574 113.702 120.034 115.142C119.38 116.887 118.141 120.919 119.945 122.387C122.707 124.636 125.062 120.132 125.383 117.96C125.779 115.281 126.144 110.929 123.303 109.414C121.2 108.292 118.633 109.564 118.073 111.86C117.677 113.479 117.215 117.657 119.885 117.247C121.945 116.932 119.982 113.284 117.865 116.226C117.132 117.243 117.278 118.142 118.518 118.47C119.994 118.861 121.267 118.241 122.382 117.263C123.051 116.676 124.102 115.711 124.343 114.77C124.435 114.412 123.82 115.17 123.793 115.235C122.736 117.806 127.2 116.195 125.502 116.195" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M120 99C119.997 98.9994 123.731 95.8278 124.472 95.25C125.198 94.6841 126.17 94.3294 127 94" stroke="#B575FF" stroke-width="3" stroke-linecap="round"/> +<path d="M86.2244 109.607C86.0263 109.9 86.4798 109.918 86.6067 109.781C86.6762 109.707 87.1366 109.149 86.9599 109.033C86.8683 108.973 86.6503 109 86.5651 109.071C86.3536 109.248 86.5477 109.419 86.507 109.312C86.2669 108.68 86.0208 109.809 86 110" stroke="white" stroke-width="3" stroke-linecap="round"/> +<path d="M119.121 112.166C118.546 112.166 117.794 112.243 118.053 113.496C118.292 114.653 119.369 113.588 119.225 112.6C119.17 112.224 118.401 113.449 118.921 113.893C119.52 114.406 120.526 112.261 119.668 112" stroke="white" stroke-width="3" stroke-linecap="round"/> +<path d="M152.018 35C151.587 26.7707 159.124 17.6932 168.168 19.1564C170.698 19.5656 171.383 24.0424 170.811 26.0732C170.184 28.3028 168.659 29.5133 167.346 31.2756" stroke="#B575FF" stroke-width="2" stroke-linecap="round"/> +<path d="M193 25.9149C193 23.4539 196.238 23.8308 197.74 24.5012C201.21 26.0511 196.588 31.059 194.939 32" stroke="#B575FF" stroke-width="2" stroke-linecap="round"/> +<path d="M175 3.88714C175.039 3.02367 175.063 1.34114 176.375 1.09195C176.894 0.993389 178.511 0.85955 178.728 1.3793C179.976 4.36645 176.577 7.3677 175.55 10" stroke="#B575FF" stroke-width="2" stroke-linecap="round"/> +<path d="M114.343 211.633C111.594 211.633 83.1655 210.245 84.3191 214.219C84.6603 215.394 89.9916 215.579 91.4775 215.619C97.8541 215.791 104.127 214.518 110.138 213.59C113.93 213.005 117.933 212.511 121.571 211.974C127.499 211.099 124.61 214.269 128.138 215.332C133.191 216.855 151.044 217.32 145.2 217.451C132.809 217.729 120.47 218.097 108.053 218.097C104.662 218.097 100.815 217.829 97.4891 218.259C96.8883 218.336 94.894 218.271 94.4659 218.492C94.0138 218.726 96.1872 219.038 96.3424 219.067C101.182 219.971 106.85 220.055 111.91 220.162C121.12 220.357 130.338 219.693 139.432 218.995C145.426 218.535 151.305 218.495 157.328 218.259C171.787 217.693 192.685 218.546 200.313 210.664C201.392 209.549 204.993 209.211 207.263 208.904C216.867 207.606 227.161 206.835 237.043 206.301C247.006 205.762 257.038 205.622 267.032 205.241C272.239 205.043 255.004 207.398 259.901 208.832C263.597 209.914 274.135 208.701 273.322 208.832C260.292 210.936 246.315 211.625 232.804 212.441C220.929 213.158 209.032 214.542 197.046 214.542C196.369 214.542 173.483 210.228 175.787 211.31C177.23 211.988 199.007 216.987 200.73 217.271C205.915 218.125 210.899 219.183 216.332 219.534C226.768 220.208 232.626 220.036 243.124 220.036C252.167 220.036 246.708 217.128 259.901 216.661C265.413 215.603 267.081 215.769 270.437 213.411C291.773 198.418 210.931 199.292 196.004 204.2C194.194 204.795 179.584 203.506 177.378 203.506C174.512 203.506 203.788 205.424 203.788 206.48C203.788 208.294 203.162 210.015 203.162 211.813C203.162 213.259 203.383 215.252 201.494 216.481C200.192 217.329 197.881 217.545 196.004 217.846C191.963 218.494 188.144 219.417 184.085 220.036C176.535 221.187 169.286 221.827 161.393 222.227C152.315 222.687 143.454 222.902 134.324 223.089C127.593 223.226 121.259 222.299 114.655 222.299C113.741 222.299 112.991 222.247 114.482 222.317C117.794 222.472 121.092 222.935 124.35 223.268C134.898 224.346 145.828 223.915 156.529 223.915C175.751 223.915 193.951 223.904 212.475 221.078C217.307 220.341 222.127 219.598 226.931 218.815C232.022 217.986 238.397 217.351 242.777 215.691C242.78 215.69 243.795 215.309 243.124 215.26C237.841 214.879 230.53 216.146 225.611 216.661C210.657 218.227 195.795 219.986 180.645 220.988C163.732 222.106 146.64 222.368 129.632 222.694C121.067 222.858 108.036 223.22 101.833 219.318C99.428 217.805 98.4078 216.964 101.242 215.206C103.888 213.565 107.325 212.298 110.937 211.31C113.988 210.476 121.821 207.572 124.281 206.301C124.69 206.089 118.835 208.401 118.652 208.401C114.644 208.401 110.636 208.401 106.628 208.401C103.643 208.401 101.323 208.65 98.4969 209.227C92.292 210.495 85.509 212.283 82.7901 215.494C79.4344 219.457 87.4639 221.598 93.8057 222.119C103.793 222.94 114.201 222.896 124.281 223.196C135.927 223.544 147.418 223.915 159.1 223.915C165.19 223.915 171.288 223.959 177.378 223.915C184.159 223.865 190.809 223.145 197.568 222.945C212.62 222.501 226.83 219.259 241.456 217.648C243.517 217.421 249.665 216.95 247.572 216.822C241.656 216.463 235.179 216.913 229.294 217.128C218.323 217.527 207.265 219.067 196.282 219.067" stroke="#EBDAFF" stroke-opacity="0.5" stroke-width="20" stroke-linecap="round"/> +<path d="M193 76.7932C197.87 71.7784 208.856 71.5395 215.389 72.3598C218.686 72.7739 223.011 76.5927 223.139 80.1429C223.189 81.5252 222.8 82.3824 224 83" stroke="#B575FF" stroke-width="2" stroke-linecap="round"/> +<path d="M18.4102 143.974C17.6006 145.665 16.8729 147.364 16.1941 149.115C16.0946 149.372 15.3716 151.938 15.0861 151.998C14.6869 152.081 15.8014 149.431 15.8775 149.281C16.4528 148.146 17.1608 147.262 18.0232 146.361C18.7678 145.584 19.4513 145.22 20.4679 144.984C21.4689 144.752 20.1795 148.542 19.8524 149.079C19.4176 149.792 20.3282 149.505 20.6966 149.372C22.8876 148.586 25.0032 147.259 27.1337 146.288C30.0962 144.938 32.8169 142.985 35.91 141.991C36.1992 141.899 36.2133 141.661 36.5608 141.661C38.7442 141.661 32.1894 141.571 30.0181 141.33C27.1925 141.018 24.4123 141 21.576 141" stroke="#B575FF" stroke-width="12" stroke-linecap="round"/> +<path d="M39.8155 138.903C32.1931 138.903 24.6843 138.025 17.0615 138.025C15.4336 138.025 14.6403 137.708 13.8292 139.325C11.8774 143.217 9.34456 146.902 7.6847 150.929C6.44506 153.937 4.68844 156.811 3.74835 159.933C3.70839 160.066 2.46829 163.216 3.2683 162.988C7.98983 161.642 12.2744 157.976 16.4215 155.415C22.7632 151.499 29.6833 149.249 36.4232 146.216C38.5332 145.267 40.5153 144.142 42.6318 143.226C43.3682 142.907 44.4721 142.364 45 141.828" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M9.17038 138C7.80394 138 7.48508 138.275 9.01924 138.582C10.9261 138.962 13.0725 139.095 15 138.931" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M74.1423 53.6805C63.8198 53.6805 54.0922 56.6335 44.9888 61.332C41.9777 62.8861 38.8172 64.3719 35.9913 66.2558C32.806 68.3794 29.9236 70.9561 26.7103 73.0571C24.4375 74.5432 23.1488 77.2045 21.5385 79.3271C20.0385 81.3044 18.1638 83.1301 16.4553 84.924C12.047 89.5526 8.06581 95.6731 6.87323 102.033C5.94851 106.965 5.80018 114.514 9.93736 118.204C12.4122 120.412 16.7024 120.923 19.8382 121.446C22.9378 121.962 27.3557 122.604 30.3589 121.516C32.2385 120.835 34.2698 120.15 36.0267 119.196C37.3365 118.485 38.5049 117.514 37.9396 119.533C37.1769 122.256 37.1602 124.871 37.1602 127.68C37.1602 128.758 36.8603 130.223 37.4791 131.152" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M42.2611 149.961C43.2154 150.916 44.2475 152.092 45.4492 152.76C45.8725 152.995 46.9093 153.323 45.9452 153.716C39.7115 156.261 32.8738 161.049 30.0401 167.425C28.2768 171.392 24.8154 175.22 24.7265 179.752C24.6616 183.066 25.1352 185.12 27.5604 187.546C33.6777 193.663 42.4961 192.67 50.4262 191.849C57.2381 191.145 65.1511 189.62 70.5821 185.19C72.5732 183.566 74.3954 181.589 76.2145 179.77C76.808 179.177 77.9311 178.409 78.2867 177.698" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M127.702 183.436C126.168 186.505 125.67 189.611 124.514 192.788C123.42 195.796 123.141 200.901 124.833 203.681C129.681 211.646 139.276 210.535 147.628 210.535C154.988 210.535 161.689 207 166.278 201.361C172.082 194.231 172.017 182.936 172.017 174.191" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M82.4314 175.466C94.3572 174.808 106.606 174.403 118.138 177.698" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M175.524 177.379C183.29 175.049 190.573 171.004 198.301 168.47C204.027 166.593 209.873 165.008 215.552 163.015C225.566 159.501 234.643 154.338 245.343 153.149" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M246.938 155.062C253.057 155.651 258.716 157.294 264.915 157.294C268.792 157.294 271.74 156.683 275.312 155.222C282.321 152.354 283.92 145.363 283.92 138.449C283.92 135.597 284.227 134.05 282.148 131.931C281.05 130.811 279.938 129.7 278.819 128.601C277.323 127.133 275.575 126.542 273.718 125.661C270.016 123.904 265.08 123.294 261.001 123.181C260.267 123.161 256.335 122.24 255.864 123.181" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M227.864 87.5821C232.348 79.6914 233.076 70.619 231.943 61.6817C231.299 56.6002 230.377 50.8219 227.864 46.2988C226.608 44.0369 223.943 41.8912 222.114 40.008C220.039 37.8721 217.091 33.6729 217.248 30.5227C217.423 27.0389 222.216 26.1599 224.719 25.2149C229.255 23.5021 231.862 23.2882 236.44 24.3056C240.506 25.2092 244.253 26.7051 247.744 28.9746C250.269 30.6159 254.047 34.0246 255.018 36.9364C256.629 41.7706 258.488 46.7278 259.466 51.7541C260.243 55.7521 260.468 61.7674 259.048 65.7118C256.354 73.195 252.973 80.1663 247.302 85.8373C245.189 87.95 243.479 89.7391 241.134 91.5629C239.67 92.7011 237.144 93.3494 236.268 95.1015" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M236.298 93.7974C247.268 98.0163 253.805 108.229 257.347 118.856" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M81.6294 51.4147C91.3014 51.4147 100.886 52.2886 110.566 52.2886C116.765 52.2886 122.785 52.7864 128.942 53.1382C135.002 53.4845 141.411 54.1472 147.27 55.7843C155.987 58.2197 165.221 58.0549 174.167 59.0614C180.383 59.7607 186.087 62.1194 191.961 64.1107C196.597 65.682 200.528 68.5643 204.949 70.5437C207.519 71.6946 210.112 72.8499 212.377 74.5735C214.998 76.5679 217.326 78.4298 219.514 80.9094C220.519 82.0488 223.463 83.3126 224.952 83.3126" stroke="#B575FF" stroke-width="5" stroke-linecap="round"/> +<path d="M98.1909 137.971C98.9839 138.852 101.237 138.745 102.263 138.373C102.533 138.275 103.682 137.713 102.942 137.342C102.647 137.195 101.136 137.064 101.408 137.744C101.513 138.007 101.55 137.444 101.534 137.393C101.418 137.02 100.986 136.971 100.679 136.84" stroke="#EBDAFF" stroke-width="9" stroke-linecap="round"/> +<path d="M98.7128 134.622C98.7654 135.148 100.649 135.437 100.209 135.144C99.8035 134.874 99.1033 134.921 98.6538 135.056C98.1094 135.219 98.1036 135.813 98.7128 135.508" stroke="#DEC3FD" stroke-width="4" stroke-linecap="round"/> +<path d="M145.891 125.763C145.928 127.399 146.377 129.005 146.377 130.629" stroke="#DEC3FD" stroke-width="4" stroke-linecap="round"/> +<path d="M154.405 124.79C154.736 125.747 154.848 127.401 155.378 128.196" stroke="#DEC3FD" stroke-width="4" stroke-linecap="round"/> +<path d="M54.9069 121.141V123.33" stroke="#DEC3FD" stroke-width="4" stroke-linecap="round"/> +<path d="M66.0974 120.898V124.304" stroke="#DEC3FD" stroke-width="4" stroke-linecap="round"/> +</svg> diff --git a/client/src/components/Common/Logo/Logo.style.ts b/client/src/components/Common/Logo/Logo.style.ts new file mode 100644 index 000000000..89f97ede0 --- /dev/null +++ b/client/src/components/Common/Logo/Logo.style.ts @@ -0,0 +1,8 @@ +import {css} from '@emotion/react'; + +export const logoStyle = css({ + display: 'flex', + justifyContent: 'center', + + width: '100%', +}); diff --git a/client/src/components/Common/Logo/Logo.tsx b/client/src/components/Common/Logo/Logo.tsx new file mode 100644 index 000000000..c8c798d2a --- /dev/null +++ b/client/src/components/Common/Logo/Logo.tsx @@ -0,0 +1,13 @@ +import Dog from '@assets/image/dog.svg'; + +import {logoStyle} from './Logo.style'; + +const Logo = () => { + return ( + <div css={logoStyle}> + <Dog /> + </div> + ); +}; + +export default Logo; diff --git a/client/src/components/Common/Logo/index.ts b/client/src/components/Common/Logo/index.ts new file mode 100644 index 000000000..31d6bf822 --- /dev/null +++ b/client/src/components/Common/Logo/index.ts @@ -0,0 +1 @@ +export {default as Logo} from './Logo'; diff --git a/client/src/global.d.ts b/client/src/global.d.ts new file mode 100644 index 000000000..bff94710c --- /dev/null +++ b/client/src/global.d.ts @@ -0,0 +1 @@ +declare module '*.svg'; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index fefc851ed..7064bd187 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -53,14 +53,16 @@ const AdminPage = () => { setIsOpenAllMemberListButton(prev => !prev); }; + const getTitleDescriptionByInitialMemberSetting = () => { + return allMemberList.length > 0 + ? '“행동 추가하기” 버튼을 눌러서 지출 내역 및 인원 변동사항을 추가해 주세요.' + : '“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요.'; + }; + return ( <> <div css={titleAndListButtonContainerStyle}> - <Title - title={eventName} - description="“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요." - price={getTotalPrice()} - /> + <Title title={eventName} description={getTitleDescriptionByInitialMemberSetting()} price={getTotalPrice()} /> {allMemberList.length !== 0 && ( <ListButton prefix="전체 참여자" diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index 682a9c836..33f1bfe3f 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -1,6 +1,8 @@ import {useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; +import {Logo} from '@components/Common/Logo'; + import {ROUTER_URLS} from '@constants/routerUrls'; const MainPage = () => { @@ -9,7 +11,8 @@ const MainPage = () => { return ( <MainLayout> <TopNav children={<></>} /> - <Title title="행동대장" description="데모데이 ~~ 시연 ~~~~~! 페이지입니다." /> + <Title title="행동대장" description="👑행동대장들의 행복한 행사 진행을 위해... 📢행동개시!" /> + <Logo /> <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateName)}>행사 생성하기</FixedButton> </MainLayout> ); From 9b61b34ec7e12326b68577c1920469049528b5fd Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:18:46 +0900 Subject: [PATCH 149/273] =?UTF-8?q?fix:=20useDynamicInput=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95=20(#327)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 --- .../AddBillActionListModalContent.tsx | 3 + .../InMember.tsx | 11 +++- .../OutMember.tsx | 2 + .../SetInitialMemberListModal.tsx | 2 + client/src/constants/errorMessage.ts | 2 +- .../src/hooks/useDynamicBillActionInput.tsx | 55 +++++++++++----- client/src/hooks/useDynamicInput.tsx | 63 ++++++++++++------- .../pages/EventPage/AdminPage/AdminPage.tsx | 1 - client/src/utils/sendLogToSentry.ts | 1 - 9 files changed, 97 insertions(+), 43 deletions(-) diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index b07f02d4d..239bc0d2d 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -15,6 +15,7 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList const { inputPairList, inputRefList, + errorIndexList, handleInputChange, getFilledInputPairList, deleteEmptyInputPairElementOnBlur, @@ -40,6 +41,7 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList elementKey={`${index}`} type="text" value={title} + isError={errorIndexList.includes(index)} onChange={e => handleInputChange(index, 'title', e)} onKeyDown={e => focusNextInputOnEnter(e, index, 'title')} onBlur={() => deleteEmptyInputPairElementOnBlur()} // TODO: (@weadie) 이 블러프롭이 내부적으로 index를 넘기고 있기 때문에 화살표 함수로 써야만하내요.. @@ -50,6 +52,7 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList elementKey={`${index}`} type="number" value={price} + isError={errorIndexList.includes(index)} onChange={e => handleInputChange(index, 'price', e)} onKeyDown={e => focusNextInputOnEnter(e, index, 'price')} onBlur={() => deleteEmptyInputPairElementOnBlur()} diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx index 23654524a..54949fc04 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx @@ -7,8 +7,14 @@ interface InMemberProps { } const InMember = ({dynamicProps}: InMemberProps) => { - const {inputList, inputRefList, handleInputChange, deleteEmptyInputElementOnBlur, focusNextInputOnEnter} = - dynamicProps; + const { + inputList, + inputRefList, + handleInputChange, + deleteEmptyInputElementOnBlur, + focusNextInputOnEnter, + errorIndexList, + } = dynamicProps; return inputList.map(({value, index}) => ( <LabelGroupInput.Element key={index} @@ -16,6 +22,7 @@ const InMember = ({dynamicProps}: InMemberProps) => { type="text" value={value} ref={el => (inputRefList.current[index] = el)} + isError={errorIndexList.includes(index)} onChange={e => handleInputChange(index, e)} onBlur={() => deleteEmptyInputElementOnBlur()} onKeyDown={e => focusNextInputOnEnter(e, index)} diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx index f83ac9085..4a2fe855f 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -11,6 +11,7 @@ const OutMember = ({dynamicProps}: OutMemberProps) => { const { inputList, inputRefList, + errorIndexList, deleteEmptyInputElementOnBlur, focusNextInputOnEnter, handleInputChange, @@ -37,6 +38,7 @@ const OutMember = ({dynamicProps}: OutMemberProps) => { type="text" value={value} ref={el => (inputRefList.current[index] = el)} + isError={errorIndexList.includes(index)} onChange={e => validationAndSearchOnChange(index, e)} onBlur={() => deleteEmptyInputElementOnBlur()} onKeyDown={e => focusNextInputOnEnter(e, index)} diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index be6ad6b87..ac9375d52 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -24,6 +24,7 @@ const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: Se getFilledInputList, errorMessage, canSubmit, + errorIndexList, focusNextInputOnEnter, } = useDynamicInput(validateMemberName); const {updateMemberList} = useStepList(); @@ -45,6 +46,7 @@ const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: Se elementKey={`${index}`} type="text" value={value} + isError={errorIndexList.includes(index)} ref={el => (inputRefList.current[index] = el)} onChange={e => handleInputChange(index, e)} onBlur={() => deleteEmptyInputElementOnBlur()} diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index cfe0fb751..e238cf90e 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -38,7 +38,7 @@ const SERVER_ERROR_MESSAGES: ErrorMessage = { export const ERROR_MESSAGE = { eventName: '행사 이름은 30자 이하만 가능해요', eventPasswordType: '비밀번호는 숫자만 입력이 가능해요', - memberName: '참여자 이름은 8자 이하의 한글, 영어만 가능해요', + memberName: '참여자 이름은 4자 이하의 한글, 영어만 가능해요', purchasePrice: '10,000,000원 이하의 숫자만 입력이 가능해요', purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', preventEmpty: '값은 비어있을 수 없어요', diff --git a/client/src/hooks/useDynamicBillActionInput.tsx b/client/src/hooks/useDynamicBillActionInput.tsx index d07794751..252b40862 100644 --- a/client/src/hooks/useDynamicBillActionInput.tsx +++ b/client/src/hooks/useDynamicBillActionInput.tsx @@ -15,6 +15,7 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe const [inputPairList, setInputPairList] = useState<InputPair[]>([{title: '', price: '', index: 0}]); const inputRefList = useRef<(HTMLInputElement | null)[]>([]); const [errorMessage, setErrorMessage] = useState(''); + const [errorIndexList, setErrorIndexList] = useState<number[]>([]); const [canSubmit, setCanSubmit] = useState(false); useEffect(() => { @@ -34,13 +35,14 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe }); // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수로 분리 - if (isLastInputPairFilled({index, field, value})) { + if ( + isLastInputPairFilled({index, field, value}) && + targetInputPair.title.trim().length !== 0 && + targetInputPair.price.trim().length !== 0 + ) { setErrorMessage(''); setInputPairList(prevInputPairList => { const updatedInputPairList = [...prevInputPairList]; - const targetInputPair = findInputPairByIndex(index, updatedInputPairList); - - targetInputPair[field] = value; // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 const newIndex = updatedInputPairList[updatedInputPairList.length - 1].index + 1; @@ -48,22 +50,22 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe return finalInputs; }); - } else if (isValidInput || value.length === 0) { + } else if (isValidInput) { + // 입력된 값이 유효하면 데이터(inputLis)를 변경합니다. setErrorMessage(''); - setInputPairList(prevInputPairList => { - const updatedInputPairList = [...prevInputPairList]; - const targetInputPair = findInputPairByIndex(index, updatedInputPairList); + if (errorIndexList.includes(index)) { + setErrorIndexList(prev => prev.filter(i => i !== index)); + } - targetInputPair[field] = value; + changeInputListValue(index, value, field); + } else if (value.length === 0) { + setErrorMessage(''); + changeErrorIndex(index); - return updatedInputPairList; - }); + changeInputListValue(index, value, field); } else { - const targetInput = findInputPairByIndex(index); - - event.target.value = targetInput[field]; - setErrorMessage(validationResultMessage ?? ''); + changeErrorIndex(targetInputPair.index); } handleCanSubmit(); @@ -96,6 +98,26 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe setCanSubmit(inputPairList.length > 0 && getFilledInputPairList().length > 0); }; + const changeInputListValue = (index: number, value: string, field: BillInputType) => { + setInputPairList(prevInputPairList => { + const updatedInputPairList = [...prevInputPairList]; + const targetInputPair = findInputPairByIndex(index, updatedInputPairList); + + targetInputPair[field] = value; + + return updatedInputPairList; + }); + }; + + const changeErrorIndex = (index: number) => { + setErrorIndexList(prev => { + if (!prev.includes(index)) { + return [...prev, index]; + } + return prev; + }); + }; + const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number, field: BillInputType) => { if (e.nativeEvent.isComposing) return; @@ -116,7 +138,7 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe // list 인자를 넘겨주면 그 인자로 찾고, 없다면 InputPairList state를 사용합니다. const getFilledInputPairList = (list?: InputPair[]) => { - return (list ?? inputPairList).filter(({title, price}) => title !== '' && price !== ''); + return (list ?? inputPairList).filter(({title, price}) => title.trim().length !== 0 && price.trim().length !== 0); }; const isLastInputPairFilled = ({index, value}: {index: number; field: BillInputType; value: string}) => { @@ -129,6 +151,7 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe inputPairList, getFilledInputPairList, inputRefList, + errorIndexList, handleInputChange, deleteEmptyInputPairElementOnBlur, errorMessage, diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index 12fdd4319..02f91bf02 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -16,13 +16,15 @@ export type ReturnUseDynamicInput = { getFilledInputList: (list?: InputValue[]) => InputValue[]; focusNextInputOnEnter: (e: React.KeyboardEvent<HTMLInputElement>, index: number) => void; canSubmit: boolean; + errorIndexList: number[]; setInputValueTargetIndex: (index: number, value: string) => void; }; const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { - const [inputList, setInputList] = useState<InputValue[]>([{value: '', index: 0}]); + const [inputList, setInputList] = useState<InputValue[]>([{index: 0, value: ''}]); const inputRefList = useRef<(HTMLInputElement | null)[]>([]); const [errorMessage, setErrorMessage] = useState(''); + const [errorIndexList, setErrorIndexList] = useState<number[]>([]); const [canSubmit, setCanSubmit] = useState(false); useEffect(() => { @@ -40,43 +42,39 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return const {isValid: isValidInput, errorMessage: validationResultMessage} = validateFunc(value); // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수 분리필요 - if (isLastInputFilled(index, value)) { + if (isLastInputFilled(index, value) && value.trim().length !== 0) { // 마지막 인풋이 한 자라도 채워진다면 새로운 인풋을 생성해 간편한 다음 입력을 유도합니다. - - setErrorMessage(''); setInputList(prevInputs => { const updatedInputList = [...prevInputs]; - const targetInput = findInputByIndex(index, updatedInputList); - - targetInput.value = value; // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 const newIndex = updatedInputList[updatedInputList.length - 1].index + 1; return [...updatedInputList, {index: newIndex, value: ''}]; }); - } else if (isValidInput || value.length === 0) { - // 인풋이 비어있다면 새로운 인풋을 생성하지 않습니다. - + } else if (isValidInput) { + // 입력된 값이 유효하면 데이터(inputLis)를 변경합니다. setErrorMessage(''); - setInputList(prevInputs => { - const updatedInputList = [...prevInputs]; - const targetInput = findInputByIndex(index, updatedInputList); - targetInput.value = value; + if (errorIndexList.includes(index)) { + setErrorIndexList(prev => prev.filter(i => i !== index)); + } - return updatedInputList; - }); + changeInputListValue(index, value); + } else if (value.length === 0) { + // value의 값이 0이라면 errorMessage는 띄워지지 않지만 값은 변경됩니다. 또한 invalid한 값이기에 errorIndex에 추가합니다. + + setErrorMessage(''); + changeErrorIndex(index); + + changeInputListValue(index, value); } else { - // 유효성 검사에 실패한 입력입니다. 이전 입력으로 복구하고 에러 메세지를 세팅합니다. + // 유효성 검사에 실패한 입력입니다. 에러 메세지를 세팅합니다. - // index에 해당하는 아이템을 찾습니다. const targetInput = findInputByIndex(index); - // 오류가 난 값말고 기존의 값을 사용합니다. - event.target.value = targetInput.value; - setErrorMessage(validationResultMessage ?? ''); + changeErrorIndex(targetInput.index); } handleCanSubmit(); @@ -110,6 +108,26 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return } }; + const changeInputListValue = (index: number, value: string) => { + setInputList(prevInputs => { + const updatedInputList = [...prevInputs]; + const targetInput = findInputByIndex(index, updatedInputList); + + targetInput.value = value; + + return updatedInputList; + }); + }; + + const changeErrorIndex = (index: number) => { + setErrorIndexList(prev => { + if (!prev.includes(index)) { + return [...prev, index]; + } + return prev; + }); + }; + const setInputValueTargetIndex = (index: number, value: string) => { setInputList(prevInputs => { const updatedInputList = [...prevInputs]; @@ -137,7 +155,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return // list 인자를 넘겨주면 그 인자로 찾고, 없다면 inputList state를 사용합니다. const getFilledInputList = (list?: InputValue[]) => { - return (list ?? inputList).filter(({value}) => value !== ''); + return (list ?? inputList).filter(({value}) => value.trim().length !== 0); }; const isLastInputFilled = (index: number, value: string) => { @@ -155,6 +173,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return getFilledInputList, focusNextInputOnEnter, canSubmit, + errorIndexList, setInputValueTargetIndex, // TODO: (@weadie) 네이밍 수정 }; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 7064bd187..2269f568c 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -33,7 +33,6 @@ const AdminPage = () => { try { await postAuthentication({eventId: eventId}); } catch (error) { - console.log(error); navigate(`${ROUTER_URLS.event}/${eventId}/login`); } }; diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts index aa1bc263f..165cf323b 100644 --- a/client/src/utils/sendLogToSentry.ts +++ b/client/src/utils/sendLogToSentry.ts @@ -32,7 +32,6 @@ const sendLogToSentry = ({level = 'error', error, errorBody}: SendLogToSentry) = scope.setTag('environment', process.env.NODE_ENV); if (error instanceof FetchError) { - console.log('fetchError'); scope.setTags({ endpoint: error.endpoint, url: window.location.href, From e47972a098da80ef328aca4c603c01c64f9079a8 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Tue, 13 Aug 2024 10:23:30 +0900 Subject: [PATCH 150/273] =?UTF-8?q?feat:=20=ED=99=88=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=A7=81=ED=81=AC=20=EB=B3=B5=EC=82=AC=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#329)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --- HDesign/package-lock.json | 4 +- HDesign/package.json | 2 +- HDesign/src/components/TopNav/TopNav.style.ts | 4 ++ client/package-lock.json | 8 +-- client/package.json | 2 +- .../CompleteCreateEventPage.tsx | 10 ++-- .../pages/EventPage/AdminPage/AdminPage.tsx | 17 ++----- .../src/pages/EventPage/EventPageLayout.tsx | 51 +++++++++++++++++-- .../src/pages/EventPage/HomePage/HomePage.tsx | 21 ++------ 9 files changed, 73 insertions(+), 46 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index dd407a7ac..192588f72 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.68", + "version": "0.1.69", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.68", + "version": "0.1.69", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index 8576b20a9..4e555b3fc 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.68", + "version": "0.1.69", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/HDesign/src/components/TopNav/TopNav.style.ts index 44e7695e7..9ca69c7b0 100644 --- a/HDesign/src/components/TopNav/TopNav.style.ts +++ b/HDesign/src/components/TopNav/TopNav.style.ts @@ -2,12 +2,16 @@ import {css} from '@emotion/react'; export const topNavStyle = css({ display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', padding: '0 1rem', width: '100%', }); export const topNavNonStyle = css({ display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', padding: '0 1rem', width: '100%', height: '1.5rem', diff --git a/client/package-lock.json b/client/package-lock.json index fef8ea21d..bae073c41 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", - "haengdong-design": "^0.1.67", + "haengdong-design": "^0.1.69", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -7250,9 +7250,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.67", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.67.tgz", - "integrity": "sha512-ULQFB+wBUBENt3SBL3/Ve5li2YKzJtbQ5eq7Lz1I6Gp1SGBeTu1ooLQ/GqRTmVdASoulEkupaNuoMZQqsg17bg==", + "version": "0.1.69", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.69.tgz", + "integrity": "sha512-XlZ7hnKn51aQOOz/x+hNM6tLjJDvvTOqLiVfOSjEvRpkMKquNWFoijclXHLNhK7tqrb6m+hDREf12mIXwSN/Ew==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index badca9598..64e1860fe 100644 --- a/client/package.json +++ b/client/package.json @@ -52,7 +52,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", - "haengdong-design": "^0.1.67", + "haengdong-design": "^0.1.69", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 2abcbda9b..200642f30 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -21,12 +21,14 @@ const CompleteCreateEventPage = () => { // TODO: (@weadie) eventId가 없는 경우에 대한 처리 필요 setUrl(eventId ?? ''); }; - getUrl(); }, []); const {showToast} = useToast(); + const env = process.env.NODE_ENV || ''; + const homeUrlByEnvironment = `https://${env.includes('development') ? 'dev.' : ''}haengdong.pro${ROUTER_URLS.event}/${url}/home`; + return ( <MainLayout> <TopNav children={<></>} /> @@ -39,17 +41,17 @@ const CompleteCreateEventPage = () => { <Text textColor="gray">링크가 없으면 페이지에 접근할 수 없어요.</Text> <Text textColor="primary">관리를 위해서 행사 링크를 복사 후 보관해 주세요.</Text> </Flex> - <Input value={`haengdong.pro${ROUTER_URLS.event}/${url}/home`} disabled /> + <Input value={homeUrlByEnvironment} disabled /> <CopyToClipboard - text={`haengdong.pro${ROUTER_URLS.event}/${url}/home`} + text={homeUrlByEnvironment} onCopy={() => showToast({ showingTime: 3000, message: '링크가 복사되었어요 :) \n링크를 절대 분실하지 마세요!', type: 'confirm', position: 'bottom', - bottom: '14rem', + bottom: '8rem', }) } > diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 2269f568c..d11409a33 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,6 +1,6 @@ import {useEffect, useState} from 'react'; import {Title, FixedButton, ListButton} from 'haengdong-design'; -import {useNavigate} from 'react-router-dom'; +import {useNavigate, useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; import {requestGetEventName} from '@apis/request/event'; @@ -12,20 +12,20 @@ import useAuth from '@hooks/useAuth'; import {ROUTER_URLS} from '@constants/routerUrls'; +import {EventPageContextProps} from '../EventPageLayout'; + import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; const AdminPage = () => { + const {eventId, eventName} = useOutletContext<EventPageContextProps>(); + const [isOpenFixedButtonBottomSheet, setIsOpenFixedBottomBottomSheet] = useState(false); const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); - // TODO: (@weadie) eventName이 새로고침시 공간이 없다가 생겨나 레이아웃이 움직이는 문제 - const [eventName, setEventName] = useState(' '); const {getTotalPrice, allMemberList} = useStepList(); - const {eventId} = useEventId(); const {postAuthentication} = useAuth(); const navigate = useNavigate(); - // TODO: (@weadie) 아래 로직을 훅으로 분리합니다. useEffect(() => { if (eventId === '') return; @@ -37,14 +37,7 @@ const AdminPage = () => { } }; - const getEventName = async () => { - const {eventName} = await requestGetEventName({eventId: eventId}); - - setEventName(eventName); - }; - postAuth(); - getEventName(); }, [eventId]); const handleOpenAllMemberListButton = () => { diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 49b1145be..bb6d0a15f 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,31 +1,72 @@ -import {MainLayout, TopNav, Switch} from 'haengdong-design'; -import {Outlet, useMatch} from 'react-router-dom'; -import {useState} from 'react'; +import {MainLayout, TopNav, Switch, Button, Flex} from 'haengdong-design'; +import {Outlet, useLocation, useMatch, useNavigate} from 'react-router-dom'; +import {useEffect, useState} from 'react'; +import CopyToClipboard from 'react-copy-to-clipboard'; + +import {useToast} from '@components/Toast/ToastProvider'; +import {requestGetEventName} from '@apis/request/event'; -import StepListProvider from '@hooks/useStepList'; import useNavSwitch from '@hooks/useNavSwitch'; +import StepListProvider from '@hooks/useStepList'; +import useEventId from '@hooks/useEventId'; import {ROUTER_URLS} from '@constants/routerUrls'; export type EventPageContextProps = { isAdmin: boolean; + eventId: string; + eventName: string; }; const EventPageLayout = () => { const {nav, paths, onChange} = useNavSwitch(); - const [order, setOrder] = useState<number>(1); + const {eventId} = useEventId(); + const [eventName, setEventName] = useState(''); + + useEffect(() => { + const getEventName = async () => { + const {eventName} = await requestGetEventName({eventId: eventId}); + + setEventName(eventName); + }; + + getEventName(); + }, [eventId]); + const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; const outletContext: EventPageContextProps = { isAdmin, + eventId, + eventName, }; + const {showToast} = useToast(); + + const env = process.env.NODE_ENV || ''; + return ( <StepListProvider> <MainLayout backgroundColor="gray"> <TopNav> <Switch value={nav} values={paths} onChange={onChange} /> + <CopyToClipboard + text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\nhttps://${env.includes('development') ? 'dev.' : ''}haengdong.pro${ROUTER_URLS.event}/${eventId}/home`} + onCopy={() => + showToast({ + showingTime: 3000, + message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', + type: 'confirm', + position: 'bottom', + bottom: '8rem', + }) + } + > + <Button size="small" variants="secondary"> + 정산 초대하기 + </Button> + </CopyToClipboard> </TopNav> <Outlet context={outletContext} /> </MainLayout> diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index cc989a7b3..1d7561a0c 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -1,31 +1,18 @@ import {Tab, Tabs, Title} from 'haengdong-design'; import {useEffect, useState} from 'react'; +import {useOutletContext} from 'react-router-dom'; import MemberReportList from '@components/MemberReportList/MemberReportList'; import StepList from '@components/StepList/StepList'; import {requestGetEventName} from '@apis/request/event'; import {useStepList} from '@hooks/useStepList'; -import useEventId from '@hooks/useEventId'; + +import {EventPageContextProps} from '../EventPageLayout'; const HomePage = () => { + const {eventName} = useOutletContext<EventPageContextProps>(); const {getTotalPrice} = useStepList(); - const {eventId} = useEventId(); - - // TODO: (@soha) 행사 이름 나중에 따로 분리해야 함 - const [eventName, setEventName] = useState(' '); - - useEffect(() => { - if (eventId === '') return; - - const getEventName = async () => { - const {eventName} = await requestGetEventName({eventId: eventId ?? ''}); - - setEventName(eventName); - }; - - getEventName(); - }, [eventId]); return ( <div> From eb5d9ce8bdcf90787ab2a6cfc69eda8902b0b187 Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:20:00 +0900 Subject: [PATCH 151/273] =?UTF-8?q?feat:=20pr=20issue=20close=20workflow?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20(#328)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pr-issue-close.yml | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/pr-issue-close.yml diff --git a/.github/workflows/pr-issue-close.yml b/.github/workflows/pr-issue-close.yml new file mode 100644 index 000000000..c37eb255d --- /dev/null +++ b/.github/workflows/pr-issue-close.yml @@ -0,0 +1,33 @@ +name: Close Issue on PR Merge + +on: + pull_request: + types: [closed] + +jobs: + close-issue: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Extract issue number from PR body + id: extract_issue + run: | + # Fetch PR body + PR_BODY=$(curl -s -H "Authorization: token ${{ secrets.CONFIG_SUBMODULE_TOKEN }}" \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}" \ + | jq -r '.body') + # Extract issue number from PR body using regex (customize if needed) + ISSUE_NUMBER=$(echo "$PR_BODY" | grep -oP '#\d+' | head -1 | sed 's/#//') + echo "ISSUE_NUMBER=$ISSUE_NUMBER" >> $GITHUB_ENV + - name: Close associated issue + if: env.ISSUE_NUMBER != '' + run: | + echo "Closing issue #${{ env.ISSUE_NUMBER }}" + curl -s -X PATCH -H "Authorization: token ${{ secrets.CONFIG_SUBMODULE_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + -d '{"state": "closed"}' \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ env.ISSUE_NUMBER }}" From f3f05f6575411b273bb5aa6394346249e5a2a31e Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Wed, 14 Aug 2024 09:58:46 +0900 Subject: [PATCH 152/273] =?UTF-8?q?test:=20cypress=20=EC=A0=81=EC=9A=A9=20?= =?UTF-8?q?=EB=B0=8F=20=ED=96=89=EC=82=AC=20=EC=83=9D=EC=84=B1=20flow=20e2?= =?UTF-8?q?e=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1=20(#331)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: cypress 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> --- .github/workflows/frontend-pull-request.yml | 15 +- client/cypress.config.ts | 12 + client/cypress/constants/constants.ts | 6 + client/cypress/e2e/createEvent.cy.ts | 79 + client/cypress/fixtures/postEvent.json | 3 + client/cypress/support/commands.ts | 58 + client/cypress/support/e2e.ts | 1 + client/package-lock.json | 1702 ++++++++++++++++++- client/package.json | 6 +- client/tsconfig.json | 4 +- client/webpack.dev.mjs | 8 +- 11 files changed, 1824 insertions(+), 70 deletions(-) create mode 100644 client/cypress.config.ts create mode 100644 client/cypress/constants/constants.ts create mode 100644 client/cypress/e2e/createEvent.cy.ts create mode 100644 client/cypress/fixtures/postEvent.json create mode 100644 client/cypress/support/commands.ts create mode 100644 client/cypress/support/e2e.ts diff --git a/.github/workflows/frontend-pull-request.yml b/.github/workflows/frontend-pull-request.yml index 238a9a0d1..e3461447c 100644 --- a/.github/workflows/frontend-pull-request.yml +++ b/.github/workflows/frontend-pull-request.yml @@ -18,10 +18,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: '20.15.1' @@ -32,3 +32,14 @@ jobs: - name: Run lint working-directory: ./client run: npm run lint + + - name: Cypress test + run: npm run dev & + env: + CI: true + + - name: Wait for the server to start + run: sleep 3 + + - name: Run Cypress tests + run: npm run cypress-run \ No newline at end of file diff --git a/client/cypress.config.ts b/client/cypress.config.ts new file mode 100644 index 000000000..2261e7871 --- /dev/null +++ b/client/cypress.config.ts @@ -0,0 +1,12 @@ +import {defineConfig} from 'cypress'; + +export default defineConfig({ + e2e: { + baseUrl: 'http://localhost:3000', + viewportWidth: 430, + viewportHeight: 930, + // setupNodeEvents(on, config) { + // // implement node event listeners here + // }, + }, +}); diff --git a/client/cypress/constants/constants.ts b/client/cypress/constants/constants.ts new file mode 100644 index 000000000..393ef5361 --- /dev/null +++ b/client/cypress/constants/constants.ts @@ -0,0 +1,6 @@ +const CONSTANTS = { + eventName: '테스트 이벤트', + eventPassword: '1234', +}; + +export default CONSTANTS; diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts new file mode 100644 index 000000000..dcfa04ee0 --- /dev/null +++ b/client/cypress/e2e/createEvent.cy.ts @@ -0,0 +1,79 @@ +import CONSTANTS from '../constants/constants'; +beforeEach(() => { + cy.blockSentry(); +}); + +describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 flow', () => { + it('랜딩페이지에서 "행사 생성하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { + cy.visit('/'); + cy.get('button').should('have.text', '행사 생성하기').click(); + cy.url().should('include', '/event/create/name'); + }); + + context('행사 이름 입력 페이지', () => { + beforeEach(() => { + cy.visit('/event/create/name'); + }); + + it('행사 이름 입력 페이지에서 input이 포커싱 되어 있고, "다음" 버튼이 비활성화 되어 있어야 한다.', () => { + cy.get('input').focused(); + cy.get('button').contains('다음').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/name'); + }); + + it('행사 이름이 1자 이상 입력된 경우 "다음" 버튼이 활성화 되고, 값이 없는 경우 "다음" 버튼이 비활성화 되어야 한다.', () => { + cy.get('input').type(CONSTANTS.eventName); + cy.get('button').contains('다음').should('not.have.attr', 'disabled'); + cy.get('input').clear(); + cy.get('input').should('have.value', ''); + cy.get('button').contains('다음').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/name'); + }); + + it('행사 이름을 입력한 후 "다음" 버튼을 누르면 행사 비밀번호 설정 화면으로 이동해야 한다.', () => { + cy.get('input').type(CONSTANTS.eventName); + cy.get('button').contains('다음').click(); + cy.url().should('include', '/event/create/password'); + }); + }); + + context('행사 비밀번호 입력 페이지', () => { + beforeEach(() => { + cy.createEventName(CONSTANTS.eventName); + }); + + it('행사 비밀번호 입력 페이지에서 input이 포커싱 되어 있고, "행동 개시!" 버튼이 비활성화 되어 있어야 한다.', () => { + cy.get('input').focused(); + cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/password'); + }); + + it('행사 비밀번호에 숫자가 아닌 입력을 할 경우 값이 입력되지 않아야 한다.', () => { + cy.get('input').type('테스트'); + cy.get('input').should('have.value', ''); + }); + + it('행사 비밀번호에 4자리 이상 입력을 할 경우 처음 네 자리만 입력되어야 한다.', () => { + cy.get('input').type('12345'); + cy.get('input').should('have.value', CONSTANTS.eventPassword); + }); + + it('행사 비밀번호이 1자 이상 입력된 경우 "행동 개시!" 버튼이 활성화 되고, 값이 없는 경우 "행동 개시!" 버튼이 비활성화 되어야 한다.', () => { + cy.get('input').type(CONSTANTS.eventPassword); + cy.get('button').contains('행동 개시!').should('not.have.attr', 'disabled'); + cy.get('input').clear(); + cy.get('input').should('have.value', ''); + cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/password'); + }); + + it('행사 비밀번호을 입력한 후 "행동 개시!" 버튼을 누르면 행사 생성 완료 화면으로 이동해야 한다.', () => { + cy.interceptAPI({type: 'postEvent', statusCode: 200}); + cy.interceptAPI({type: 'getEventName', statusCode: 200}); + cy.get('input').type(CONSTANTS.eventPassword); + cy.get('button').contains('행동 개시!').click(); + + cy.url().should('include', '/event/create/complete'); + }); + }); +}); diff --git a/client/cypress/fixtures/postEvent.json b/client/cypress/fixtures/postEvent.json new file mode 100644 index 000000000..63b91e17b --- /dev/null +++ b/client/cypress/fixtures/postEvent.json @@ -0,0 +1,3 @@ +{ + "eventId": "550e8400-e29b-41d4-a716-446655440000" +} \ No newline at end of file diff --git a/client/cypress/support/commands.ts b/client/cypress/support/commands.ts new file mode 100644 index 000000000..c51d00580 --- /dev/null +++ b/client/cypress/support/commands.ts @@ -0,0 +1,58 @@ +import CONSTANTS from '../constants/constants'; + +type APIType = 'sentry' | 'postEvent' | 'getEventName'; + +interface InterceptAPIProps { + type: APIType; + delay?: number; + statusCode?: number; +} +const POST_EVENT = { + method: 'POST', + url: /.*api\/events.*/, +}; + +const GET_EVENT_NAME = { + method: 'GET', + url: /.*api\/events\.*/, +}; + +Cypress.Commands.add('blockSentry', () => { + cy.intercept('POST', /.*sentry.io\/api.*/, {statusCode: 200}).as('sentry'); +}); + +Cypress.Commands.add('interceptAPI', ({type, delay = 0, statusCode = 200}: InterceptAPIProps) => { + if (type === 'postEvent') + cy.intercept(POST_EVENT, { + delay, + statusCode, + fixture: 'postEvent.json', + }).as('postEvent'); + if (type === 'getEventName') + cy.intercept(GET_EVENT_NAME, { + delay, + statusCode, + body: { + eventName: CONSTANTS.eventName, + }, + }).as('getEventName'); +}); + +Cypress.Commands.add('createEventName', (eventName: string) => { + cy.visit('/event/create/name'); + cy.get('input').type(eventName); + cy.get('button').contains('다음').click(); + cy.url().should('include', '/event/create/password'); +}); + +declare global { + namespace Cypress { + interface Chainable { + blockSentry(): Chainable<void>; + interceptAPI(props: InterceptAPIProps): Chainable<void>; + createEventName(eventName: string): Chainable<void>; + } + } +} + +export {}; diff --git a/client/cypress/support/e2e.ts b/client/cypress/support/e2e.ts new file mode 100644 index 000000000..1221b17e0 --- /dev/null +++ b/client/cypress/support/e2e.ts @@ -0,0 +1 @@ +import './commands'; diff --git a/client/package-lock.json b/client/package-lock.json index bae073c41..f3731b138 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -29,7 +29,7 @@ "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", - "dotenv": "^16.4.5", + "cypress": "^13.13.2", "dotenv-webpack": "^8.1.0", "eslint": "^9.6.0", "eslint-import-resolver-typescript": "^3.6.1", @@ -1837,6 +1837,79 @@ "tough-cookie": "^4.1.4" } }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cypress/request": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.10.4", + "safe-buffer": "^5.1.2", + "tough-cookie": "^4.1.3", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/request/node_modules/qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -3602,6 +3675,18 @@ "@types/send": "*" } }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true + }, + "node_modules/@types/sizzle": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", + "dev": true + }, "node_modules/@types/sockjs": { "version": "0.3.36", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", @@ -3638,6 +3723,16 @@ "@types/node": "*" } }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", @@ -4092,6 +4187,19 @@ "node": ">= 6.0.0" } }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4156,6 +4264,15 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -4228,6 +4345,26 @@ "node": ">= 8" } }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4407,12 +4544,60 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", "dev": true }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -4428,6 +4613,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz", + "integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==", + "dev": true + }, "node_modules/axe-core": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", @@ -4517,12 +4717,41 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -4544,6 +4773,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "node_modules/body-parser": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", @@ -4659,6 +4900,39 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -4689,6 +4963,15 @@ "node": ">= 0.8" } }, + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -4756,6 +5039,12 @@ } ] }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4777,6 +5066,15 @@ "node": ">=0.8.0" } }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -4822,6 +5120,21 @@ "node": ">=6.0" } }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -4843,6 +5156,27 @@ "node": ">=0.10.0" } }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cli-spinners": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", @@ -4855,6 +5189,77 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/cli-width": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", @@ -4981,15 +5386,36 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, - "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, "engines": { "node": ">=14" } }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -5236,12 +5662,255 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/cypress": { + "version": "13.13.2", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.2.tgz", + "integrity": "sha512-PvJQU33933NvS1StfzEb8/mu2kMy4dABwCF+yd5Bi7Qly1HOVf+Bufrygee/tlmty/6j5lX+KIi8j9Q3JUMbhA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@cypress/request": "^3.0.1", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.7.1", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.1", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.3", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + } + }, + "node_modules/cypress/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cypress/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cypress/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cypress/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/cypress/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/cypress/node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true + }, + "node_modules/cypress/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/data-view-buffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", @@ -5293,6 +5962,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", + "dev": true + }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", @@ -5441,6 +6116,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -5634,6 +6318,16 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -5669,6 +6363,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", @@ -5682,6 +6385,19 @@ "node": ">=10.13.0" } }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -6482,6 +7198,12 @@ "node": ">= 0.6" } }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "dev": true + }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -6520,6 +7242,18 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/express": { "version": "4.19.2", "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", @@ -6577,6 +7311,56 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -6665,25 +7449,58 @@ "node": ">=0.8.0" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" + "pend": "~1.2.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" @@ -6828,6 +7645,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/fork-ts-checker-webpack-plugin": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", @@ -6960,6 +7786,20 @@ "node": ">=8" } }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -7130,6 +7970,24 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "dependencies": { + "async": "^3.2.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -7168,6 +8026,21 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globals": { "version": "15.9.0", "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", @@ -7635,6 +8508,20 @@ } } }, + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -7678,6 +8565,26 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -7730,12 +8637,30 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -7872,6 +8797,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, "node_modules/is-core-module": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", @@ -8006,6 +8943,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -8205,6 +9158,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -8281,6 +9252,12 @@ "node": ">=0.10.0" } }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, "node_modules/iterator.prototype": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", @@ -8363,6 +9340,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -8385,6 +9368,12 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -8397,6 +9386,12 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -8420,6 +9415,21 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -8481,6 +9491,15 @@ "shell-quote": "^1.8.1" } }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true, + "engines": { + "node": "> 0.8" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -8491,69 +9510,360 @@ "type-check": "~0.4.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/listr2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils-webpack-v4": { + "name": "loader-utils", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/loader-runner": { + "node_modules/log-update/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=6.11.5" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/loader-utils-webpack-v4": { - "name": "loader-utils", - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "node_modules/log-update/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "color-name": "~1.1.4" }, "engines": { - "node": ">=8.9.0" + "node": ">=7.0.0" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/log-update/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "dependencies": { - "p-locate": "^5.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/loose-envify": { "version": "1.4.0", @@ -9211,6 +10521,15 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -9261,6 +10580,12 @@ "node": ">= 0.8.0" } }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "dev": true + }, "node_modules/outvariant": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", @@ -9297,6 +10622,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-retry": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", @@ -9457,6 +10797,18 @@ "node": ">=8" } }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, "node_modules/picocolors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", @@ -9474,6 +10826,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -9583,6 +10944,18 @@ "node": ">=6.0.0" } }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pretty-error": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", @@ -9593,6 +10966,15 @@ "renderkid": "^3.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -9652,6 +11034,16 @@ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -9988,6 +11380,15 @@ "strip-ansi": "^6.0.1" } }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "dependencies": { + "throttleit": "^1.0.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -10066,6 +11467,19 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -10085,6 +11499,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, "node_modules/rimraf": { "version": "5.0.10", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", @@ -10135,6 +11555,15 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-array-concat": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", @@ -10509,6 +11938,53 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", @@ -10594,6 +12070,31 @@ "wbuf": "^1.7.3" } }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -11077,12 +12578,36 @@ "tslib": "^2" } }, + "node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true, + "engines": { + "node": ">=14.14" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -11315,6 +12840,24 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -11551,6 +13094,15 @@ "webpack-virtual-modules": "^0.5.0" } }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", @@ -11638,6 +13190,26 @@ "node": ">= 0.8" } }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, "node_modules/watchpack": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", @@ -12305,6 +13877,12 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", @@ -12395,6 +13973,16 @@ "node": ">=8" } }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/client/package.json b/client/package.json index 64e1860fe..c73dae15d 100644 --- a/client/package.json +++ b/client/package.json @@ -9,7 +9,9 @@ "build": "NODE_ENV=production webpack --config webpack.prod.mjs", "build-dev": "NODE_ENV=development webpack --config webpack.dev.mjs", "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", - "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'" + "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", + "cypress-open": "cypress open", + "cypress-run": "cypress run" }, "keywords": [], "author": "", @@ -25,7 +27,7 @@ "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", - "dotenv": "^16.4.5", + "cypress": "^13.13.2", "dotenv-webpack": "^8.1.0", "eslint": "^9.6.0", "eslint-import-resolver-typescript": "^3.6.1", diff --git a/client/tsconfig.json b/client/tsconfig.json index a80c56bbd..f409ed6f5 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -20,7 +20,7 @@ // "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "types": ["node", "jest"], + "types": ["node", "cypress"], "esModuleInterop": true, "strictNullChecks": true, "strictFunctionTypes": true, @@ -48,5 +48,5 @@ "outDir": "./dist" }, "node": true, - "include": ["src"] + "include": ["src", "cypress/**/*.ts"] } diff --git a/client/webpack.dev.mjs b/client/webpack.dev.mjs index bfe53d51b..5ad42ed45 100644 --- a/client/webpack.dev.mjs +++ b/client/webpack.dev.mjs @@ -3,7 +3,6 @@ import {merge} from 'webpack-merge'; import Dotenv from 'dotenv-webpack'; import common from './webpack.common.mjs'; import {fileURLToPath} from 'url'; -import {sentryWebpackPlugin} from '@sentry/webpack-plugin'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -17,7 +16,7 @@ export default merge(common, { clean: true, publicPath: '/', }, - devtool: 'source-map', + devtool: 'eval-source-map', devServer: { port: 3000, historyApiFallback: true, @@ -30,10 +29,5 @@ export default merge(common, { new Dotenv({ path: '.env.dev', }), - sentryWebpackPlugin({ - authToken: process.env.SENTRY_AUTH_TOKEN, - org: 'wtc-o6', - project: 'javascript-react', - }), ], }); From 6894c08516856251b3b4f79887f888765c1ac73f Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:09:47 +0900 Subject: [PATCH 153/273] =?UTF-8?q?fix:=20=ED=86=A0=ED=81=B0=EC=9D=B4=20?= =?UTF-8?q?=EC=97=86=EC=9D=84=20=EB=95=8C,=20=EA=B4=80=EB=A6=AC=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=95=98?= =?UTF-8?q?=EB=A9=B4=20=EC=98=A4=EB=A5=98=EA=B0=80=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#338)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 --- client/src/apis/useFetch.ts | 5 ++-- client/src/constants/regExp.ts | 1 + client/src/hooks/useDeleteMemberAction.tsx | 5 ++-- client/src/hooks/useEventId.tsx | 25 ------------------- client/src/hooks/usePutAndDeleteBillAction.ts | 5 ++-- client/src/hooks/useSearchInMemberList.ts | 8 +++--- .../src/hooks/useSearchMemberReportList.tsx | 9 +++---- client/src/hooks/useSetAllMemberList.tsx | 4 +-- client/src/hooks/useStepList.tsx | 19 ++++++-------- .../pages/EventPage/AdminPage/AdminPage.tsx | 17 +++---------- .../EventPage/AdminPage/EventLoginPage.tsx | 9 ++++--- .../src/pages/EventPage/EventPageLayout.tsx | 9 ++++--- client/src/utils/getEventIdByUrl.ts | 13 ++++++++++ 13 files changed, 51 insertions(+), 78 deletions(-) delete mode 100644 client/src/hooks/useEventId.tsx create mode 100644 client/src/utils/getEventIdByUrl.ts diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts index 12350e798..b5f94df84 100644 --- a/client/src/apis/useFetch.ts +++ b/client/src/apis/useFetch.ts @@ -1,9 +1,8 @@ import {useState} from 'react'; import {NavigateFunction, useNavigate} from 'react-router-dom'; -import useEventId from '@hooks/useEventId'; - import sendLogToSentry from '@utils/sendLogToSentry'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; import {UNKNOWN_ERROR} from '@constants/errorMessage'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -21,7 +20,7 @@ export const useFetch = () => { const {setError, clearError} = useError(); const [loading, setLoading] = useState(false); const navigate = useNavigate(); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const fetch = async <T>({queryFunction, onSuccess, onError}: FetchProps<T>): Promise<T> => { setLoading(true); diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts index ab9d5fcc0..4d910ac99 100644 --- a/client/src/constants/regExp.ts +++ b/client/src/constants/regExp.ts @@ -2,6 +2,7 @@ const REGEXP = { eventPassword: /^[0-9]*$/, memberName: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s]*$/, purchaseTitle: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s]*$/, + eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, }; export default REGEXP; diff --git a/client/src/hooks/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction.tsx index 0a2c0ac95..1883929f2 100644 --- a/client/src/hooks/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction.tsx @@ -5,18 +5,19 @@ import {useState} from 'react'; import {useToast} from '@components/Toast/ToastProvider'; import {requestDeleteMemberAction} from '@apis/request/member'; -import useEventId from '@hooks/useEventId'; import {useStepList} from '@hooks/useStepList'; import {useFetch} from '@apis/useFetch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + const useDeleteMemberAction = ( memberActionList: MemberAction[], setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>, ) => { const {stepList, refreshStepList} = useStepList(); const [aliveActionList, setAliveActionList] = useState<MemberAction[]>(memberActionList); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {showToast} = useToast(); const {fetch} = useFetch(); diff --git a/client/src/hooks/useEventId.tsx b/client/src/hooks/useEventId.tsx deleted file mode 100644 index ca3775f8e..000000000 --- a/client/src/hooks/useEventId.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import {useEffect, useState} from 'react'; -import {useLocation} from 'react-router-dom'; - -const useEventId = () => { - const [eventId, setEventId] = useState(''); - const location = useLocation(); - - const extractIdFromUrl = (url: string) => { - const regex = /\/event\/([a-zA-Z0-9-]+)\//; - const match = url.match(regex); - return match ? match[1] : null; - }; - - const curEventId = extractIdFromUrl(location.pathname) ?? ''; - - useEffect(() => { - setEventId(curEventId); - }, []); - - return { - eventId, - }; -}; - -export default useEventId; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 445172f21..9cb399ef8 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -5,12 +5,13 @@ import {useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; import {requestDeleteBillAction, requestPutBillAction} from '@apis/request/bill'; -import useEventId from '@hooks/useEventId'; import {useStepList} from '@hooks/useStepList'; import {BillInputType, InputPair} from '@hooks/useDynamicBillActionInput'; import {useFetch} from '@apis/useFetch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + import ERROR_MESSAGE from '@constants/errorMessage'; const usePutAndDeleteBillAction = ( @@ -18,7 +19,7 @@ const usePutAndDeleteBillAction = ( validateFunc: (inputPair: Bill) => ValidateResult, onClose: () => void, ) => { - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {refreshStepList} = useStepList(); const {fetch} = useFetch(); diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index d8acfb00c..fb9b547a6 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -4,7 +4,7 @@ import {requestGetCurrentInMemberList} from '@apis/request/member'; import {useFetch} from '@apis/useFetch'; -import useEventId from './useEventId'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; export type ReturnUseSearchInMemberList = { currentInputIndex: number; @@ -17,7 +17,7 @@ export type ReturnUseSearchInMemberList = { const useSearchInMemberList = ( setInputValueTargetIndex: (index: number, value: string) => void, ): ReturnUseSearchInMemberList => { - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {fetch} = useFetch(); const [currentInputIndex, setCurrentInputIndex] = useState(-1); @@ -29,15 +29,13 @@ const useSearchInMemberList = ( const [filteredInMemberList, setFilteredInMemberList] = useState<Array<string>>([]); useEffect(() => { - if (eventId === '') return; - const getCurrentInMembers = async () => { const currentInMemberListFromServer = await fetch({queryFunction: () => requestGetCurrentInMemberList(eventId)}); setCurrentInMemberList(currentInMemberListFromServer.members); }; getCurrentInMembers(); - }, [eventId]); + }, []); const filterMatchItems = (keyword: string) => { if (keyword.trim() === '') return []; diff --git a/client/src/hooks/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList.tsx index 7dca34b68..ccbc5358f 100644 --- a/client/src/hooks/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList.tsx @@ -4,10 +4,10 @@ import {useEffect, useState} from 'react'; import {requestGetMemberReportList} from '@apis/request/report'; -import useEventId from '@hooks/useEventId'; - import {useFetch} from '@apis/useFetch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + type UseSearchMemberReportListParams = { name: string; }; @@ -15,21 +15,20 @@ type UseSearchMemberReportListParams = { const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { const [memberReportList, setMemberReportList] = useState<MemberReport[]>([]); const [memberReportSearchList, setMemberReportSearchList] = useState<MemberReport[]>([]); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {fetch} = useFetch(); useEffect(() => { const fetchMemberReportList = async () => { // TODO: (@weadie) cors 고쳐지면 주석 풀게요. // TODO: (@weadie) eventId에 의존하는 두 개의 훅에 대한 리펙토링 필요 - if (eventId === '') return; const memberReportListData = await fetch({queryFunction: () => requestGetMemberReportList({eventId})}); setMemberReportList(memberReportListData); }; fetchMemberReportList(); - }, [eventId]); + }, []); // TODO: (@weadie) 글자가 완성될 때마다 아래 로직이 실행되어야 합니다. useEffect(() => { diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index c0c14c13a..44066dbf6 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -6,8 +6,8 @@ import {MemberChange, requestDeleteAllMemberList, requestPutAllMemberList} from import {useFetch} from '@apis/useFetch'; import isArraysEqual from '@utils/isArraysEqual'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; -import useEventId from './useEventId'; import {useStepList} from './useStepList'; interface UseSetAllMemberListProps { @@ -29,7 +29,7 @@ const useSetAllMemberList = ({ const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); const {refreshStepList} = useStepList(); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {fetch} = useFetch(); useEffect(() => { diff --git a/client/src/hooks/useStepList.tsx b/client/src/hooks/useStepList.tsx index d0f31abaa..4898925a6 100644 --- a/client/src/hooks/useStepList.tsx +++ b/client/src/hooks/useStepList.tsx @@ -6,10 +6,10 @@ import {requestPostBillList} from '@apis/request/bill'; import {requestGetAllMemberList, requestPostMemberList} from '@apis/request/member'; import {requestGetStepList} from '@apis/request/stepList'; -import useEventId from '@hooks/useEventId'; - import {useFetch} from '@apis/useFetch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + interface StepListContextProps { stepList: (BillStep | MemberStep)[]; allMemberList: string[]; @@ -25,16 +25,7 @@ const StepListProvider = ({children}: PropsWithChildren) => { const {fetch} = useFetch(); const [stepList, setStepList] = useState<(BillStep | MemberStep)[]>([]); const [allMemberList, setAllMemberList] = useState<string[]>([]); - - const {eventId} = useEventId(); - - useEffect(() => { - if (eventId === '') return; - - refreshStepList(); - - // TODO: (@weadie) useEffect를 꼭 써야하는가? - }, [eventId]); + const eventId = getEventIdByUrl(); const refreshStepList = async () => { const stepList = await fetch({queryFunction: () => requestGetStepList({eventId})}); @@ -43,6 +34,10 @@ const StepListProvider = ({children}: PropsWithChildren) => { setStepList(stepList); }; + useEffect(() => { + refreshStepList(); + }, []); + const updateMemberList = async ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => { try { await fetch({queryFunction: () => requestPostMemberList({eventId, type, memberNameList})}); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index d11409a33..a1ea053d9 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,17 +1,13 @@ import {useEffect, useState} from 'react'; import {Title, FixedButton, ListButton} from 'haengdong-design'; -import {useNavigate, useOutletContext} from 'react-router-dom'; +import {useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; -import {requestGetEventName} from '@apis/request/event'; import {ModalBasedOnMemberCount} from '@components/Modal/index'; import {useStepList} from '@hooks/useStepList'; -import useEventId from '@hooks/useEventId'; import useAuth from '@hooks/useAuth'; -import {ROUTER_URLS} from '@constants/routerUrls'; - import {EventPageContextProps} from '../EventPageLayout'; import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; @@ -24,21 +20,14 @@ const AdminPage = () => { const {getTotalPrice, allMemberList} = useStepList(); const {postAuthentication} = useAuth(); - const navigate = useNavigate(); useEffect(() => { - if (eventId === '') return; - const postAuth = async () => { - try { - await postAuthentication({eventId: eventId}); - } catch (error) { - navigate(`${ROUTER_URLS.event}/${eventId}/login`); - } + await postAuthentication({eventId: eventId}); }; postAuth(); - }, [eventId]); + }, []); const handleOpenAllMemberListButton = () => { setIsOpenFixedBottomBottomSheet(prev => !prev); diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index fda0d841c..d9c8c2128 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,13 +1,14 @@ import {useState} from 'react'; -import {useLocation, useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back, Switch} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Switch} from 'haengdong-design'; import validateEventPassword from '@utils/validate/validateEventPassword'; -import useEventId from '@hooks/useEventId'; import useAuth from '@hooks/useAuth'; import useNavSwitch from '@hooks/useNavSwitch'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + import RULE from '@constants/rule'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -17,7 +18,7 @@ const EventLoginPage = () => { const [errorMessage, setErrorMessage] = useState(''); const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); - const {eventId} = useEventId(); + const eventId = getEventIdByUrl(); const {postLogin} = useAuth(); const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index bb6d0a15f..13a6aa67a 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,5 +1,5 @@ import {MainLayout, TopNav, Switch, Button, Flex} from 'haengdong-design'; -import {Outlet, useLocation, useMatch, useNavigate} from 'react-router-dom'; +import {Outlet, useMatch} from 'react-router-dom'; import {useEffect, useState} from 'react'; import CopyToClipboard from 'react-copy-to-clipboard'; @@ -8,7 +8,8 @@ import {requestGetEventName} from '@apis/request/event'; import useNavSwitch from '@hooks/useNavSwitch'; import StepListProvider from '@hooks/useStepList'; -import useEventId from '@hooks/useEventId'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -21,8 +22,8 @@ export type EventPageContextProps = { const EventPageLayout = () => { const {nav, paths, onChange} = useNavSwitch(); - const {eventId} = useEventId(); const [eventName, setEventName] = useState(''); + const eventId = getEventIdByUrl(); useEffect(() => { const getEventName = async () => { @@ -32,7 +33,7 @@ const EventPageLayout = () => { }; getEventName(); - }, [eventId]); + }, []); const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; diff --git a/client/src/utils/getEventIdByUrl.ts b/client/src/utils/getEventIdByUrl.ts new file mode 100644 index 000000000..f52885215 --- /dev/null +++ b/client/src/utils/getEventIdByUrl.ts @@ -0,0 +1,13 @@ +import REGEXP from '@constants/regExp'; + +const extractEventIdFromUrl = (url: string) => { + const regex = REGEXP.eventUrl; + const match = url.match(regex); + return match ? match[1] : null; +}; + +const getEventIdByUrl = () => { + return extractEventIdFromUrl(window.location.pathname) || ''; +}; + +export default getEventIdByUrl; From f516a03afafba4326dd8fdcae2d4f07ac3c6eebd Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 14 Aug 2024 17:43:06 +0900 Subject: [PATCH 154/273] =?UTF-8?q?fix:=20=EC=9D=B8=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=EC=A3=BC=20=EC=B6=94=EA=B0=80=20=EC=8B=9C=20disable=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20(#339)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 --- .../OutMember.tsx | 4 +- client/src/hooks/useDynamicInput.tsx | 42 ++++++++++--------- client/src/hooks/useSearchInMemberList.ts | 4 +- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx index 4a2fe855f..d139261fd 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -15,10 +15,10 @@ const OutMember = ({dynamicProps}: OutMemberProps) => { deleteEmptyInputElementOnBlur, focusNextInputOnEnter, handleInputChange, - setInputValueTargetIndex, + validateAndSetTargetInput, } = dynamicProps; const {currentInputIndex, filteredInMemberList, handleCurrentInputIndex, searchCurrentInMember, chooseMember} = - useSearchInMemberList(setInputValueTargetIndex); + useSearchInMemberList(validateAndSetTargetInput); const validationAndSearchOnChange = (inputIndex: number, event: React.ChangeEvent<HTMLInputElement>) => { handleCurrentInputIndex(inputIndex); diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index 02f91bf02..3584d3a05 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -17,7 +17,7 @@ export type ReturnUseDynamicInput = { focusNextInputOnEnter: (e: React.KeyboardEvent<HTMLInputElement>, index: number) => void; canSubmit: boolean; errorIndexList: number[]; - setInputValueTargetIndex: (index: number, value: string) => void; + validateAndSetTargetInput: (index: number, value: string) => void; }; const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { @@ -37,11 +37,15 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return } }, [inputList]); + // event에서 value를 받아와서 새 인풋을 만들고 검증 후 set 하는 함수 const handleInputChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; - const {isValid: isValidInput, errorMessage: validationResultMessage} = validateFunc(value); + makeNewInputWhenFirstCharacterInput(index, value); + validateAndSetTargetInput(index, value); + }; - // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수 분리필요 + // 첫 번째 문자가 입력됐을 때 새로운 인풋이 생기는 기능 분리 + const makeNewInputWhenFirstCharacterInput = (index: number, value: string) => { if (isLastInputFilled(index, value) && value.trim().length !== 0) { // 마지막 인풋이 한 자라도 채워진다면 새로운 인풋을 생성해 간편한 다음 입력을 유도합니다. setInputList(prevInputs => { @@ -52,8 +56,15 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return return [...updatedInputList, {index: newIndex, value: ''}]; }); - } else if (isValidInput) { - // 입력된 값이 유효하면 데이터(inputLis)를 변경합니다. + } + }; + + // onChange와 setValue 둘 다 지원하기 위해서 validate를 분리 + const validateAndSetTargetInput = (index: number, value: string) => { + const {isValid: isValidInput, errorMessage: validationResultMessage} = validateFunc(value); + + if (isValidInput) { + // 입력된 값이 유효하면 데이터(inputList)를 변경합니다. setErrorMessage(''); if (errorIndexList.includes(index)) { @@ -76,13 +87,17 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return setErrorMessage(validationResultMessage ?? ''); changeErrorIndex(targetInput.index); } + }; + // inputList가 변했을 때 canSubmit이 반영되도록 + // setValue가 수행되기 전에 handleCanSubmit이 실행되어 새로운 입력값에 대한 검증이 되지 않는 버그를 해결 + useEffect(() => { handleCanSubmit(); - }; + }, [inputList]); // 현재까지 입력된 값들로 submit을 할 수 있는지 여부를 핸들합니다. const handleCanSubmit = () => { - setCanSubmit(inputList.length > 0 && getFilledInputList().length > 0); + setCanSubmit(inputList.length > 0 && getFilledInputList().length > 0 && errorIndexList.length === 0); }; const deleteEmptyInputElementOnBlur = () => { @@ -128,17 +143,6 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return }); }; - const setInputValueTargetIndex = (index: number, value: string) => { - setInputList(prevInputs => { - const updatedInputList = [...prevInputs]; - const targetInput = findInputByIndex(index, updatedInputList); - - targetInput.value = value; - - return updatedInputList; - }); - }; - const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => { if (e.nativeEvent.isComposing) return; @@ -174,7 +178,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return focusNextInputOnEnter, canSubmit, errorIndexList, - setInputValueTargetIndex, + validateAndSetTargetInput, // TODO: (@weadie) 네이밍 수정 }; }; diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index fb9b547a6..66e65b887 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -15,7 +15,7 @@ export type ReturnUseSearchInMemberList = { }; const useSearchInMemberList = ( - setInputValueTargetIndex: (index: number, value: string) => void, + validateAndSetTargetInput: (index: number, value: string) => void, ): ReturnUseSearchInMemberList => { const eventId = getEventIdByUrl(); @@ -49,7 +49,7 @@ const useSearchInMemberList = ( const chooseMember = (inputIndex: number, name: string) => { setFilteredInMemberList([]); - setInputValueTargetIndex(inputIndex, name); + validateAndSetTargetInput(inputIndex, name); }; const searchCurrentInMember = (event: React.ChangeEvent<HTMLInputElement>) => { From b01cb3a135694528b321f14b2c2cc4086fdd2823 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:12:48 +0900 Subject: [PATCH 155/273] =?UTF-8?q?feat:=20Sentry=20prod=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=97=90=EC=84=9C=EB=A7=8C=20=EB=8F=8C=EC=95=84?= =?UTF-8?q?=EA=B0=80=EB=8F=84=EB=A1=9D=20fetcher=20=EC=84=A4=EC=A0=95=20(#?= =?UTF-8?q?343)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 --- client/src/apis/useFetch.ts | 3 +++ client/src/global.d.ts | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts index b5f94df84..512ef4a96 100644 --- a/client/src/apis/useFetch.ts +++ b/client/src/apis/useFetch.ts @@ -64,6 +64,9 @@ export const useFetch = () => { }; const captureError = async (error: Error, navigate: NavigateFunction, eventId: string) => { + // prod 환경에서만 Sentry capture 실행 + if (process.env.NODE_ENV !== 'production') return; + const errorBody: ServerError = error instanceof FetchError ? error.errorBody : {message: error.message, errorCode: error.name}; diff --git a/client/src/global.d.ts b/client/src/global.d.ts index bff94710c..97ed3c462 100644 --- a/client/src/global.d.ts +++ b/client/src/global.d.ts @@ -1 +1,7 @@ declare module '*.svg'; + +declare namespace NodeJS { + interface ProcessEnv { + readonly NODE_ENV: 'development' | 'production' | 'test'; + } +} From 08c60bd84677d3a6a6e5ff998cd644165c87bc01 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:13:47 +0900 Subject: [PATCH 156/273] =?UTF-8?q?feat:=20=ED=99=98=EA=B2=BD=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=ED=83=80=EC=9E=85=20=EC=84=A0=EC=96=B8=20(#345)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> --- client/src/apis/baseUrl.ts | 2 +- client/src/global.d.ts | 4 ++++ .../pages/CreateEventPage/CompleteCreateEventPage.tsx | 9 +++++---- client/src/pages/EventPage/EventPageLayout.tsx | 6 +++--- client/src/utils/getEventPageUrlByEnvironment.ts | 11 +++++++++++ 5 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 client/src/utils/getEventPageUrlByEnvironment.ts diff --git a/client/src/apis/baseUrl.ts b/client/src/apis/baseUrl.ts index e508ba375..37fc00a94 100644 --- a/client/src/apis/baseUrl.ts +++ b/client/src/apis/baseUrl.ts @@ -1,3 +1,3 @@ export const BASE_URL = { - HD: process.env.API_BASE_URL ?? '', + HD: process.env.API_BASE_URL, }; diff --git a/client/src/global.d.ts b/client/src/global.d.ts index 97ed3c462..dbf6320af 100644 --- a/client/src/global.d.ts +++ b/client/src/global.d.ts @@ -3,5 +3,9 @@ declare module '*.svg'; declare namespace NodeJS { interface ProcessEnv { readonly NODE_ENV: 'development' | 'production' | 'test'; + + // env keys + readonly API_BASE_URL: string; + readonly AMPLITUDE_KEY: string; } } diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 200642f30..d60817f79 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -6,6 +6,8 @@ import {css} from '@emotion/react'; import {useToast} from '@components/Toast/ToastProvider'; +import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; + import {ROUTER_URLS} from '@constants/routerUrls'; const CompleteCreateEventPage = () => { @@ -26,8 +28,7 @@ const CompleteCreateEventPage = () => { const {showToast} = useToast(); - const env = process.env.NODE_ENV || ''; - const homeUrlByEnvironment = `https://${env.includes('development') ? 'dev.' : ''}haengdong.pro${ROUTER_URLS.event}/${url}/home`; + const homePageUrl = getEventPageUrlByEnvironment(url, 'home'); return ( <MainLayout> @@ -41,10 +42,10 @@ const CompleteCreateEventPage = () => { <Text textColor="gray">링크가 없으면 페이지에 접근할 수 없어요.</Text> <Text textColor="primary">관리를 위해서 행사 링크를 복사 후 보관해 주세요.</Text> </Flex> - <Input value={homeUrlByEnvironment} disabled /> + <Input value={homePageUrl} disabled /> <CopyToClipboard - text={homeUrlByEnvironment} + text={homePageUrl} onCopy={() => showToast({ showingTime: 3000, diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 13a6aa67a..771422087 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -10,6 +10,7 @@ import useNavSwitch from '@hooks/useNavSwitch'; import StepListProvider from '@hooks/useStepList'; import getEventIdByUrl from '@utils/getEventIdByUrl'; +import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -44,8 +45,7 @@ const EventPageLayout = () => { }; const {showToast} = useToast(); - - const env = process.env.NODE_ENV || ''; + const url = getEventPageUrlByEnvironment(eventId, 'home'); return ( <StepListProvider> @@ -53,7 +53,7 @@ const EventPageLayout = () => { <TopNav> <Switch value={nav} values={paths} onChange={onChange} /> <CopyToClipboard - text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\nhttps://${env.includes('development') ? 'dev.' : ''}haengdong.pro${ROUTER_URLS.event}/${eventId}/home`} + text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\n${url}`} onCopy={() => showToast({ showingTime: 3000, diff --git a/client/src/utils/getEventPageUrlByEnvironment.ts b/client/src/utils/getEventPageUrlByEnvironment.ts new file mode 100644 index 000000000..bcfce54e9 --- /dev/null +++ b/client/src/utils/getEventPageUrlByEnvironment.ts @@ -0,0 +1,11 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; + +type EventPageTab = 'home' | 'admin'; + +const getEventPageUrlByEnvironment = (eventId: string, tab: EventPageTab) => { + const isDevelopment = process.env.NODE_ENV === 'development'; + + return `https://${isDevelopment ? 'dev.' : ''}haengdong.pro${ROUTER_URLS.event}/${eventId}/${tab}`; +}; + +export default getEventPageUrlByEnvironment; From 364bcd8035a2d673f4f870d7f196b02df02125d1 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:14:08 +0900 Subject: [PATCH 157/273] =?UTF-8?q?feat:=20useDeleteMemberAction=20?= =?UTF-8?q?=ED=86=A0=EC=8A=A4=ED=8A=B8=20=ED=95=A8=EC=88=98=20=EA=B2=B0?= =?UTF-8?q?=ED=95=A9=EB=8F=84=20=EC=A0=9C=EA=B1=B0=20(#347)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 --- .../DeleteMemberActionModal.tsx | 34 ++++++++++++- client/src/hooks/useDeleteMemberAction.tsx | 49 +++++++++---------- 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx index a509b5d54..18b7e13ac 100644 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -2,6 +2,8 @@ import type {MemberAction, MemberType} from 'types/serviceType'; import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; +import {useToast} from '@components/Toast/ToastProvider'; + import useDeleteMemberAction from '@hooks/useDeleteMemberAction'; import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; @@ -19,10 +21,38 @@ const DeleteMemberActionModal = ({ isBottomSheetOpened, setIsBottomSheetOpened, }: DeleteMemberActionModalProps) => { - const {aliveActionList, deleteMemberActionList, addDeleteMemberAction} = useDeleteMemberAction( + const {showToast} = useToast(); + + const showToastAlreadyExistMemberAction = () => { + showToast({ + isClickToClose: true, + showingTime: 3000, + message: '이미 삭제된 인원입니다.', + type: 'error', + bottom: '160px', + }); + }; + + const showToastExistSameMemberFromAfterStep = (name: string) => { + showToast({ + isClickToClose: true, + showingTime: 3000, + message: `이후의 ${name}가 사라져요`, + type: 'error', + position: 'top', + top: '30px', + style: { + zIndex: 9000, + }, + }); + }; + + const {aliveActionList, deleteMemberActionList, addDeleteMemberAction} = useDeleteMemberAction({ memberActionList, setIsBottomSheetOpened, - ); + showToastAlreadyExistMemberAction, + showToastExistSameMemberFromAfterStep, + }); return ( <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> diff --git a/client/src/hooks/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction.tsx index 1883929f2..be16baf02 100644 --- a/client/src/hooks/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction.tsx @@ -2,7 +2,6 @@ import type {MemberAction} from 'types/serviceType'; import {useState} from 'react'; -import {useToast} from '@components/Toast/ToastProvider'; import {requestDeleteMemberAction} from '@apis/request/member'; import {useStepList} from '@hooks/useStepList'; @@ -11,14 +10,22 @@ import {useFetch} from '@apis/useFetch'; import getEventIdByUrl from '@utils/getEventIdByUrl'; -const useDeleteMemberAction = ( - memberActionList: MemberAction[], - setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>, -) => { +type UseDeleteMemberActionProps = { + memberActionList: MemberAction[]; + setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; + showToastAlreadyExistMemberAction: () => void; + showToastExistSameMemberFromAfterStep: (name: string) => void; +}; + +const useDeleteMemberAction = ({ + memberActionList, + setIsBottomSheetOpened, + showToastAlreadyExistMemberAction, + showToastExistSameMemberFromAfterStep, +}: UseDeleteMemberActionProps) => { const {stepList, refreshStepList} = useStepList(); const [aliveActionList, setAliveActionList] = useState<MemberAction[]>(memberActionList); const eventId = getEventIdByUrl(); - const {showToast} = useToast(); const {fetch} = useFetch(); const deleteMemberAction = async (actionId: number) => { @@ -46,36 +53,24 @@ const useDeleteMemberAction = ( } }; - const addDeleteMemberAction = (memberAction: MemberAction) => { + const checkAlreadyExistMemberAction = (memberAction: MemberAction, showToast: () => void) => { if (!memberActionList.includes(memberAction)) { - showToast({ - isClickToClose: true, - showingTime: 3000, - message: '이미 삭제된 인원입니다.', - type: 'error', - bottom: '160px', - }); - return; + showToast(); } + }; + const checkExistSameMemberFromAfterStep = (memberAction: MemberAction, showToast: () => void) => { if (isExistSameMemberFromAfterStep(memberAction)) { - showToast({ - isClickToClose: true, - showingTime: 3000, - message: `이후의 ${memberAction.name}가 사라져요`, - type: 'error', - position: 'top', - top: '30px', - style: { - zIndex: 9000, - }, - }); + showToast(); } + }; + const addDeleteMemberAction = (memberAction: MemberAction) => { + checkAlreadyExistMemberAction(memberAction, showToastAlreadyExistMemberAction); + checkExistSameMemberFromAfterStep(memberAction, () => showToastExistSameMemberFromAfterStep(memberAction.name)); setAliveActionList(prev => prev.filter(aliveMember => aliveMember.actionId !== memberAction.actionId)); }; - // 현재 선택된 액션의 인덱스를 구해서 뒤의 동일인물의 액션이 있는지를 파악하는 기능 const isExistSameMemberFromAfterStep = (memberAction: MemberAction) => { const memberActionList = stepList .filter(step => step.type !== 'BILL') From ae6ce80a71cc75c86a696b2327e58efaee80190d Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:14:42 +0900 Subject: [PATCH 158/273] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=84=B1=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0=20-=20Title=20component=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20=EB=B0=8F=20UX=20writing=20=EC=88=98=EC=A0=95=20(#352)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 --- HDesign/package-lock.json | 4 ++-- HDesign/package.json | 2 +- HDesign/src/components/Text/Text.style.ts | 6 +++++- HDesign/src/components/Title/Title.stories.tsx | 3 ++- HDesign/src/components/Title/Title.tsx | 8 ++++++-- client/package-lock.json | 8 ++++---- client/package.json | 2 +- .../SetInitialMemberListModal.tsx | 2 +- client/src/pages/EventPage/AdminPage/AdminPage.tsx | 7 ++++--- 9 files changed, 26 insertions(+), 16 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 192588f72..084161fd1 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.69", + "version": "0.1.72", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.69", + "version": "0.1.72", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index 4e555b3fc..ad2a06ea3 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.69", + "version": "0.1.72", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/Text/Text.style.ts b/HDesign/src/components/Text/Text.style.ts index 6560c8274..650260e62 100644 --- a/HDesign/src/components/Text/Text.style.ts +++ b/HDesign/src/components/Text/Text.style.ts @@ -21,5 +21,9 @@ export const getSizeStyling = ({size, textColor, theme}: Required<TextStyleProps const colorStyle = css({color: theme.colors[textColor]}); - return [style[size], colorStyle]; + const baseStyle = css({ + whiteSpace: 'pre-line', + }); + + return [style[size], colorStyle, baseStyle]; }; diff --git a/HDesign/src/components/Title/Title.stories.tsx b/HDesign/src/components/Title/Title.stories.tsx index 3973779db..2c91287b4 100644 --- a/HDesign/src/components/Title/Title.stories.tsx +++ b/HDesign/src/components/Title/Title.stories.tsx @@ -25,7 +25,8 @@ const meta = { }, args: { title: '페이지 제목이에요', - description: '이곳에는 페이지 설명이 들어가요. 페이지에 대한 설명을 자세하게 적어주면 좋아요 :)', + description: `이곳에는 페이지 설명이 들어가요. + 페이지에 대한 설명을 자세하게 적어주면 좋아요 :)`, price: 100000, }, } satisfies Meta<typeof Title>; diff --git a/HDesign/src/components/Title/Title.tsx b/HDesign/src/components/Title/Title.tsx index 759588b5e..e17de5e88 100644 --- a/HDesign/src/components/Title/Title.tsx +++ b/HDesign/src/components/Title/Title.tsx @@ -1,4 +1,5 @@ /** @jsxImportSource @emotion/react */ +import Flex from '@components/Flex/Flex'; import Text from '@components/Text/Text'; import {priceContainerStyle, titleContainerStyle} from '@components/Title/Title.style'; import {TitleProps} from '@components/Title/Title.type'; @@ -11,7 +12,7 @@ export const Title: React.FC<TitleProps> = ({title, description, price}: TitlePr <div css={titleContainerStyle(theme)}> <Text size="subTitle">{title}</Text> {description && ( - <Text textColor="darkGray" size="caption"> + <Text textColor="darkGray" size="body"> {description} </Text> )} @@ -20,7 +21,10 @@ export const Title: React.FC<TitleProps> = ({title, description, price}: TitlePr <Text textColor="gray" size="caption"> 전체 지출 금액 </Text> - <Text>{price.toLocaleString('ko-kr')}원</Text> + <Flex alignItems="center" gap="0.25rem"> + <Text>{price.toLocaleString('ko-kr')}</Text> + <Text size="caption">원</Text> + </Flex> </div> )} </div> diff --git a/client/package-lock.json b/client/package-lock.json index f3731b138..0a884603e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", - "haengdong-design": "^0.1.69", + "haengdong-design": "^0.1.72", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -8123,9 +8123,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.69", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.69.tgz", - "integrity": "sha512-XlZ7hnKn51aQOOz/x+hNM6tLjJDvvTOqLiVfOSjEvRpkMKquNWFoijclXHLNhK7tqrb6m+hDREf12mIXwSN/Ew==", + "version": "0.1.72", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.72.tgz", + "integrity": "sha512-7Qtk/HygT5IhLzUTQzcx7FbgZo/ZrqVZhKA08zJaf1wcOlc3CkXO3Ljl1wQloHGejg71K1N1BO3L208tppxycQ==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index c73dae15d..b0d9e7ff0 100644 --- a/client/package.json +++ b/client/package.json @@ -54,7 +54,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", - "haengdong-design": "^0.1.69", + "haengdong-design": "^0.1.72", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index ac9375d52..623d9f98f 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -37,7 +37,7 @@ const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: Se return ( <BottomSheet isOpened={isOpenBottomSheet} onClose={() => setIsOpenBottomSheet(false)}> <div css={setInitialMemberListModalStyle}> - <Text size="bodyBold">초기 인원 설정하기</Text> + <Text size="bodyBold">시작 인원 추가하기</Text> <div css={setInitialMemberListModalInputGroupStyle}> <LabelGroupInput labelText="이름" errorText={errorMessage}> {inputList.map(({value, index}) => ( diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index a1ea053d9..ac0d85c05 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -36,8 +36,9 @@ const AdminPage = () => { const getTitleDescriptionByInitialMemberSetting = () => { return allMemberList.length > 0 - ? '“행동 추가하기” 버튼을 눌러서 지출 내역 및 인원 변동사항을 추가해 주세요.' - : '“초기인원 설정하기” 버튼을 눌러서 행사 초기 인원을 설정해 주세요.'; + ? `지출 내역 및 인원 변동을 추가해 주세요. + 인원 변동을 기준으로 몇 차인지 나뉘어져요.` + : '“시작 인원 추가” 버튼을 눌러 행사의 시작부터 참여하는 사람들의 이름을 입력해 주세요.'; }; return ( @@ -55,7 +56,7 @@ const AdminPage = () => { <section css={receiptStyle}> <StepList /> <FixedButton - children={allMemberList.length === 0 ? '초기인원 설정하기' : '행동 추가하기'} + children={allMemberList.length === 0 ? '시작인원 추가하기' : '행동 추가하기'} onClick={() => setIsOpenFixedBottomBottomSheet(prev => !prev)} /> {isOpenFixedButtonBottomSheet && ( From 843d6795d6ded6f997b09b4827fb556f421e4fc9 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:14:58 +0900 Subject: [PATCH 159/273] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=9B=85=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 --- client/src/hooks/useSetPassword.ts | 49 +++++++++++++++++++ .../CreateEventPage/SetEventPasswordPage.tsx | 42 ++++------------ client/src/pages/CreateEventPage/index.ts | 1 + client/src/router.tsx | 3 +- 4 files changed, 61 insertions(+), 34 deletions(-) create mode 100644 client/src/hooks/useSetPassword.ts diff --git a/client/src/hooks/useSetPassword.ts b/client/src/hooks/useSetPassword.ts new file mode 100644 index 000000000..0ba5e7272 --- /dev/null +++ b/client/src/hooks/useSetPassword.ts @@ -0,0 +1,49 @@ +import {useState} from 'react'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import {useFetch} from '@apis/useFetch'; + +import RULE from '@constants/rule'; + +import useEvent from './useEvent'; + +const useSetPassword = (eventName: string) => { + const {fetch} = useFetch(); + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const {createNewEvent} = useEvent(); + + const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + const {eventId} = await fetch({queryFunction: () => createNewEvent({eventName, password: parseInt(password)})}); + return eventId; + }; + + const handlePasswordChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + const {isValid, errorMessage} = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(errorMessage ?? ''); + } + }; + + return { + password, + errorMessage, + canSubmit, + submitPassword, + handlePasswordChange, + }; +}; + +export default useSetPassword; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 04c8dd760..a3572d24d 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -2,60 +2,38 @@ import {useEffect, useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; -import validateEventPassword from '@utils/validate/validateEventPassword'; -import {requestPostNewEvent} from '@apis/request/event'; - -import useEvent from '@hooks/useEvent'; +import useSetPassword from '@hooks/useSetPassword'; import RULE from '@constants/rule'; import {ROUTER_URLS} from '@constants/routerUrls'; const SetEventPasswordPage = () => { - const [eventName, setEventName] = useState(''); - const [password, setPassword] = useState(''); - const [errorMessage, setErrorMessage] = useState(''); - const [canSubmit, setCanSubmit] = useState(false); - const {createNewEvent} = useEvent(); const navigate = useNavigate(); const location = useLocation(); useEffect(() => { if (!location.state) { navigate(ROUTER_URLS.main); - } else { - setEventName(location.state.eventName); } - }, []); + }, [location.state]); - const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); + const {password, errorMessage, canSubmit, submitPassword, handlePasswordChange} = useSetPassword( + location.state?.eventName, + ); - const {eventId} = await createNewEvent({eventName, password: parseInt(password)}); + const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => { + const eventId = await submitPassword(event); navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`); }; - const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { - const newValue = event.target.value; - const validation = validateEventPassword(newValue); - - setCanSubmit(newValue.length === RULE.maxEventPasswordLength); - - if (validation.isValid) { - setPassword(newValue); - setErrorMessage(''); - } else { - event.target.value = password; - setErrorMessage(validation.errorMessage ?? ''); - } - }; return ( <MainLayout> <TopNav> <Back /> </TopNav> <Title title="행사 비밀번호 설정" description="행사 관리에 필요한 4 자리의 숫자 비밀번호를 입력해 주세요." /> - <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <form onSubmit={onSubmit} style={{padding: '0 1rem'}}> <LabelInput labelText="비밀번호" errorText={errorMessage} @@ -63,10 +41,10 @@ const SetEventPasswordPage = () => { type="secret" maxLength={RULE.maxEventPasswordLength} placeholder="비밀번호" - onChange={e => handleChange(e)} + onChange={handlePasswordChange} isError={!!errorMessage} autoFocus - ></LabelInput> + /> <FixedButton disabled={!canSubmit}>행동 개시!</FixedButton> </form> </MainLayout> diff --git a/client/src/pages/CreateEventPage/index.ts b/client/src/pages/CreateEventPage/index.ts index 9b66c3ba5..6d3d6c808 100644 --- a/client/src/pages/CreateEventPage/index.ts +++ b/client/src/pages/CreateEventPage/index.ts @@ -1,2 +1,3 @@ export {default as SetEventNamePage} from './SetEventNamePage'; +export {default as SetEventPasswordPage} from './SetEventPasswordPage'; export {default as CompleteCreateEventPage} from './CompleteCreateEventPage'; diff --git a/client/src/router.tsx b/client/src/router.tsx index 52d6da760..a6af2184d 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -3,10 +3,9 @@ import {createBrowserRouter} from 'react-router-dom'; import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; -import SetEventPasswordPage from '@pages/CreateEventPage/SetEventPasswordPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; -import {CompleteCreateEventPage, SetEventNamePage} from '@pages/CreateEventPage'; +import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; import {MainPage} from '@pages/MainPage'; import {EventPage} from '@pages/EventPage'; From 26eb877bbcad0f6d3e38530768fd555630742044 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:15:11 +0900 Subject: [PATCH 160/273] =?UTF-8?q?fix:=20=ED=83=AD=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=20=EC=8B=9C=20=EC=A0=84=EC=B2=B4=EA=B0=80=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EA=B2=83=EC=B2=98=EB=9F=BC=20=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EB=8A=94=20=ED=98=84=EC=83=81=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?(#356)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HDesign/src/components/Tabs/Tabs.style.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HDesign/src/components/Tabs/Tabs.style.ts b/HDesign/src/components/Tabs/Tabs.style.ts index 99a514547..3ea38924c 100644 --- a/HDesign/src/components/Tabs/Tabs.style.ts +++ b/HDesign/src/components/Tabs/Tabs.style.ts @@ -10,6 +10,8 @@ export const tabListStyle = (theme: Theme) => cursor: 'pointer', + WebkitTapHighlightColor: 'transparent', + '&::after': { position: 'absolute', left: 0, From c1c0916d0cf7fd4d36b0e49c15042e0a6c41b0da Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:16:19 +0900 Subject: [PATCH 161/273] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=84=B1=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0=20-=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=9E=85=EB=A0=A5=20=EC=95=84=EC=9D=B4=ED=85=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#357)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> --- HDesign/package-lock.json | 5 +- HDesign/package.json | 2 +- .../EditableItem/EditableItem.Input.style.ts | 75 +++++++++++++++++++ .../EditableItem/EditableItem.Input.tsx | 27 +++++++ .../EditableItem/EditableItem.Input.type.ts | 18 +++++ .../EditableItem/EditableItem.context.tsx | 23 ++++++ .../EditableItem.input.stories.tsx | 44 +++++++++++ .../EditableItem/EditableItem.stories.tsx | 44 +++++++++++ .../EditableItem/EditableItem.style.ts | 14 ++++ .../components/EditableItem/EditableItem.tsx | 40 ++++++++++ .../EditableItem/EditableItem.type.ts | 20 +++++ .../EditableItem/useEditableItem.ts | 23 ++++++ .../EditableItem/useEditableItemInput.ts | 46 ++++++++++++ HDesign/src/index.tsx | 2 + 14 files changed, 380 insertions(+), 3 deletions(-) create mode 100644 HDesign/src/components/EditableItem/EditableItem.Input.style.ts create mode 100644 HDesign/src/components/EditableItem/EditableItem.Input.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.Input.type.ts create mode 100644 HDesign/src/components/EditableItem/EditableItem.context.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.input.stories.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.stories.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.style.ts create mode 100644 HDesign/src/components/EditableItem/EditableItem.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.type.ts create mode 100644 HDesign/src/components/EditableItem/useEditableItem.ts create mode 100644 HDesign/src/components/EditableItem/useEditableItemInput.ts diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 084161fd1..274804d74 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,13 @@ { "name": "haengdong-design", - "version": "0.1.72", + "version": "0.1.74", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.72", + "version": "0.1.74", + "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index ad2a06ea3..e01107490 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.72", + "version": "0.1.74", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts new file mode 100644 index 000000000..fc346d77b --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts @@ -0,0 +1,75 @@ +import {css} from '@emotion/react'; + +import {TextSize} from '@components/Text/Text.type'; + +import {Theme} from '@theme/theme.type'; + +import TYPOGRAPHY from '@token/typography'; + +interface InputWrapperStyleProps { + theme: Theme; + hasFocus: boolean; + hasError: boolean; +} + +interface InputStyleProps { + theme: Theme; + textSize: TextSize; +} + +interface InputSizeStyleProps { + textSize: TextSize; +} + +interface InputBaseStyleProps { + theme: Theme; +} + +export const inputWrapperStyle = ({theme, hasFocus, hasError}: InputWrapperStyleProps) => + css({ + position: 'relative', + display: 'inline-block', + + '&::after': { + content: '""', + position: 'absolute', + left: 0, + right: 0, + bottom: 0, + height: '0.125rem', + backgroundColor: hasFocus ? theme.colors.primary : hasError ? theme.colors.error : 'transparent', + transition: 'background-color 0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }, + }); + +export const inputStyle = ({theme, textSize}: InputStyleProps) => [inputSizeStyle({textSize}), inputBaseStyle({theme})]; + +const inputSizeStyle = ({textSize}: InputSizeStyleProps) => { + const style = { + head: css(TYPOGRAPHY.head), + title: css(TYPOGRAPHY.title), + subTitle: css(TYPOGRAPHY.subTitle), + bodyBold: css(TYPOGRAPHY.bodyBold), + body: css(TYPOGRAPHY.body), + smallBodyBold: css(TYPOGRAPHY.smallBodyBold), + smallBody: css(TYPOGRAPHY.smallBody), + captionBold: css(TYPOGRAPHY.captionBold), + caption: css(TYPOGRAPHY.caption), + tiny: css(TYPOGRAPHY.tiny), + }; + + return [style[textSize]]; +}; + +const inputBaseStyle = ({theme}: InputBaseStyleProps) => + css({ + border: 'none', + outline: 'none', + paddingBottom: '0.125rem', + + color: theme.colors.black, + '&:placeholder': { + color: theme.colors.gray, + }, + }); diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/HDesign/src/components/EditableItem/EditableItem.Input.tsx new file mode 100644 index 000000000..b6af0c144 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.tsx @@ -0,0 +1,27 @@ +/** @jsxImportSource @emotion/react */ +import React, {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; + +import {InputProps} from '@components/EditableItem/EditableItem.Input.type'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {inputStyle, inputWrapperStyle} from './EditableItem.Input.style'; +import useEditableItemInput from './useEditableItemInput'; + +export const EditableItemInput: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( + {textSize = 'body', hasError = false, ...htmlProps}, + ref, +) { + const {theme} = useTheme(); + const inputRef = useRef<HTMLInputElement>(null); + const {hasFocus} = useEditableItemInput({inputRef}); + useImperativeHandle(ref, () => inputRef.current!); + + return ( + <div css={inputWrapperStyle({theme, hasFocus, hasError})}> + <input css={inputStyle({theme, textSize})} ref={inputRef} {...htmlProps} /> + </div> + ); +}); + +export default EditableItemInput; diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.type.ts b/HDesign/src/components/EditableItem/EditableItem.Input.type.ts new file mode 100644 index 000000000..5d58238e8 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.type.ts @@ -0,0 +1,18 @@ +import {TextSize} from '@components/Text/Text.type'; + +import {Theme} from '@theme/theme.type'; + +export interface InputStyleProps { + hasError?: boolean; + textSize?: TextSize; +} + +export interface InputCustomProps {} + +export interface InputStylePropsWithTheme extends InputStyleProps { + theme: Theme; +} + +export type InputOptionProps = InputStyleProps & InputCustomProps; + +export type InputProps = React.ComponentProps<'input'> & InputOptionProps; diff --git a/HDesign/src/components/EditableItem/EditableItem.context.tsx b/HDesign/src/components/EditableItem/EditableItem.context.tsx new file mode 100644 index 000000000..a2aeef4bc --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.context.tsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, PropsWithChildren, useContext, useState} from 'react'; + +interface EditableItemContextProps { + hasAnyFocus: boolean; + setHasAnyFocus: React.Dispatch<React.SetStateAction<boolean>>; +} + +const EditableItemContext = createContext<EditableItemContextProps | null>(null); + +export const useEditableItemContext = () => { + const context = useContext(EditableItemContext); + if (!context) { + throw new Error('useEditableItemContext must be used within an EditableItemProvider'); + } + return context; +}; + +export const EditableItemProvider: React.FC<PropsWithChildren> = ({children}: React.PropsWithChildren) => { + const [hasAnyFocus, setHasAnyFocus] = useState(false); + + return <EditableItemContext.Provider value={{hasAnyFocus, setHasAnyFocus}}>{children}</EditableItemContext.Provider>; +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx new file mode 100644 index 000000000..a23483b78 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx @@ -0,0 +1,44 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import EditableItemInput from '@components/EditableItem/EditableItem.Input'; + +import EditableItem from './EditableItem'; +import {EditableItemProvider} from './EditableItem.context'; + +const meta = { + title: 'Components/EditableItemInput', + component: EditableItemInput, + tags: ['autodocs'], + parameters: {}, + argTypes: { + textSize: { + description: '', + control: {type: 'select'}, + }, + hasError: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + placeholder: '지출 내역', + textSize: 'body', + hasError: false, + autoFocus: true, + }, +} satisfies Meta<typeof EditableItemInput>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + return ( + <EditableItemProvider> + <EditableItem.Input {...args} /> + </EditableItemProvider> + ); + }, +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.stories.tsx new file mode 100644 index 000000000..976a4aa90 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.stories.tsx @@ -0,0 +1,44 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import EditableItem from '@components/EditableItem/EditableItem'; +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; + +const meta = { + title: 'Components/EditableItem', + component: EditableItem, + tags: ['autodocs'], + parameters: {}, + argTypes: { + backgroundColor: { + description: '', + control: {type: 'select'}, + }, + }, + args: { + backgroundColor: 'lightGrayContainer', + }, +} satisfies Meta<typeof EditableItem>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + return ( + <EditableItem + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input placeholder="지출 내역" textSize="bodyBold"></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input placeholder="0" type="number" style={{textAlign: 'right'}}></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.style.ts b/HDesign/src/components/EditableItem/EditableItem.style.ts new file mode 100644 index 000000000..c817e5f7d --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.style.ts @@ -0,0 +1,14 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export const editableItemStyle = (theme: Theme, backgroundColor: ColorKeys) => + css({ + display: 'flex', + justifyContent: 'space-between', + padding: '0.5rem', + borderRadius: '0.5rem', + backgroundColor: theme.colors[backgroundColor], + }); diff --git a/HDesign/src/components/EditableItem/EditableItem.tsx b/HDesign/src/components/EditableItem/EditableItem.tsx new file mode 100644 index 000000000..cc1892370 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.tsx @@ -0,0 +1,40 @@ +/** @jsxImportSource @emotion/react */ +import React, {useEffect} from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {editableItemStyle} from './EditableItem.style'; +import EditableItemInput from './EditableItem.Input'; +import {EditableItemProps} from './EditableItem.type'; +import {EditableItemProvider} from './EditableItem.context'; +import useEditableItem from './useEditableItem'; + +const EditableItemBase = ({ + onInputFocus, + onInputBlur, + backgroundColor = 'white', + children, + ...htmlProps +}: EditableItemProps) => { + const {theme} = useTheme(); + + useEditableItem({onInputFocus, onInputBlur}); + + return ( + <div css={editableItemStyle(theme, backgroundColor)} {...htmlProps}> + {children} + </div> + ); +}; + +export const EditableItem = (props: EditableItemProps) => { + return ( + <EditableItemProvider> + <EditableItemBase {...props} /> + </EditableItemProvider> + ); +}; + +EditableItem.Input = EditableItemInput; + +export default EditableItem; diff --git a/HDesign/src/components/EditableItem/EditableItem.type.ts b/HDesign/src/components/EditableItem/EditableItem.type.ts new file mode 100644 index 000000000..b19a76427 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.type.ts @@ -0,0 +1,20 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export interface EditableItemStyleProps { + backgroundColor: ColorKeys; +} + +export interface EditableItemCustomProps { + onInputFocus?: () => void; + onInputBlur?: () => void; +} + +export interface EditableItemStylePropsWithTheme extends EditableItemStyleProps { + theme: Theme; +} + +export type EditableItemOptionProps = EditableItemStyleProps & EditableItemCustomProps; + +export type EditableItemProps = React.ComponentProps<'div'> & EditableItemOptionProps; diff --git a/HDesign/src/components/EditableItem/useEditableItem.ts b/HDesign/src/components/EditableItem/useEditableItem.ts new file mode 100644 index 000000000..86880deb6 --- /dev/null +++ b/HDesign/src/components/EditableItem/useEditableItem.ts @@ -0,0 +1,23 @@ +import {useEffect} from 'react'; + +import {useEditableItemContext} from './EditableItem.context'; + +interface UseEditableItemProps { + onInputFocus?: () => void; + onInputBlur?: () => void; +} + +const useEditableItem = ({onInputFocus, onInputBlur}: UseEditableItemProps) => { + const {hasAnyFocus} = useEditableItemContext(); + + useEffect(() => { + if (hasAnyFocus && onInputFocus) { + onInputFocus(); + } + if (!hasAnyFocus && onInputBlur) { + onInputBlur(); + } + }, [hasAnyFocus, onInputFocus, onInputBlur]); +}; + +export default useEditableItem; diff --git a/HDesign/src/components/EditableItem/useEditableItemInput.ts b/HDesign/src/components/EditableItem/useEditableItemInput.ts new file mode 100644 index 000000000..3253ad0ea --- /dev/null +++ b/HDesign/src/components/EditableItem/useEditableItemInput.ts @@ -0,0 +1,46 @@ +import {useCallback, useEffect, useState} from 'react'; + +import {useEditableItemContext} from './EditableItem.context'; + +interface UseEditableItemInputProps { + inputRef: React.RefObject<HTMLInputElement>; +} + +const useEditableItemInput = ({inputRef}: UseEditableItemInputProps) => { + const [hasFocus, setHasFocus] = useState(false); + const {setHasAnyFocus} = useEditableItemContext(); + + const handleFocus = useCallback(() => { + setHasFocus(true); + setHasAnyFocus(true); + }, [setHasAnyFocus]); + + const handleBlur = useCallback(() => { + setHasFocus(false); + setHasAnyFocus(false); + }, [setHasAnyFocus]); + + useEffect(() => { + const input = inputRef.current; + + if (input) { + input.addEventListener('focus', handleFocus); + input.addEventListener('blur', handleBlur); + + return () => { + input.removeEventListener('focus', handleFocus); + input.removeEventListener('blur', handleBlur); + }; + } + }, [handleFocus, handleBlur, inputRef]); + + useEffect(() => { + if (document.activeElement === inputRef.current) { + handleFocus(); + } + }, [handleFocus, inputRef]); + + return {hasFocus}; +}; + +export default useEditableItemInput; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx index e6498965e..656690951 100644 --- a/HDesign/src/index.tsx +++ b/HDesign/src/index.tsx @@ -2,6 +2,7 @@ import BottomSheet from '@components/BottomSheet/BottomSheet'; import Button from '@components/Button/Button'; import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; +import EditableItem from '@components/EditableItem/EditableItem'; import ExpenseList from '@components/ExpenseList/ExpenseList'; import FixedButton from '@components/FixedButton/FixedButton'; import Flex from '@components/Flex/Flex'; @@ -33,6 +34,7 @@ export { Button, DragHandleItem, DragHandleItemContainer, + EditableItem, ExpenseList, FixedButton, Flex, From 9634f1539d5ef3a0a0259d41bd8220a395c63bd5 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:18:55 +0900 Subject: [PATCH 162/273] =?UTF-8?q?refactor:=20=ED=96=89=EC=82=AC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EC=99=84=EB=A3=8C=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=EC=84=9C=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=83=81=ED=83=9C=20=EC=A0=9C=EA=B1=B0=20(#350)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 --- .../CreateEventPage/CompleteCreateEventPage.tsx | 16 +++------------- .../pages/CreateEventPage/SetEventNamePage.tsx | 3 --- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index d60817f79..d9c4f6bce 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -1,4 +1,3 @@ -import {useEffect, useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; import {Button, FixedButton, Flex, Input, MainLayout, Text, Title, TopNav} from 'haengdong-design'; import {CopyToClipboard} from 'react-copy-to-clipboard'; @@ -13,18 +12,9 @@ import {ROUTER_URLS} from '@constants/routerUrls'; const CompleteCreateEventPage = () => { const navigate = useNavigate(); const location = useLocation(); - const [url, setUrl] = useState(''); - useEffect(() => { - const getUrl = async () => { - // TODO: (@weadie) eventId를 location에서 불러오는 로직 함수로 분리해서 재사용 - const params = new URLSearchParams(location.search); - const eventId = params.get('eventId'); - // TODO: (@weadie) eventId가 없는 경우에 대한 처리 필요 - setUrl(eventId ?? ''); - }; - getUrl(); - }, []); + const params = new URLSearchParams(location.search); + const eventId = params.get('eventId'); const {showToast} = useToast(); @@ -62,7 +52,7 @@ const CompleteCreateEventPage = () => { </CopyToClipboard> </div> - <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${url}/admin`)}>관리 페이지로 이동</FixedButton> + <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>관리 페이지로 이동</FixedButton> </MainLayout> ); }; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index ef0417d8a..68f57a242 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -4,8 +4,6 @@ import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdon import validateEventName from '@utils/validate/validateEventName'; -import useEvent from '@hooks/useEvent'; - import {ROUTER_URLS} from '@constants/routerUrls'; const SetEventNamePage = () => { @@ -13,7 +11,6 @@ const SetEventNamePage = () => { const [errorMessage, setErrorMessage] = useState(''); const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); - const {createNewEvent} = useEvent(); const submitEventName = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); From 249fc3f9fc032bc17666047d13f15bf9169775a4 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:32:46 +0900 Subject: [PATCH 163/273] =?UTF-8?q?fix:=20=EC=9D=B8=EC=9B=90=20=ED=83=88?= =?UTF-8?q?=EC=A3=BC=20=EC=8B=9C=20=EA=B2=80=EC=83=89=EC=9D=B4=20=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=20(#368)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/request/member.ts | 2 +- client/src/hooks/useSearchInMemberList.ts | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 48329e78f..141061bc1 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -73,7 +73,7 @@ export const requestDeleteAllMemberList = async ({eventId, memberName}: WithEven }; export type ResponseGetCurrentInMemberList = { - members: Array<{name: string}>; + memberNames: string[]; }; export const requestGetCurrentInMemberList = async (eventId: string) => { diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index 66e65b887..04514d689 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -23,7 +23,7 @@ const useSearchInMemberList = ( const [currentInputIndex, setCurrentInputIndex] = useState(-1); // 서버에서 가져온 전체 리스트 - const [currentInMemberList, setCurrentInMemberList] = useState<Array<{name: string}>>([]); + const [currentInMemberList, setCurrentInMemberList] = useState<Array<string>>([]); // 검색된 리스트 (따로 둔 이유는 검색 후 클릭했을 때 리스트를 비워주어야하기 때문) const [filteredInMemberList, setFilteredInMemberList] = useState<Array<string>>([]); @@ -31,7 +31,7 @@ const useSearchInMemberList = ( useEffect(() => { const getCurrentInMembers = async () => { const currentInMemberListFromServer = await fetch({queryFunction: () => requestGetCurrentInMemberList(eventId)}); - setCurrentInMemberList(currentInMemberListFromServer.members); + setCurrentInMemberList(currentInMemberListFromServer.memberNames); }; getCurrentInMembers(); @@ -40,11 +40,9 @@ const useSearchInMemberList = ( const filterMatchItems = (keyword: string) => { if (keyword.trim() === '') return []; - const MatchItems = currentInMemberList.map(({name}) => name); - - return MatchItems.filter( - matchItem => matchItem.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1, - ).slice(0, 3); + return currentInMemberList + .filter(member => member.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1) + .slice(0, 3); }; const chooseMember = (inputIndex: number, name: string) => { From ee322f6986cca2a39347c672533a01088cc52f9f Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:50:02 +0900 Subject: [PATCH 164/273] =?UTF-8?q?fix:=20=EB=A8=B8=EC=A7=80=ED=95=98?= =?UTF-8?q?=EB=A9=B4=EC=84=9C=20=EC=8B=A0=EA=B2=BD=EC=93=B0=EC=A7=80=20?= =?UTF-8?q?=EB=AA=BB=ED=95=9C=20=EC=BD=94=EB=93=9C=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20(#381)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index d9c4f6bce..d33f5b6e7 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -18,7 +18,7 @@ const CompleteCreateEventPage = () => { const {showToast} = useToast(); - const homePageUrl = getEventPageUrlByEnvironment(url, 'home'); + const homePageUrl = getEventPageUrlByEnvironment(eventId ?? '', 'home'); return ( <MainLayout> From 7d54702f4fd11a455323b47dd6b93b18a8fb0338 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:56:51 +0900 Subject: [PATCH 165/273] =?UTF-8?q?feat:=20Input=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20(#376)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 --- .../LabelGroupInput/LabelGroupInput.type.ts | 2 +- HDesign/src/components/LabelInput/LabelInput.tsx | 8 +++++--- HDesign/src/components/LabelInput/LabelInput.type.ts | 2 +- client/src/ErrorProvider.tsx | 2 +- .../AddBillActionListModalContent.tsx | 4 +++- client/src/components/Toast/ToastProvider.tsx | 2 +- client/src/constants/errorMessage.ts | 4 +--- client/src/hooks/useDynamicBillActionInput.tsx | 9 ++++----- client/src/hooks/useDynamicInput.tsx | 11 ++++------- client/src/hooks/usePutAndDeleteBillAction.ts | 8 ++++---- client/src/hooks/useSetPassword.ts | 5 ++--- client/src/utils/validate/type.ts | 2 +- client/src/utils/validate/validateEventName.ts | 4 ++-- client/src/utils/validate/validateEventPassword.ts | 4 ++-- client/src/utils/validate/validateMemberName.ts | 2 +- client/src/utils/validate/validatePurchase.ts | 6 +++--- 16 files changed, 36 insertions(+), 39 deletions(-) diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts b/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts index cfa938457..8507311b5 100644 --- a/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts @@ -2,7 +2,7 @@ export interface LabelGroupInputStyleProps {} export interface LabelGroupInputCustomProps { labelText: string; - errorText?: string; + errorText: string | null; } export type LabelGroupInputOptionProps = LabelGroupInputStyleProps & LabelGroupInputCustomProps; diff --git a/HDesign/src/components/LabelInput/LabelInput.tsx b/HDesign/src/components/LabelInput/LabelInput.tsx index f9dd3b71a..43f60c220 100644 --- a/HDesign/src/components/LabelInput/LabelInput.tsx +++ b/HDesign/src/components/LabelInput/LabelInput.tsx @@ -29,9 +29,11 @@ const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, Label <Text size="caption" css={labelTextStyle(theme, hasFocus, !!htmlProps.value)}> {labelText} </Text> - <Text size="caption" css={errorTextStyle(theme, isError ?? false)}> - {errorText} - </Text> + {errorText && ( + <Text size="caption" css={errorTextStyle(theme, isError ?? false)}> + {errorText} + </Text> + )} </Flex> <Flex flexDirection="column" gap="0.5rem"> <Input ref={inputRef} isError={isError} placeholder={labelText} {...htmlProps} /> diff --git a/HDesign/src/components/LabelInput/LabelInput.type.ts b/HDesign/src/components/LabelInput/LabelInput.type.ts index ec24b3a30..83e7e9751 100644 --- a/HDesign/src/components/LabelInput/LabelInput.type.ts +++ b/HDesign/src/components/LabelInput/LabelInput.type.ts @@ -2,7 +2,7 @@ export interface LabelInputStyleProps {} export interface LabelInputCustomProps { labelText: string; - errorText?: string; + errorText: string | null; isError?: boolean; autoFocus: boolean; } diff --git a/client/src/ErrorProvider.tsx b/client/src/ErrorProvider.tsx index ef0714c7f..92b93fb60 100644 --- a/client/src/ErrorProvider.tsx +++ b/client/src/ErrorProvider.tsx @@ -1,6 +1,6 @@ import {createContext, useState, useContext, useEffect, ReactNode} from 'react'; -import SERVER_ERROR_MESSAGES from '@constants/errorMessage'; +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; // 에러 컨텍스트 생성 interface ErrorContextType { diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index 239bc0d2d..cc49d5953 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -1,4 +1,5 @@ import {FixedButton, LabelGroupInput} from 'haengdong-design'; +import {useEffect} from 'react'; import validatePurchase from '@utils/validate/validatePurchase'; @@ -15,6 +16,7 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList const { inputPairList, inputRefList, + errorMessage, errorIndexList, handleInputChange, getFilledInputPairList, @@ -34,7 +36,7 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList return ( <div css={style.container}> <div css={style.inputContainer}> - <LabelGroupInput labelText="지출내역 / 금액"> + <LabelGroupInput labelText="지출내역 / 금액" errorText={errorMessage}> {inputPairList.map(({index, title, price}) => ( <div key={index} css={style.input}> <LabelGroupInput.Element diff --git a/client/src/components/Toast/ToastProvider.tsx b/client/src/components/Toast/ToastProvider.tsx index 3107e37ac..d842a3a08 100644 --- a/client/src/components/Toast/ToastProvider.tsx +++ b/client/src/components/Toast/ToastProvider.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import {createContext, useContext, useEffect, useState} from 'react'; -import SERVER_ERROR_MESSAGES from '@constants/errorMessage'; +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; import {useError} from '../../ErrorProvider'; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index e238cf90e..f874f6ff4 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -1,6 +1,6 @@ type ErrorMessage = Record<string, string>; -const SERVER_ERROR_MESSAGES: ErrorMessage = { +export const SERVER_ERROR_MESSAGES: ErrorMessage = { EVENT_NOT_FOUND: '존재하지 않는 행사입니다.', EVENT_NAME_LENGTH_INVALID: '행사 이름은 2자 이상 30자 이하만 입력 가능합니다.', EVENT_NAME_CONSECUTIVE_SPACES: '행사 이름에는 공백 문자가 연속될 수 없습니다.', @@ -45,5 +45,3 @@ export const ERROR_MESSAGE = { }; export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; - -export default SERVER_ERROR_MESSAGES; diff --git a/client/src/hooks/useDynamicBillActionInput.tsx b/client/src/hooks/useDynamicBillActionInput.tsx index 252b40862..f21311de8 100644 --- a/client/src/hooks/useDynamicBillActionInput.tsx +++ b/client/src/hooks/useDynamicBillActionInput.tsx @@ -14,7 +14,7 @@ export type BillInputType = 'title' | 'price'; const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateResult) => { const [inputPairList, setInputPairList] = useState<InputPair[]>([{title: '', price: '', index: 0}]); const inputRefList = useRef<(HTMLInputElement | null)[]>([]); - const [errorMessage, setErrorMessage] = useState(''); + const [errorMessage, setErrorMessage] = useState<string | null>(null); const [errorIndexList, setErrorIndexList] = useState<number[]>([]); const [canSubmit, setCanSubmit] = useState(false); @@ -34,13 +34,14 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe [field]: value, }); + setErrorMessage(validationResultMessage); + // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수로 분리 if ( isLastInputPairFilled({index, field, value}) && targetInputPair.title.trim().length !== 0 && targetInputPair.price.trim().length !== 0 ) { - setErrorMessage(''); setInputPairList(prevInputPairList => { const updatedInputPairList = [...prevInputPairList]; @@ -52,19 +53,17 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe }); } else if (isValidInput) { // 입력된 값이 유효하면 데이터(inputLis)를 변경합니다. - setErrorMessage(''); if (errorIndexList.includes(index)) { setErrorIndexList(prev => prev.filter(i => i !== index)); } changeInputListValue(index, value, field); } else if (value.length === 0) { - setErrorMessage(''); + setErrorMessage(null); changeErrorIndex(index); changeInputListValue(index, value, field); } else { - setErrorMessage(validationResultMessage ?? ''); changeErrorIndex(targetInputPair.index); } diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index 3584d3a05..77e25098c 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -12,7 +12,7 @@ export type ReturnUseDynamicInput = { inputRefList: React.MutableRefObject<(HTMLInputElement | null)[]>; handleInputChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; deleteEmptyInputElementOnBlur: () => void; - errorMessage: string; + errorMessage: string | null; getFilledInputList: (list?: InputValue[]) => InputValue[]; focusNextInputOnEnter: (e: React.KeyboardEvent<HTMLInputElement>, index: number) => void; canSubmit: boolean; @@ -23,7 +23,7 @@ export type ReturnUseDynamicInput = { const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { const [inputList, setInputList] = useState<InputValue[]>([{index: 0, value: ''}]); const inputRefList = useRef<(HTMLInputElement | null)[]>([]); - const [errorMessage, setErrorMessage] = useState(''); + const [errorMessage, setErrorMessage] = useState<string | null>(null); const [errorIndexList, setErrorIndexList] = useState<number[]>([]); const [canSubmit, setCanSubmit] = useState(false); @@ -62,11 +62,10 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return // onChange와 setValue 둘 다 지원하기 위해서 validate를 분리 const validateAndSetTargetInput = (index: number, value: string) => { const {isValid: isValidInput, errorMessage: validationResultMessage} = validateFunc(value); + setErrorMessage(validationResultMessage); if (isValidInput) { // 입력된 값이 유효하면 데이터(inputList)를 변경합니다. - setErrorMessage(''); - if (errorIndexList.includes(index)) { setErrorIndexList(prev => prev.filter(i => i !== index)); } @@ -75,7 +74,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return } else if (value.length === 0) { // value의 값이 0이라면 errorMessage는 띄워지지 않지만 값은 변경됩니다. 또한 invalid한 값이기에 errorIndex에 추가합니다. - setErrorMessage(''); + setErrorMessage(null); changeErrorIndex(index); changeInputListValue(index, value); @@ -83,8 +82,6 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return // 유효성 검사에 실패한 입력입니다. 에러 메세지를 세팅합니다. const targetInput = findInputByIndex(index); - - setErrorMessage(validationResultMessage ?? ''); changeErrorIndex(targetInput.index); } }; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 9cb399ef8..925f591e8 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -12,7 +12,7 @@ import {useFetch} from '@apis/useFetch'; import getEventIdByUrl from '@utils/getEventIdByUrl'; -import ERROR_MESSAGE from '@constants/errorMessage'; +import {ERROR_MESSAGE} from '@constants/errorMessage'; const usePutAndDeleteBillAction = ( initialValue: InputPair, @@ -26,7 +26,7 @@ const usePutAndDeleteBillAction = ( const [inputPair, setInputPair] = useState<InputPair>(initialValue); const [canSubmit, setCanSubmit] = useState(false); const [errorInfo, setErrorInfo] = useState<Record<string, boolean>>({title: false, price: false}); - const [errorMessage, setErrorMessage] = useState<string | undefined>(); + const [errorMessage, setErrorMessage] = useState<string | null>(null); const handleInputChange = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; @@ -42,9 +42,10 @@ const usePutAndDeleteBillAction = ( const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue()); + setErrorMessage(errorMessage); + if (isValid) { // valid일 경우 에러메시지 nope, setValue, submit은 value가 비지 않았을 때 true를 설정 - setErrorMessage(undefined); setInputPair(prevInputPair => { return { ...prevInputPair, @@ -55,7 +56,6 @@ const usePutAndDeleteBillAction = ( } else { // valid하지 않으면 event.target.value 덮어쓰기 event.target.value = inputPair[field]; - setErrorMessage(errorMessage); setCanSubmit(false); } diff --git a/client/src/hooks/useSetPassword.ts b/client/src/hooks/useSetPassword.ts index 0ba5e7272..8e8cf9c8c 100644 --- a/client/src/hooks/useSetPassword.ts +++ b/client/src/hooks/useSetPassword.ts @@ -11,7 +11,7 @@ import useEvent from './useEvent'; const useSetPassword = (eventName: string) => { const {fetch} = useFetch(); const [password, setPassword] = useState(''); - const [errorMessage, setErrorMessage] = useState(''); + const [errorMessage, setErrorMessage] = useState<string | null>(null); const [canSubmit, setCanSubmit] = useState(false); const {createNewEvent} = useEvent(); @@ -27,13 +27,12 @@ const useSetPassword = (eventName: string) => { const {isValid, errorMessage} = validateEventPassword(newValue); setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + setErrorMessage(errorMessage); if (isValid) { setPassword(newValue); - setErrorMessage(''); } else { event.target.value = password; - setErrorMessage(errorMessage ?? ''); } }; diff --git a/client/src/utils/validate/type.ts b/client/src/utils/validate/type.ts index ba8b0953b..df81f1644 100644 --- a/client/src/utils/validate/type.ts +++ b/client/src/utils/validate/type.ts @@ -1,5 +1,5 @@ export interface ValidateResult { isValid: boolean; - errorMessage?: string; + errorMessage: string | null; errorInfo?: Record<string, boolean>; } diff --git a/client/src/utils/validate/validateEventName.ts b/client/src/utils/validate/validateEventName.ts index b390f12b9..93f4ecef1 100644 --- a/client/src/utils/validate/validateEventName.ts +++ b/client/src/utils/validate/validateEventName.ts @@ -1,4 +1,4 @@ -import ERROR_MESSAGE from '@constants/errorMessage'; +import {ERROR_MESSAGE} from '@constants/errorMessage'; import RULE from '@constants/rule'; import {ValidateResult} from './type'; @@ -7,7 +7,7 @@ const validateEventName = (name: string): ValidateResult => { if (name.length > RULE.maxEventNameLength) { return {isValid: false, errorMessage: ERROR_MESSAGE.eventName}; } - return {isValid: true}; + return {isValid: true, errorMessage: null}; }; export default validateEventName; diff --git a/client/src/utils/validate/validateEventPassword.ts b/client/src/utils/validate/validateEventPassword.ts index 70499e393..7075e2f3e 100644 --- a/client/src/utils/validate/validateEventPassword.ts +++ b/client/src/utils/validate/validateEventPassword.ts @@ -1,4 +1,4 @@ -import ERROR_MESSAGE from '@constants/errorMessage'; +import {ERROR_MESSAGE} from '@constants/errorMessage'; import REGEXP from '@constants/regExp'; import {ValidateResult} from './type'; @@ -7,7 +7,7 @@ const validateEventPassword = (password: string): ValidateResult => { if (!REGEXP.eventPassword.test(password)) { return {isValid: false, errorMessage: ERROR_MESSAGE.eventPasswordType}; } - return {isValid: true}; + return {isValid: true, errorMessage: null}; }; export default validateEventPassword; diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts index 06c7416dd..053028761 100644 --- a/client/src/utils/validate/validateMemberName.ts +++ b/client/src/utils/validate/validateMemberName.ts @@ -16,7 +16,7 @@ const validateMemberName = (name: string): ValidateResult => { }; if (validateOnlyString() && validateLength()) { - return {isValid: true}; + return {isValid: true, errorMessage: null}; } return {isValid: false, errorMessage: ERROR_MESSAGE.memberName}; diff --git a/client/src/utils/validate/validatePurchase.ts b/client/src/utils/validate/validatePurchase.ts index 7c7a4b3d6..9915ce8b7 100644 --- a/client/src/utils/validate/validatePurchase.ts +++ b/client/src/utils/validate/validatePurchase.ts @@ -1,6 +1,6 @@ import type {Bill} from 'types/serviceType'; -import ERROR_MESSAGE from '@constants/errorMessage'; +import {ERROR_MESSAGE} from '@constants/errorMessage'; import RULE from '@constants/rule'; import REGEXP from '@constants/regExp'; @@ -8,7 +8,7 @@ import {ValidateResult} from './type'; const validatePurchase = (inputPair: Bill): ValidateResult => { const {title, price} = inputPair; - let errorMessage; + let errorMessage: string | null = null; const errorInfo = { price: false, @@ -38,7 +38,7 @@ const validatePurchase = (inputPair: Bill): ValidateResult => { }; if (validatePrice() && validateTitle()) { - return {isValid: true, errorMessage: ''}; + return {isValid: true, errorMessage: null}; } return {isValid: false, errorMessage, errorInfo}; From a5bf87aa21ecc811b0b3297816d4353ef4318b37 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Fri, 16 Aug 2024 18:00:56 +0900 Subject: [PATCH 166/273] =?UTF-8?q?feat:=20=EA=B3=B5=ED=86=B5=20input=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A5=BC=20useInput=20hook=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC=20(#379)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 --- .../OutMember.tsx | 4 +- client/src/constants/errorMessage.ts | 1 + client/src/hooks/useDynamicInput.tsx | 89 +++++------------- client/src/hooks/useInput.tsx | 93 +++++++++++++++++++ client/src/hooks/useSearchInMemberList.ts | 6 +- client/src/hooks/useSetAllMemberList.tsx | 68 ++++++-------- client/src/utils/isArraysEqual.ts | 2 +- .../src/utils/validate/validateMemberName.ts | 13 ++- 8 files changed, 157 insertions(+), 119 deletions(-) create mode 100644 client/src/hooks/useInput.tsx diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx index d139261fd..949d47fa9 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -15,10 +15,10 @@ const OutMember = ({dynamicProps}: OutMemberProps) => { deleteEmptyInputElementOnBlur, focusNextInputOnEnter, handleInputChange, - validateAndSetTargetInput, + handleChange, } = dynamicProps; const {currentInputIndex, filteredInMemberList, handleCurrentInputIndex, searchCurrentInMember, chooseMember} = - useSearchInMemberList(validateAndSetTargetInput); + useSearchInMemberList(handleChange); const validationAndSearchOnChange = (inputIndex: number, event: React.ChangeEvent<HTMLInputElement>) => { handleCurrentInputIndex(inputIndex); diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index f874f6ff4..71354bd99 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -42,6 +42,7 @@ export const ERROR_MESSAGE = { purchasePrice: '10,000,000원 이하의 숫자만 입력이 가능해요', purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', preventEmpty: '값은 비어있을 수 없어요', + invalidInput: '올바르지 않은 입력이에요.', }; export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index 77e25098c..cd639d770 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -2,6 +2,8 @@ import {useEffect, useRef, useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; +import useInput from './useInput'; + type InputValue = { value: string; index: number; @@ -10,22 +12,25 @@ type InputValue = { export type ReturnUseDynamicInput = { inputList: InputValue[]; inputRefList: React.MutableRefObject<(HTMLInputElement | null)[]>; + errorMessage: string | null; + canSubmit: boolean; + errorIndexList: number[]; + handleChange: (index: number, value: string) => void; handleInputChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; deleteEmptyInputElementOnBlur: () => void; - errorMessage: string | null; getFilledInputList: (list?: InputValue[]) => InputValue[]; focusNextInputOnEnter: (e: React.KeyboardEvent<HTMLInputElement>, index: number) => void; - canSubmit: boolean; - errorIndexList: number[]; - validateAndSetTargetInput: (index: number, value: string) => void; + setInputValueTargetIndex: (index: number, value: string) => void; }; const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { - const [inputList, setInputList] = useState<InputValue[]>([{index: 0, value: ''}]); + const initialInputList = [{index: 0, value: ''}]; const inputRefList = useRef<(HTMLInputElement | null)[]>([]); - const [errorMessage, setErrorMessage] = useState<string | null>(null); - const [errorIndexList, setErrorIndexList] = useState<number[]>([]); - const [canSubmit, setCanSubmit] = useState(false); + + const {inputList, errorMessage, errorIndexList, canSubmit, handleChange, setInputList} = useInput({ + validateFunc, + initialInputList, + }); useEffect(() => { if (inputRefList.current.length <= 0) return; @@ -37,14 +42,13 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return } }, [inputList]); - // event에서 value를 받아와서 새 인풋을 만들고 검증 후 set 하는 함수 const handleInputChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; + makeNewInputWhenFirstCharacterInput(index, value); - validateAndSetTargetInput(index, value); + handleChange(index, value); }; - // 첫 번째 문자가 입력됐을 때 새로운 인풋이 생기는 기능 분리 const makeNewInputWhenFirstCharacterInput = (index: number, value: string) => { if (isLastInputFilled(index, value) && value.trim().length !== 0) { // 마지막 인풋이 한 자라도 채워진다면 새로운 인풋을 생성해 간편한 다음 입력을 유도합니다. @@ -59,44 +63,6 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return } }; - // onChange와 setValue 둘 다 지원하기 위해서 validate를 분리 - const validateAndSetTargetInput = (index: number, value: string) => { - const {isValid: isValidInput, errorMessage: validationResultMessage} = validateFunc(value); - setErrorMessage(validationResultMessage); - - if (isValidInput) { - // 입력된 값이 유효하면 데이터(inputList)를 변경합니다. - if (errorIndexList.includes(index)) { - setErrorIndexList(prev => prev.filter(i => i !== index)); - } - - changeInputListValue(index, value); - } else if (value.length === 0) { - // value의 값이 0이라면 errorMessage는 띄워지지 않지만 값은 변경됩니다. 또한 invalid한 값이기에 errorIndex에 추가합니다. - - setErrorMessage(null); - changeErrorIndex(index); - - changeInputListValue(index, value); - } else { - // 유효성 검사에 실패한 입력입니다. 에러 메세지를 세팅합니다. - - const targetInput = findInputByIndex(index); - changeErrorIndex(targetInput.index); - } - }; - - // inputList가 변했을 때 canSubmit이 반영되도록 - // setValue가 수행되기 전에 handleCanSubmit이 실행되어 새로운 입력값에 대한 검증이 되지 않는 버그를 해결 - useEffect(() => { - handleCanSubmit(); - }, [inputList]); - - // 현재까지 입력된 값들로 submit을 할 수 있는지 여부를 핸들합니다. - const handleCanSubmit = () => { - setCanSubmit(inputList.length > 0 && getFilledInputList().length > 0 && errorIndexList.length === 0); - }; - const deleteEmptyInputElementOnBlur = () => { // 0, 1번 input이 값이 있는 상태에서 두 input의 값을 모두 x버튼으로 제거해도 input이 2개 남아있는 문제를 위해 조건문을 추가했습니다. if (getFilledInputList().length === 0 && inputList.length > 1) { @@ -107,7 +73,6 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return // *표시 조건문은 처음에 input을 클릭했다가 블러시켰을 때 filledInputList가 아예 없어 .index에 접근할 때 오류가 납니다. 이를 위한 얼리리턴을 두었습니다. if (getFilledInputList().length === 0) return; - // * if (getFilledInputList().length !== inputList.length) { setInputList(inputList => { const filledInputList = getFilledInputList(inputList); @@ -120,7 +85,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return } }; - const changeInputListValue = (index: number, value: string) => { + const setInputValueTargetIndex = (index: number, value: string) => { setInputList(prevInputs => { const updatedInputList = [...prevInputs]; const targetInput = findInputByIndex(index, updatedInputList); @@ -131,15 +96,6 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return }); }; - const changeErrorIndex = (index: number) => { - setErrorIndexList(prev => { - if (!prev.includes(index)) { - return [...prev, index]; - } - return prev; - }); - }; - const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => { if (e.nativeEvent.isComposing) return; @@ -147,14 +103,11 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return inputRefList.current[index + 1]?.focus(); } }; - // 아래부터는 이 훅에서 재사용되는 함수입니다. - // list 인자를 넘겨주면 그 인자로 찾고, 없다면 inputList state를 사용합니다. const findInputByIndex = (index: number, list?: InputValue[]) => { return (list ?? inputList).filter(input => input.index === index)[0]; }; - // list 인자를 넘겨주면 그 인자로 찾고, 없다면 inputList state를 사용합니다. const getFilledInputList = (list?: InputValue[]) => { return (list ?? inputList).filter(({value}) => value.trim().length !== 0); }; @@ -168,15 +121,15 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return return { inputList, inputRefList, + errorMessage, + canSubmit, + errorIndexList, handleInputChange, + handleChange, deleteEmptyInputElementOnBlur, - errorMessage, getFilledInputList, focusNextInputOnEnter, - canSubmit, - errorIndexList, - validateAndSetTargetInput, - // TODO: (@weadie) 네이밍 수정 + setInputValueTargetIndex, }; }; diff --git a/client/src/hooks/useInput.tsx b/client/src/hooks/useInput.tsx new file mode 100644 index 000000000..1b90805a2 --- /dev/null +++ b/client/src/hooks/useInput.tsx @@ -0,0 +1,93 @@ +import {useEffect, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; + +export type InputValue = { + value: string; + index?: number; +}; + +export type UseInputReturn<T = InputValue> = { + inputList: T[]; + errorMessage: string; + errorIndexList: number[]; + canSubmit: boolean; + handleChange: (index: number, value: string) => void; + setInputList: React.Dispatch<React.SetStateAction<T[]>>; + addErrorIndex: (index: number) => void; + setCanSubmit: React.Dispatch<React.SetStateAction<boolean>>; +}; + +type UseInputProps<T = InputValue> = { + validateFunc: (value: string) => ValidateResult; + initialInputList: T[]; +}; + +const useInput = <T extends InputValue>({validateFunc, initialInputList}: UseInputProps<T>): UseInputReturn<T> => { + const [inputList, setInputList] = useState<T[]>(initialInputList); + const [errorMessage, setErrorMessage] = useState(''); + const [errorIndexList, setErrorIndexList] = useState<number[]>([]); + const [canSubmit, setCanSubmit] = useState(false); + + useEffect(() => { + changeCanSubmit(); + }, [errorMessage, errorIndexList]); + + const handleChange = (index: number = 0, value: string) => { + const {isValid, errorMessage: validationResultMessage} = validateFunc(value); + + if (validationResultMessage === ERROR_MESSAGE.preventEmpty) { + setErrorMessage(validationResultMessage); + updateInputList(index, value); + addErrorIndex(index); + } else if (isValid && value.length !== 0) { + // TODO: (@soha) 쿠키가 작업한 errorMessage를 위로 올리기 변경 추후에 merge후에 반영하기 + setErrorMessage(''); + updateInputList(index, value); + removeErrorIndex(index); + } + }; + + const updateInputList = (index: number, value: string) => { + setInputList(prev => { + const newList = [...prev]; + const targetInput = newList.find(input => input.index === index); + if (targetInput) { + targetInput.value = value; + } + return newList; + }); + }; + + const removeErrorIndex = (index: number) => { + setErrorIndexList(prev => prev.filter(i => i !== index)); + }; + + const addErrorIndex = (index: number) => { + setErrorIndexList(prev => { + if (!prev.includes(index)) { + return [...prev, index]; + } + return prev; + }); + }; + + const changeCanSubmit = () => { + setCanSubmit(errorIndexList.length || errorMessage.length ? false : true); + }; + + return { + inputList, + errorMessage, + errorIndexList, + canSubmit, + handleChange, + setInputList, + addErrorIndex, + setCanSubmit, + }; +}; + +export default useInput; diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index 04514d689..ed7df41a3 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -14,9 +14,7 @@ export type ReturnUseSearchInMemberList = { chooseMember: (inputIndex: number, name: string) => void; }; -const useSearchInMemberList = ( - validateAndSetTargetInput: (index: number, value: string) => void, -): ReturnUseSearchInMemberList => { +const useSearchInMemberList = (handleChange: (index: number, value: string) => void): ReturnUseSearchInMemberList => { const eventId = getEventIdByUrl(); const {fetch} = useFetch(); @@ -47,7 +45,7 @@ const useSearchInMemberList = ( const chooseMember = (inputIndex: number, name: string) => { setFilteredInMemberList([]); - validateAndSetTargetInput(inputIndex, name); + handleChange(inputIndex, name); }; const searchCurrentInMember = (event: React.ChangeEvent<HTMLInputElement>) => { diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index 44066dbf6..69fd4ba96 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -9,6 +9,7 @@ import isArraysEqual from '@utils/isArraysEqual'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import {useStepList} from './useStepList'; +import useInput from './useInput'; interface UseSetAllMemberListProps { validateFunc: (name: string) => ValidateResult; @@ -16,18 +17,37 @@ interface UseSetAllMemberListProps { handleCloseAllMemberListModal: () => void; } +interface UseSetAllMemberListReturns { + editedAllMemberList: string[]; + canSubmit: boolean; + errorMessage: string; + errorIndexList: number[]; + handleNameChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; + handleClickDeleteButton: (index: number) => Promise<void>; + handlePutAllMemberList: () => Promise<void>; +} + const useSetAllMemberList = ({ validateFunc, allMemberList, handleCloseAllMemberListModal, -}: UseSetAllMemberListProps) => { - const [editedAllMemberList, setEditedAllMemberList] = useState<string[]>(allMemberList); - const [errorMessage, setErrorMessage] = useState(''); - const [errorIndexList, setErrorIndexList] = useState<number[]>([]); - const [canSubmit, setCanSubmit] = useState(false); +}: UseSetAllMemberListProps): UseSetAllMemberListReturns => { + const initialInputList = allMemberList.map((name, index) => ({index, value: name})); + const { + inputList, + errorMessage, + errorIndexList, + canSubmit, + handleChange, + setInputList: setEditedAllMemberList, + setCanSubmit, + } = useInput({validateFunc, initialInputList}); + const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); + const editedAllMemberList = inputList.map(input => input.value); + const {refreshStepList} = useStepList(); const eventId = getEventIdByUrl(); const {fetch} = useFetch(); @@ -38,35 +58,8 @@ const useSetAllMemberList = ({ const handleNameChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; - const {isValid, errorMessage: validationResultMessage} = validateFunc(value); - - if (isValid && value.length !== 0) { - setErrorMessage(''); - - setEditedAllMemberList(prev => { - const newList = [...prev]; - newList[index] = value; - return newList; - }); - setErrorIndexList(prev => prev.filter(i => i !== index)); - - setCanSubmit(true); - } else if (value.length === 0) { - setErrorMessage(''); - - setEditedAllMemberList(prev => { - const newList = [...prev]; - newList[index] = value; - return newList; - }); - - changeErrorIndex(index); - } else { - setErrorMessage(validationResultMessage ?? ''); - - changeErrorIndex(index); - } + handleChange(index, value); }; const handleClickDeleteButton = async (index: number) => { @@ -110,15 +103,6 @@ const useSetAllMemberList = ({ }); }; - const changeErrorIndex = (index: number) => { - setErrorIndexList(prev => { - if (!prev.includes(index)) { - return [...prev, index]; - } - return prev; - }); - }; - return { editedAllMemberList, canSubmit, diff --git a/client/src/utils/isArraysEqual.ts b/client/src/utils/isArraysEqual.ts index 1f033eefc..df73a8552 100644 --- a/client/src/utils/isArraysEqual.ts +++ b/client/src/utils/isArraysEqual.ts @@ -1,4 +1,4 @@ -const isArraysEqual = (arr1: string[], arr2: string[]) => { +const isArraysEqual = <T>(arr1: T[], arr2: T[]) => { if (arr1.length !== arr2.length) return false; // 배열을 정렬한 후 비교 diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts index 053028761..e73f42271 100644 --- a/client/src/utils/validate/validateMemberName.ts +++ b/client/src/utils/validate/validateMemberName.ts @@ -5,6 +5,7 @@ import RULE from '@constants/rule'; import {ValidateResult} from './type'; const validateMemberName = (name: string): ValidateResult => { + let errorMessage = null; const validateOnlyString = () => { if (!REGEXP.memberName.test(name)) return false; return true; @@ -15,11 +16,19 @@ const validateMemberName = (name: string): ValidateResult => { return true; }; - if (validateOnlyString() && validateLength()) { + const validateEmpty = () => { + if (!name.trim().length) { + errorMessage = ERROR_MESSAGE.preventEmpty; + return false; + } + return true; + }; + + if (validateOnlyString() && validateLength() && validateEmpty()) { return {isValid: true, errorMessage: null}; } - return {isValid: false, errorMessage: ERROR_MESSAGE.memberName}; + return {isValid: false, errorMessage: errorMessage || ERROR_MESSAGE.memberName}; }; export default validateMemberName; From cd775ba326c1d1f19d93306672f9d4051d43001d Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 16 Aug 2024 18:15:54 +0900 Subject: [PATCH 167/273] =?UTF-8?q?test:=20=ED=9B=85=EC=97=90=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#358)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 --- .github/workflows/frontend-pull-request.yml | 46 +- client/jest.config.ts | 43 + client/jest.polyfills.ts | 20 + client/jest.setup.ts | 22 + client/package-lock.json | 14220 +++++++++++----- client/package.json | 18 +- client/src/ErrorProvider.tsx | 8 +- client/src/apis/fetcher.ts | 10 +- client/src/apis/request/auth.ts | 12 +- client/src/apis/useFetch.ts | 113 - .../MemberReportList/MemberReportList.tsx | 2 +- .../AddBillActionListModalContent.tsx | 6 +- .../AddMemberActionListModalContent.tsx | 2 +- .../DeleteMemberActionModal.tsx | 3 +- .../SetInitialMemberListModal.tsx | 2 +- client/src/components/StepList/StepList.tsx | 2 +- client/src/constants/errorMessage.ts | 1 + client/src/constants/password.ts | 1 + client/src/hooks/useAuth.tsx | 19 - client/src/hooks/useAuth/useAuth.test.tsx | 135 + client/src/hooks/useAuth/useAuth.tsx | 21 + .../useDeleteMemberAction.test.tsx | 131 + .../useDeleteMemberAction.tsx | 6 +- .../src/hooks/useDynamicBillActionInput.tsx | 66 +- client/src/hooks/useEvent/useEvent.test.tsx | 66 + client/src/hooks/{ => useEvent}/useEvent.tsx | 3 +- client/src/hooks/useFetch/useFetch.test.tsx | 154 + client/src/hooks/useFetch/useFetch.ts | 64 + client/src/hooks/usePutAndDeleteBillAction.ts | 6 +- client/src/hooks/useSearchInMemberList.ts | 3 +- .../useSearchMemberReportList.test.tsx | 34 + .../useSearchMemberReportList.tsx | 4 +- client/src/hooks/useSetAllMemberList.tsx | 73 +- client/src/hooks/useSetPassword.ts | 5 +- .../hooks/useStepList/useStepList.test.tsx | 111 + .../hooks/{ => useStepList}/useStepList.tsx | 12 +- client/src/mocks/handlers.ts | 17 +- client/src/mocks/handlers/authHandlers.ts | 104 + client/src/mocks/handlers/eventHandlers.ts | 55 + client/src/mocks/handlers/reportHandlers.ts | 13 + client/src/mocks/handlers/stepListHandler.ts | 111 + client/src/mocks/handlers/testHandlers.ts | 23 + client/src/mocks/invalidMemberStepList.json | 91 + client/src/mocks/memberActionStepList.json | 21 + client/src/mocks/reportList.json | 18 + client/src/mocks/server.ts | 5 + client/src/mocks/serverConstants.ts | 4 + client/src/mocks/validValueForTest.ts | 4 + .../CreateEventPage/SetEventPasswordPage.tsx | 8 +- .../pages/EventPage/AdminPage/AdminPage.tsx | 11 +- .../EventPage/AdminPage/EventLoginPage.tsx | 9 +- .../src/pages/EventPage/EventPageLayout.tsx | 2 +- .../src/pages/EventPage/HomePage/HomePage.tsx | 5 +- client/src/utils/captureError.ts | 57 + client/src/utils/objectToQueryString.ts | 9 + client/tsconfig.json | 4 +- 56 files changed, 11037 insertions(+), 4978 deletions(-) create mode 100644 client/jest.config.ts create mode 100644 client/jest.polyfills.ts create mode 100644 client/jest.setup.ts delete mode 100644 client/src/apis/useFetch.ts create mode 100644 client/src/constants/password.ts delete mode 100644 client/src/hooks/useAuth.tsx create mode 100644 client/src/hooks/useAuth/useAuth.test.tsx create mode 100644 client/src/hooks/useAuth/useAuth.tsx create mode 100644 client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx rename client/src/hooks/{ => useDeleteMemberAction}/useDeleteMemberAction.tsx (96%) create mode 100644 client/src/hooks/useEvent/useEvent.test.tsx rename client/src/hooks/{ => useEvent}/useEvent.tsx (89%) create mode 100644 client/src/hooks/useFetch/useFetch.test.tsx create mode 100644 client/src/hooks/useFetch/useFetch.ts create mode 100644 client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx rename client/src/hooks/{ => useSearchMemberReportList}/useSearchMemberReportList.tsx (96%) create mode 100644 client/src/hooks/useStepList/useStepList.test.tsx rename client/src/hooks/{ => useStepList}/useStepList.tsx (92%) create mode 100644 client/src/mocks/handlers/authHandlers.ts create mode 100644 client/src/mocks/handlers/eventHandlers.ts create mode 100644 client/src/mocks/handlers/reportHandlers.ts create mode 100644 client/src/mocks/handlers/stepListHandler.ts create mode 100644 client/src/mocks/handlers/testHandlers.ts create mode 100644 client/src/mocks/invalidMemberStepList.json create mode 100644 client/src/mocks/memberActionStepList.json create mode 100644 client/src/mocks/reportList.json create mode 100644 client/src/mocks/server.ts create mode 100644 client/src/mocks/serverConstants.ts create mode 100644 client/src/mocks/validValueForTest.ts create mode 100644 client/src/utils/captureError.ts create mode 100644 client/src/utils/objectToQueryString.ts diff --git a/.github/workflows/frontend-pull-request.yml b/.github/workflows/frontend-pull-request.yml index e3461447c..c2749939b 100644 --- a/.github/workflows/frontend-pull-request.yml +++ b/.github/workflows/frontend-pull-request.yml @@ -10,36 +10,40 @@ on: jobs: test: runs-on: ubuntu-latest - + defaults: run: shell: bash working-directory: ./client steps: - - name: Checkout code - uses: actions/checkout@v4 + - name: Checkout code + uses: actions/checkout@v4 - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '20.15.1' + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.15.1' - - name: Install dependencies - working-directory: ./client - run: npm install + - name: Install dependencies + working-directory: ./client + run: npm install - - name: Run lint - working-directory: ./client - run: npm run lint + - name: Run lint + working-directory: ./client + run: npm run lint + + - name: Run test + working-directory: ./client + run: npm run test - - name: Cypress test - run: npm run dev & - env: - CI: true + - name: Cypress test + run: npm run dev & + env: + CI: true - - name: Wait for the server to start - run: sleep 3 + - name: Wait for the server to start + run: sleep 3 - - name: Run Cypress tests - run: npm run cypress-run \ No newline at end of file + - name: Run Cypress tests + run: npm run cypress-run diff --git a/client/jest.config.ts b/client/jest.config.ts new file mode 100644 index 000000000..7d54d6b1d --- /dev/null +++ b/client/jest.config.ts @@ -0,0 +1,43 @@ +import type {Config} from 'jest'; + +const config: Config = { + preset: 'ts-jest', + // testEnvironment: 'node', // Node.js 모듈(fs, path, http 등)을 사용한 서버 사이드 로직이나 파일 시스템 접근, 네트워크 요청 등을 테스트 + testEnvironment: 'jsdom', // 브라우저 내에서의 JavaScript 동작을 모방하여, DOM 조작, 이벤트 핸들링, 브라우저 관련 API 호출 + transform: { + '^.+\\.ts?$': 'ts-jest', + }, + collectCoverage: true, + coverageReporters: ['text'], + coveragePathIgnorePatterns: [ + '<rootDir>/node_modules/', + '<rootDir>/src/utils/', + '<rootDir>/src/mocks/', + '<rootDir>/src/apis/', + '<rootDir>/src/request/', + '<rootDir>/src/constants/', + '<rootDir>/src/errors/', + '<rootDir>/src/ErrorProvider.tsx', + ], + + verbose: true, + setupFiles: ['./jest.polyfills.ts'], + setupFilesAfterEnv: ['./jest.setup.ts'], + transformIgnorePatterns: ['<rootDir>/node_modules/'], + moduleNameMapper: { + '@/(.*)$': '<rootDir>/src/$1', // path alias를 적용하기 위함 + '^@apis/(.*)$': '<rootDir>/src/apis/$1', + '^@constants/(.*)$': '<rootDir>/src/constants/$1', + '^@hooks/(.*)$': '<rootDir>/src/hooks/$1', + '^@utils/(.*)$': '<rootDir>/src/utils/$1', + '^@pages/(.*)$': '<rootDir>/src/pages/$1', + '^@types/(.*)$': '<rootDir>/src/types/$1', + '^@errors/(.*)$': '<rootDir>/src/errors/$1', + '^@mocks/(.*)$': '<rootDir>/src/mocks/$1', + }, + testEnvironmentOptions: { + customExportConditions: [''], + }, +}; + +export default config; diff --git a/client/jest.polyfills.ts b/client/jest.polyfills.ts new file mode 100644 index 000000000..16547bc80 --- /dev/null +++ b/client/jest.polyfills.ts @@ -0,0 +1,20 @@ +import {TextDecoder, TextEncoder} from 'node:util'; + +Object.defineProperties(globalThis, { + TextDecoder: {value: TextDecoder}, + TextEncoder: {value: TextEncoder}, +}); + +import {Blob, File} from 'node:buffer'; + +import {fetch, Headers, FormData, Request, Response} from 'undici'; + +Object.defineProperties(globalThis, { + fetch: {value: fetch, writable: true}, + Blob: {value: Blob}, + File: {value: File}, + Headers: {value: Headers}, + FormData: {value: FormData}, + Request: {value: Request}, + Response: {value: Response}, +}); diff --git a/client/jest.setup.ts b/client/jest.setup.ts new file mode 100644 index 000000000..d3ff94078 --- /dev/null +++ b/client/jest.setup.ts @@ -0,0 +1,22 @@ +import {server} from './src/mocks/server'; +import * as router from 'react-router'; + +beforeAll(() => { + server.listen(); + + Object.defineProperty(window, 'location', { + writable: true, + value: { + ...window.location, + pathname: '/event/abc-123/', // 원하는 pathname 설정 + }, + }); +}); +afterEach(() => server.resetHandlers()); +afterAll(() => server.close()); + +beforeAll(() => {}); +jest.mock('./src/utils/captureError'); +jest.mock('./src/utils/sendLogToSentry'); + +jest.spyOn(router, 'useNavigate').mockImplementation(() => jest.fn()); diff --git a/client/package-lock.json b/client/package-lock.json index 0a884603e..ca9b099ba 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", - "haengdong-design": "^0.1.72", + "haengdong-design": "^0.1.74", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -21,9 +21,14 @@ "devDependencies": { "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", + "@jest/types": "^29.6.3", "@sentry/webpack-plugin": "^2.22.0", "@svgr/webpack": "^8.1.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.4.8", + "@testing-library/react": "^16.0.0", "@types/dotenv-webpack": "^7.0.7", + "@types/jest": "^29.5.12", "@types/react": "^18.3.3", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.0", @@ -42,12 +47,18 @@ "globals": "^15.8.0", "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jsdom": "^24.1.1", "modify-source-webpack-plugin": "^4.1.0", "msw": "^2.3.5", "prettier": "3.3.2", + "ts-jest": "^29.2.4", "ts-loader": "^9.5.1", - "typescript": "^5.5.3", + "ts-node": "^10.9.2", + "typescript": "^5.5.4", "typescript-eslint": "^7.16.0", + "undici": "^5.28.4", "webpack": "^5.93.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.4", @@ -58,6 +69,12 @@ "npm": ">=10.7.0" } }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -516,6 +533,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", @@ -1800,6 +1829,12 @@ "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "node_modules/@bundled-es-modules/cookie": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz", @@ -1847,6 +1882,28 @@ "node": ">=0.1.90" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@cypress/request": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", @@ -2166,6 +2223,15 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2373,2020 +2439,6041 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=6" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@jsonjoy.com/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "dependencies": { + "p-locate": "^4.1.0" }, - "peerDependencies": { - "tslib": "2" + "engines": { + "node": ">=8" } }, - "node_modules/@jsonjoy.com/json-pack": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", - "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "@jsonjoy.com/base64": "^1.1.1", - "@jsonjoy.com/util": "^1.1.2", - "hyperdyperid": "^1.2.0", - "thingies": "^1.20.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=10.0" + "node": ">=6" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jsonjoy.com/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", - "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "dependencies": { + "p-limit": "^2.2.0" }, - "peerDependencies": { - "tslib": "2" + "engines": { + "node": ">=8" } }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "dev": true + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/@mswjs/interceptors": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", - "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.2.1", - "strict-event-emitter": "^0.5.1" - }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 8" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", - "dev": true - }, - "node_modules/@open-draft/logger": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "is-node-process": "^1.2.0", - "outvariant": "^1.4.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@open-draft/until": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "optional": true, "engines": { - "node": ">=14" + "node": ">=8" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "dependencies": { + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@remix-run/router": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", - "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", "engines": { - "node": ">=14.0.0" + "node": ">=8" } }, - "node_modules/@sentry-internal/browser-utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", - "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, "dependencies": { - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=14.18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@sentry-internal/feedback": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", - "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=14.18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@sentry-internal/replay": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", - "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@sentry-internal/browser-utils": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14.18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@sentry-internal/replay-canvas": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", - "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@sentry-internal/replay": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=14.18" + "node": ">=7.0.0" } }, - "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", - "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">= 14" + "node": ">=8" } }, - "node_modules/@sentry/browser": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", - "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@sentry-internal/browser-utils": "8.25.0", - "@sentry-internal/feedback": "8.25.0", - "@sentry-internal/replay": "8.25.0", - "@sentry-internal/replay-canvas": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=14.18" + "node": ">=8" } }, - "node_modules/@sentry/bundler-plugin-core": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", - "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dev": true, "dependencies": { - "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "2.22.0", - "@sentry/cli": "^2.33.1", - "dotenv": "^16.3.1", - "find-up": "^5.0.0", - "glob": "^9.3.2", - "magic-string": "0.30.8", - "unplugin": "1.0.1" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">= 14" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "jest-get-type": "^29.6.3" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@sentry/cli": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", - "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, - "hasInstallScript": true, "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.7", - "progress": "^2.0.3", - "proxy-from-env": "^1.1.0", - "which": "^2.0.2" - }, - "bin": { - "sentry-cli": "bin/sentry-cli" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">= 10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "optionalDependencies": { - "@sentry/cli-darwin": "2.33.1", - "@sentry/cli-linux-arm": "2.33.1", - "@sentry/cli-linux-arm64": "2.33.1", - "@sentry/cli-linux-i686": "2.33.1", - "@sentry/cli-linux-x64": "2.33.1", - "@sentry/cli-win32-i686": "2.33.1", - "@sentry/cli-win32-x64": "2.33.1" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@sentry/cli-darwin": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", - "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@sentry/cli-linux-arm": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", - "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", - "cpu": [ - "arm" - ], + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], - "engines": { - "node": ">=10" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@sentry/cli-linux-arm64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", - "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", - "cpu": [ - "arm64" - ], + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@sentry/cli-linux-i686": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", - "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", - "cpu": [ - "x86", - "ia32" - ], + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=10" + "node": ">=7.0.0" } }, - "node_modules/@sentry/cli-linux-x64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", - "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", - "cpu": [ - "x64" - ], + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">=10" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@sentry/cli-win32-i686": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", - "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", - "cpu": [ - "x86", - "ia32" - ], + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/@sentry/cli-win32-x64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", - "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", - "cpu": [ - "x64" - ], + "node_modules/@jest/reporters/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@sentry/core": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", - "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", + "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=14.18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@sentry/react": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", - "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { - "@sentry/browser": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0", - "hoist-non-react-statics": "^3.3.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=14.18" - }, - "peerDependencies": { - "react": "^16.14.0 || 17.x || 18.x || 19.x" + "node": "*" } }, - "node_modules/@sentry/types": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", - "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=14.18" + "node": ">=8" } }, - "node_modules/@sentry/utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", - "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, "dependencies": { - "@sentry/types": "8.25.0" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=14.18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@sentry/webpack-plugin": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", - "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { - "@sentry/bundler-plugin-core": "2.22.0", - "unplugin": "1.0.1", - "uuid": "^9.0.0" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "webpack": ">=4.40.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@sentry/webpack-plugin/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@storybook/addon-webpack5-compiler-swc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", - "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, "dependencies": { - "@swc/core": "^1.7.3", - "swc-loader": "^0.2.3" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=18" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=14" + "node": ">=8" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "node_modules/@jest/transform/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/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=8" } }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", - "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "engines": { - "node": ">=14" + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", - "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=12" + "node": ">=8" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@svgr/babel-preset": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", - "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", - "@svgr/babel-plugin-transform-svg-component": "8.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@svgr/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", - "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3", - "snake-case": "^3.0.4" + "color-name": "~1.1.4" }, "engines": { - "node": ">=14" + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "engines": { + "node": ">=8" } }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", - "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dependencies": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=14" + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/gregberge" + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/@svgr/plugin-jsx": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", - "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", + "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "dev": true, "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "@svgr/hast-util-to-babel-ast": "8.0.0", - "svg-parser": "^2.0.4" + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" }, "engines": { - "node": ">=14" + "node": ">=10.0" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/gregberge" + "url": "https://github.com/sponsors/streamich" }, "peerDependencies": { - "@svgr/core": "*" + "tslib": "2" } }, - "node_modules/@svgr/plugin-svgo": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", - "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", - "dependencies": { - "cosmiconfig": "^8.1.3", - "deepmerge": "^4.3.1", - "svgo": "^3.0.2" - }, + "node_modules/@jsonjoy.com/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "dev": true, "engines": { - "node": ">=14" + "node": ">=10.0" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/gregberge" + "url": "https://github.com/sponsors/streamich" }, "peerDependencies": { - "@svgr/core": "*" + "tslib": "2" } }, - "node_modules/@svgr/webpack": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", - "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@babel/plugin-transform-react-constant-elements": "^7.21.3", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", - "@svgr/core": "8.1.0", - "@svgr/plugin-jsx": "8.1.0", - "@svgr/plugin-svgo": "8.1.0" + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@mswjs/interceptors": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", + "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" }, "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" + "node": ">=18" } }, - "node_modules/@swc/core": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.6.tgz", - "integrity": "sha512-FZxyao9eQks1MRmUshgsZTmlg/HB2oXK5fghkoWJm/1CU2q2kaJlVDll2as5j+rmWiwkp0Gidlq8wlXcEEAO+g==", - "hasInstallScript": true, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.12" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.6", - "@swc/core-darwin-x64": "1.7.6", - "@swc/core-linux-arm-gnueabihf": "1.7.6", - "@swc/core-linux-arm64-gnu": "1.7.6", - "@swc/core-linux-arm64-musl": "1.7.6", - "@swc/core-linux-x64-gnu": "1.7.6", - "@swc/core-linux-x64-musl": "1.7.6", - "@swc/core-win32-arm64-msvc": "1.7.6", - "@swc/core-win32-ia32-msvc": "1.7.6", - "@swc/core-win32-x64-msvc": "1.7.6" - }, - "peerDependencies": { - "@swc/helpers": "*" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } + "node": ">= 8" } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.6.tgz", - "integrity": "sha512-6lYHey84ZzsdtC7UuPheM4Rm0Inzxm6Sb8U6dmKc4eCx8JL0LfWG4LC5RsdsrTxnjTsbriWlnhZBffh8ijUHIQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "engines": { - "node": ">=10" + "node": ">= 8" } }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.6.tgz", - "integrity": "sha512-Fyl+8aH9O5rpx4O7r2KnsPpoi32iWoKOYKiipeTbGjQ/E95tNPxbmsz4yqE8Ovldcga60IPJ5OKQA3HWRiuzdw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, "engines": { - "node": ">=10" + "node": ">= 8" } }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.6.tgz", - "integrity": "sha512-2WxYTqFaOx48GKC2cbO1/IntA+w+kfCFy436Ij7qRqqtV/WAvTM9TC1OmiFbqq436rSot52qYmX8fkwdB5UcLQ==", - "cpu": [ - "arm" - ], + "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", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=10" + "node": ">=14" } }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.6.tgz", - "integrity": "sha512-TBEGMSe0LhvPe4S7E68c7VzgT3OMu4VTmBLS7B2aHv4v8uZO92Khpp7L0WqgYU1y5eMjk+XLDLi4kokiNHv/Hg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, "engines": { - "node": ">=10" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" } }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.6.tgz", - "integrity": "sha512-QI8QGL0HGT42tj7F1A+YAzhGkJjUcvvTfI1e2m704W0Enl2/UIK9v5D1zvQzYwusRyKuaQfbeBRYDh0NcLOGLg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@remix-run/router": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", "engines": { - "node": ">=10" + "node": ">=14.0.0" } }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.6.tgz", - "integrity": "sha512-61AYVzhjuNQAVIKKWOJu3H0/pFD28RYJGxnGg3YMhvRLRyuWNyY5Nyyj2WkKcz/ON+g38Arlz00NT1LDIViRLg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@sentry-internal/browser-utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", + "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, "engines": { - "node": ">=10" + "node": ">=14.18" } }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.6.tgz", - "integrity": "sha512-hQFznpfLK8XajfAAN9Cjs0w/aVmO7iu9VZvInyrTCRcPqxV5O+rvrhRxKvC1LRMZXr5M6JRSRtepp5w+TK4kAw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@sentry-internal/feedback": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", + "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, "engines": { - "node": ">=10" + "node": ">=14.18" } }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.6.tgz", - "integrity": "sha512-Aqsd9afykVMuekzjm4X4TDqwxmG4CrzoOSFe0hZrn9SMio72l5eAPnMtYoe5LsIqtjV8MNprLfXaNbjHjTegmA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@sentry-internal/replay": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", + "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, "engines": { - "node": ">=10" + "node": ">=14.18" } }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.6.tgz", - "integrity": "sha512-9h0hYnOeRVNeQgHQTvD1Im67faNSSzBZ7Adtxyu9urNLfBTJilMllFd2QuGHlKW5+uaT6ZH7ZWDb+c/enx7Lcg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@sentry-internal/replay-canvas": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", + "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", + "dependencies": { + "@sentry-internal/replay": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, "engines": { - "node": ">=10" + "node": ">=14.18" } }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.6.tgz", - "integrity": "sha512-izeoB8glCSe6IIDQmrVm6bvR9muk9TeKgmtY7b6l1BwL4BFnTUk4dMmpbntT90bEVQn3JPCaPtUG4HfL8VuyuA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", + "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "dev": true, "engines": { - "node": ">=10" + "node": ">= 14" } }, - "node_modules/@swc/counter": { - "version": "0.1.3", + "node_modules/@sentry/browser": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", + "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry-internal/feedback": "8.25.0", + "@sentry-internal/replay": "8.25.0", + "@sentry-internal/replay-canvas": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", + "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "2.22.0", + "@sentry/cli": "^2.33.1", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/cli": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", + "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", + "dependencies": { + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/react": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", + "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "dependencies": { + "@sentry/browser": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/types": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", + "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", + "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", + "dependencies": { + "@sentry/types": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/webpack-plugin": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", + "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "dev": true, + "dependencies": { + "@sentry/bundler-plugin-core": "2.22.0", + "unplugin": "1.0.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "webpack": ">=4.40.0" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "dependencies": { + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@swc/core": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.11.tgz", + "integrity": "sha512-AB+qc45UrJrDfbhPKcUXk+9z/NmFfYYwJT6G7/iur0fCse9kXjx45gi40+u/O2zgarG/30/zV6E3ps8fUvjh7g==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.11", + "@swc/core-darwin-x64": "1.7.11", + "@swc/core-linux-arm-gnueabihf": "1.7.11", + "@swc/core-linux-arm64-gnu": "1.7.11", + "@swc/core-linux-arm64-musl": "1.7.11", + "@swc/core-linux-x64-gnu": "1.7.11", + "@swc/core-linux-x64-musl": "1.7.11", + "@swc/core-win32-arm64-msvc": "1.7.11", + "@swc/core-win32-ia32-msvc": "1.7.11", + "@swc/core-win32-x64-msvc": "1.7.11" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.11.tgz", + "integrity": "sha512-HRQv4qIeMBPThZ6Y/4yYW52rGsS6yrpusvuxLGyoFo45Y0y12/V2yXkOIA/0HIQyrqoUAxn1k4zQXpPaPNCmnw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.11.tgz", + "integrity": "sha512-vtMQj0F3oYwDu5yhO7SKDRg1XekRSi6/TbzHAbBXv+dBhlGGvcZZynT1H90EVFTv+7w7Sh+lOFvRv5Z4ZTcxow==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.11.tgz", + "integrity": "sha512-mHtzWKxhtyreI4CSxs+3+ENv8t/Qo35WFoYG66qHEgJz/Z2Lh6jv1E+MYgHdYwnpQHgHbdvAco7HsBu/Dt6xXw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.11.tgz", + "integrity": "sha512-FRwe/x0GfXSQjGP2lIk+NO0pUFS/lI/RorCLBPiK808EVE9JTbh9DKCc/4Bbb4jgScAjNkrFCUVObQYl3YKmpA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.11.tgz", + "integrity": "sha512-GY/rs0+GUq14Gbnza90KOrQd/9yHd5qQMii5jcSWcUCT5A8QTa8kiicsM2NxZeTJ69xlKmT7sLod5l99lki/2A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.11.tgz", + "integrity": "sha512-QDkGRwSPmp2RBOlSs503IUXlWYlny8DyznTT0QuK0ML2RpDFlXWU94K/EZhS0RBEUkMY/W51OacM8P8aS/dkCg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.11.tgz", + "integrity": "sha512-SBEfKrXy6zQ6ksnyxw1FaCftrIH4fLfA81xNnKb7x/6iblv7Ko6H0aK3P5C86jyqF/82+ONl9C7ImGkUFQADig==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.11.tgz", + "integrity": "sha512-a2Y4xxEsLLYHJN7sMnw9+YQJDi3M1BxEr9hklfopPuGGnYLFNnx5CypH1l9ReijEfWjIAHNi7pq3m023lzW1Hg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.11.tgz", + "integrity": "sha512-ZbZFMwZO+j8ulhegJ7EhJ/QVZPoQ5qc30ylJQSxizizTJaen71Q7/13lXWc6ksuCKvg6dUKrp/TPgoxOOtSrFA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.11.tgz", + "integrity": "sha512-IUohZedSJyDu/ReEBG/mqX6uG29uA7zZ9z6dIAF+p6eFxjXmh9MuHryyM+H8ebUyoq/Ad3rL+rUCksnuYNnI0w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" }, - "node_modules/@swc/types": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", - "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.8.tgz", + "integrity": "sha512-JD0G+Zc38f5MBHA4NgxQMR5XtO5Jx9g86jqturNTt2WUfRmLDIY7iKkWHDCCTiDuFMre6nxAD5wHw9W5kI4rGw==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", + "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true + }, + "node_modules/@types/dotenv-webpack": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", + "integrity": "sha512-tltVokFUeYuSjNmHc6N892Asu/JIQcnH2iUF5A29/VKqv9opq6KlrmnKd/Lt/bBikV/z0YN2K0kguTwWirYCMQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-copy-to-clipboard": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz", + "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true + }, + "node_modules/@types/sizzle": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", + "dev": true + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "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": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "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, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "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, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz", + "integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==", + "dev": true + }, + "node_modules/axe-core": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001649", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz", + "integrity": "sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "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==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/core-js-compat": { + "version": "3.38.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", + "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@swc/counter": "^0.1.3" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=10.13.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "node_modules/create-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@types/connect": "*", - "@types/node": "*" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "node_modules/create-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/create-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "dev": true, + "dependencies": { + "rrweb-cssom": "^0.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/cypress": { + "version": "13.13.2", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.2.tgz", + "integrity": "sha512-PvJQU33933NvS1StfzEb8/mu2kMy4dABwCF+yd5Bi7Qly1HOVf+Bufrygee/tlmty/6j5lX+KIi8j9Q3JUMbhA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@cypress/request": "^3.0.1", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.7.1", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.1", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.3", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + } + }, + "node_modules/cypress/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "@types/node": "*" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "@types/node": "*" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "node_modules/cypress/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "node_modules/cypress/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@types/dotenv-webpack": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", - "integrity": "sha512-tltVokFUeYuSjNmHc6N892Asu/JIQcnH2iUF5A29/VKqv9opq6KlrmnKd/Lt/bBikV/z0YN2K0kguTwWirYCMQ==", + "node_modules/cypress/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true, - "dependencies": { - "@types/node": "*", - "tapable": "^2.2.0", - "webpack": "^5" + "engines": { + "node": ">= 6" } }, - "node_modules/@types/eslint": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", - "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "node_modules/cypress/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "node_modules/cypress/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "node_modules/cypress/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "node_modules/cypress/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" + "engines": { + "node": ">=8" } }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.14", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", - "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "node_modules/cypress/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true, - "dependencies": { - "@types/node": "*" + "engines": { + "node": ">=8.12.0" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "node_modules/cypress/node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", "dev": true }, - "node_modules/@types/mute-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", - "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", - "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "node_modules/cypress/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, - "dependencies": { - "undici-types": "~6.13.0" + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "node_modules/cypress/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "@types/node": "*" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true - }, - "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/@types/react-copy-to-clipboard": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz", - "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==", + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", "dev": true, "dependencies": { - "@types/react": "*" + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "node_modules/data-urls/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", "dev": true, "dependencies": { - "@types/react": "*" + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", "dev": true, "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, "dependencies": { - "@types/express": "*" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", - "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", - "dev": true - }, - "node_modules/@types/sizzle": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", - "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", - "dev": true - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, "dependencies": { - "@types/node": "*" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/statuses": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", - "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "node_modules/dayjs": { + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", "dev": true }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "dev": true + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } }, - "node_modules/@types/wrap-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", - "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", "dev": true }, - "node_modules/@types/ws": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", - "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, - "dependencies": { - "@types/node": "*" + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } } }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", "dev": true, - "optional": true, "dependencies": { - "@types/node": "*" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" - }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "execa": "^5.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 10" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "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, "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, "engines": { - "node": ">=10" + "node": ">=0.4.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" + "node": ">= 0.8" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=6" } }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", "dev": true, "dependencies": { - "@xtuc/ieee754": "^1.2.0" + "utila": "~0.4" } }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "dev": true, "dependencies": { - "@xtuc/long": "4.2.2" + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "engines": { + "node": ">=12" } }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" + "no-case": "^3.0.4", + "tslib": "^2.0.3" } }, - "node_modules/@webpack-cli/configtest": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", - "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, "engines": { - "node": ">=14.15.0" + "node": ">=12" }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "funding": { + "url": "https://dotenvx.com" } }, - "node_modules/@webpack-cli/info": { + "node_modules/dotenv-defaults": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", - "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz", + "integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==", + "dev": true, + "dependencies": { + "dotenv": "^8.2.0" + } + }, + "node_modules/dotenv-defaults/node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", "dev": true, "engines": { - "node": ">=14.15.0" - }, - "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" + "node": ">=10" } }, - "node_modules/@webpack-cli/serve": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", - "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "node_modules/dotenv-webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz", + "integrity": "sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag==", "dev": true, + "dependencies": { + "dotenv-defaults": "^2.0.2" + }, "engines": { - "node": ">=14.15.0" + "node": ">=10" }, "peerDependencies": { - "webpack": "5.x.x", - "webpack-cli": "5.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } + "webpack": "^4 || ^5" } }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" }, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "node_modules/electron-to-chromium": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, "engines": { - "node": ">=0.4.0" + "node": ">= 4" } }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, - "peerDependencies": { - "acorn": "^8" + "engines": { + "node": ">= 0.8" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "once": "^1.4.0" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "dependencies": { - "debug": "4" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">= 6.0.0" + "node": ">=10.13.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=8.6" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" + "bin": { + "envinfo": "dist/cli.js" }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "engines": { + "node": ">=4" } }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "node_modules/es-define-property": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "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, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", "dev": true, "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", "dev": true, - "engines": { - "node": ">=10" + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" } }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "node_modules/es-shim-unscopables": { + "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, "dependencies": { - "deep-equal": "^2.0.5" + "hasown": "^2.0.0" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "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==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4395,1058 +8482,1017 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "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" - }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/array-union": { + "node_modules/escodegen": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "dependencies": { - "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" - }, + "optional": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "node_modules/eslint": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", "dev": true, "dependencies": { - "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" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://eslint.org/donate" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "ms": "^2.1.1" } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 0.4" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "debug": "^3.2.7" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { - "safer-buffer": "~2.1.0" + "ms": "^2.1.1" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "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.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, "engines": { - "node": ">=0.8" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, - "engines": { - "node": ">= 4.0.0" + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/available-typed-arrays": { - "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==", + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, "engines": { "node": "*" } }, - "node_modules/aws4": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz", - "integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==", - "dev": true - }, - "node_modules/axe-core": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", - "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, "engines": { - "node": ">=4" + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "deep-equal": "^2.0.5" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10", - "npm": ">=6" + "node": "*" } }, - "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" }, "engines": { - "node": ">=10" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "node_modules/eslint-plugin-react": { + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "tweetnacl": "^0.14.3" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { "node": "*" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "node_modules/eslint-scope": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { - "node": ">= 0.8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "ms": "2.0.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "node_modules/brace-expansion": { + "node_modules/eslint/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, - "dependencies": { - "fill-range": "^7.1.1" + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.23.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", - "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { - "caniuse-lite": "^1.0.30001646", - "electron-to-chromium": "^1.5.4", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": "*" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, + "has-flag": "^4.0.0" + }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "dependencies": { - "run-applescript": "^7.0.0" + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": ">=18" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "engines": { - "node": ">= 0.8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" + "estraverse": "^5.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "engines": { - "node": ">=6" + "node": ">=0.10" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.0" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001649", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz", - "integrity": "sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/chalk/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">= 0.6" } }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "engines": { - "node": ">= 0.8.0" + "node": ">=0.8.x" } }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", "dev": true, "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">= 8.10.0" + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "pify": "^2.2.0" }, "engines": { - "node": ">= 6" + "node": ">=4" } }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { - "node": ">=6.0" + "node": ">= 0.8.0" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dev": true, "dependencies": { - "source-map": "~0.6.0" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 10.0" + "node": ">= 0.10.0" } }, - "node_modules/clean-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==", + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" }, "engines": { - "node": ">=8" + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" } }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "dev": true, - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } + "engines": [ + "node >=0.6.0" + ] }, - "node_modules/cli-table3/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "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 }, - "node_modules/cli-table3/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=8" + "node": ">=8.6.0" } }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "engines": { - "node": ">= 12" + "node": ">= 4.9.1" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" + "reusify": "^1.0.4" } }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "websocket-driver": ">=0.5.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=0.8.0" } }, - "node_modules/cliui/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "bser": "2.1.1" } }, - "node_modules/cliui/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "pend": "~1.2.0" } }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "escape-string-regexp": "^1.0.5" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" + "node": ">=0.8.0" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "delayed-stream": "~1.0.0" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=16.0.0" } }, - "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, - "engines": { - "node": ">=14" + "dependencies": { + "minimatch": "^5.0.1" } }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=4.0.0" + "node": ">=10" } }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { - "mime-db": ">= 1.43.0 < 2" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dev": true, "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8" } }, - "node_modules/compression/node_modules/debug": { + "node_modules/finalhandler/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", @@ -5455,271 +9501,156 @@ "ms": "2.0.0" } }, - "node_modules/compression/node_modules/ms": { + "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, - "node_modules/compression/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "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==", - "dependencies": { - "toggle-selection": "^1.0.6" + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" } }, - "node_modules/core-js-compat": { - "version": "3.38.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", - "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, "dependencies": { - "browserslist": "^4.23.3" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "engines": { + "node": ">=16" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" + "node": ">=4.0" }, "peerDependenciesMeta": { - "typescript": { + "debug": { "optional": true } } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "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==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" + "is-callable": "^1.1.3" } }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dev": true, "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dependencies": { - "css-tree": "~2.2.0" - }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" + "node": "*" } }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/cypress": { - "version": "13.13.2", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.2.tgz", - "integrity": "sha512-PvJQU33933NvS1StfzEb8/mu2kMy4dABwCF+yd5Bi7Qly1HOVf+Bufrygee/tlmty/6j5lX+KIi8j9Q3JUMbhA==", + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", "dev": true, - "hasInstallScript": true, "dependencies": { - "@cypress/request": "^3.0.1", - "@cypress/xvfb": "^1.2.4", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.7.1", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-ci": "^3.0.1", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.3", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" }, "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" } }, - "node_modules/cypress/node_modules/ansi-styles": { + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -5734,7 +9665,17 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cypress/node_modules/chalk": { + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -5750,19 +9691,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cypress/node_modules/color-convert": { + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -5774,186 +9703,341 @@ "node": ">=7.0.0" } }, - "node_modules/cypress/node_modules/color-name": { + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/cypress/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/cypress/node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/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, + "bin": { + "semver": "bin/semver.js" }, "engines": { "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/cypress/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "dependencies": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/cypress/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { - "pump": "^3.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cypress/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/cypress/node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", "dev": true, - "engines": { - "node": ">=8.12.0" + "dependencies": { + "async": "^3.2.0" } }, - "node_modules/cypress/node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", - "dev": true - }, - "node_modules/cypress/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "dependencies": { + "assert-plus": "^1.0.0" } }, - "node_modules/cypress/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=10" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "assert-plus": "^1.0.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=0.10" + "node": ">=10.13.0" } }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", "dev": true, "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "ini": "2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "node_modules/globals": { + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "node_modules/globalthis": { + "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, "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -5962,124 +10046,116 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dayjs": { - "version": "1.11.12", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", - "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { - "ms": "2.1.2" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=6.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" + "get-intrinsic": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, + "node_modules/haengdong-design": { + "version": "0.1.74", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.74.tgz", + "integrity": "sha512-K75LDIR4wqR+Z8YDTMsYXm9sWQ60Qw4DLPSOSnsb5mzncX1u3/z+zLOb1gs/zS8YZznUwzu6HzavWh6Sl8guNQ==", "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" + "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@svgr/webpack": "^8.1.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" }, "engines": { - "node": ">=18" - }, + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "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==", + "dev": true, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "node_modules/has-property-descriptors": { + "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, "dependencies": { - "execa": "^5.0.0" + "es-define-property": "^1.0.0" }, - "engines": { - "node": ">= 10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, "engines": { "node": ">= 0.4" }, @@ -6087,27 +10163,25 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "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==", "dev": true, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -6116,100 +10190,245 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, - "engines": { - "node": ">=0.4.0" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, - "engines": { - "node": ">= 0.8" + "dependencies": { + "safe-buffer": "~5.1.0" } }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "node": ">=18" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/html-loader": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.1.0.tgz", + "integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==", "dev": true, "dependencies": { - "path-type": "^4.0.0" + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" }, "engines": { - "node": ">=8" + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, "engines": { - "node": ">=6" + "node": ">= 12" } }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", "dev": true, "dependencies": { - "esutils": "^2.0.2" + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" + "node": ">=12" } }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "dependencies": { "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/dom-serializer/node_modules/entities": { + "node_modules/htmlparser2/node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", @@ -6218,393 +10437,377 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "dependencies": { - "domelementtype": "^2.2.0" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": ">= 0.8" } }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "engines": { + "node": ">=8.0.0" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "debug": "^4.3.4" }, - "funding": { - "url": "https://dotenvx.com" + "engines": { + "node": ">= 14" } }, - "node_modules/dotenv-defaults": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz", - "integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==", + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", "dev": true, "dependencies": { - "dotenv": "^8.2.0" + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } } }, - "node_modules/dotenv-defaults/node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, "engines": { - "node": ">=10" + "node": ">=0.10" } }, - "node_modules/dotenv-webpack": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz", - "integrity": "sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag==", + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "dependencies": { - "dotenv-defaults": "^2.0.2" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">=10" - }, - "peerDependencies": { - "webpack": "^4 || ^5" + "node": ">= 6" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "engines": { + "node": ">=10.17.0" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", - "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "engines": { + "node": ">=10.18" + } }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, "engines": { - "node": ">= 4" + "node": ">=0.10.0" } }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, - "engines": { - "node": ">= 0.8" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, - "dependencies": { - "once": "^1.4.0" + "engines": { + "node": ">= 4" } }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { - "node": ">=8.6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">=0.8.19" } }, - "node_modules/envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, "dependencies": { - "is-arrayish": "^0.2.1" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "hasown": "^2.0.0", + "side-channel": "^1.0.4" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { - "node": ">= 0.4" + "node": ">=10.13.0" } }, - "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==", + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", "dev": true, "engines": { - "node": ">= 0.4" + "node": ">= 10" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "dev": true, "dependencies": { - "es-errors": "^1.3.0" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "has-bigints": "^1.0.1" }, - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-shim-unscopables": { - "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==", + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { - "hasown": "^2.0.0" + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "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==", + "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==", "dev": true, "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -6613,1076 +10816,1030 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "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, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", - "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.17.1", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.8.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "ci-info": "^3.2.0" }, "bin": { - "eslint": "bin/eslint.js" + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "dependencies": { + "hasown": "^2.0.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" + "is-typed-array": "^1.1.13" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "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==", "dev": true, "dependencies": { - "debug": "^3.2.7" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "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.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "engines": { + "node": ">=8" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", - "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, "dependencies": { - "aria-query": "~5.1.3", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.9.1", - "axobject-query": "~3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.19", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" }, "engines": { - "node": "*" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", "dev": true, "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">= 0.4" }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react": { - "version": "7.35.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", - "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "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==", "dev": true, "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", - "string.prototype.repeat": "^1.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", "dev": true, "engines": { "node": ">=10" }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "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==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "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, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "call-bind": "^1.0.7" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "has-symbols": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "which-typed-array": "^1.1.14" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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, "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "node": ">= 0.4" }, - "engines": { - "node": "*" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "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==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "call-bind": "^1.0.2" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", "dev": true, "dependencies": { - "estraverse": "^5.1.0" + "is-inside-container": "^1.0.0" }, "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" + "node": ">=16" }, - "engines": { - "node": ">=4.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", - "dev": true - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { - "node": ">=0.8.x" + "node": ">=8" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "node_modules/istanbul-lib-instrument/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, - "dependencies": { - "pify": "^2.2.0" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.10.0" + "node": ">=10" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "dependencies": { "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "node": ">=10" } }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { - "pump": "^3.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "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 - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=8.6.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" }, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">= 4.9.1" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "reusify": "^1.0.4" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "websocket-driver": ">=0.5.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "pend": "~1.2.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=0.8.0" + "node": "*" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "flat-cache": "^4.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=8" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "dependencies": { - "to-regex-range": "^5.0.1" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dev": true, "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">= 0.8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", "dev": true, "dependencies": { - "ms": "2.0.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "bin": { - "flat": "cli.js" + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=16" + "node": ">=8" } }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, "engines": { - "node": ">=4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "debug": { + "node-notifier": { "optional": 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==", + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "is-callable": "^1.1.3" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=8" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", - "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^8.2.0", + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=12.13.0", - "yarn": ">=1.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "typescript": ">3.6.0", - "webpack": "^5.11.0" + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { + "node_modules/jest-config/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -7697,7 +11854,7 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "node_modules/jest-config/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", @@ -7707,7 +11864,7 @@ "concat-map": "0.0.1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "node_modules/jest-config/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -7723,7 +11880,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { + "node_modules/jest-config/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -7735,13 +11892,34 @@ "node": ">=7.0.0" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { + "node_modules/jest-config/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/has-flag": { + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -7750,7 +11928,7 @@ "node": ">=8" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "node_modules/jest-config/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", @@ -7762,19 +11940,7 @@ "node": "*" } }, - "node_modules/fork-ts-checker-webpack-plugin/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, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { + "node_modules/jest-config/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -7786,1504 +11952,1522 @@ "node": ">=8" } }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 0.12" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=12" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node": ">=8" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=7.0.0" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/get-tsconfig": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", - "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "resolve-pkg-maps": "^1.0.0" + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dev": true, "dependencies": { - "async": "^3.2.0" + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dev": true, "dependencies": { - "assert-plus": "^1.0.0" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "color-convert": "^2.0.1" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "is-glob": "^4.0.3" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "ini": "2.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=7.0.0" } }, - "node_modules/globals": { - "version": "15.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", - "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/jest-environment-jsdom/node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3" + "cssom": "~0.3.6" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "node_modules/jest-environment-jsdom/node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, - "node_modules/graphql": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", - "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "node_modules/jest-environment-jsdom/node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + "node": ">=12" } }, - "node_modules/haengdong-design": { - "version": "0.1.72", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.72.tgz", - "integrity": "sha512-7Qtk/HygT5IhLzUTQzcx7FbgZo/ZrqVZhKA08zJaf1wcOlc3CkXO3Ljl1wQloHGejg71K1N1BO3L208tppxycQ==", + "node_modules/jest-environment-jsdom/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, "dependencies": { - "@emotion/react": "^11.11.4", - "@storybook/addon-webpack5-compiler-swc": "^1.0.5", - "@svgr/webpack": "^8.1.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=20.15.1", - "npm": ">=10.7.0" + "node": ">= 6" } }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "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==", + "node_modules/jest-environment-jsdom/node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/jest-environment-jsdom/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/jest-environment-jsdom/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "dependencies": { - "es-define-property": "^1.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/jest-environment-jsdom/node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", "dev": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=14" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "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==", + "node_modules/jest-environment-jsdom/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "dev": true, - "engines": { - "node": ">= 0.4" + "dependencies": { + "punycode": "^2.1.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=12" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/jest-environment-jsdom/node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.3" + "xml-name-validator": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/jest-environment-jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, "dependencies": { - "function-bind": "^1.1.2" + "iconv-lite": "0.6.3" }, "engines": { - "node": ">= 0.4" + "node": ">=12" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "node_modules/jest-environment-jsdom/node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/headers-polyfill": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", - "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", - "dev": true - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" + "engines": { + "node": ">=12" } }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "node_modules/jest-environment-jsdom/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dev": true, "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/jest-environment-jsdom/node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "engines": { + "node": ">=12" } }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/html-loader": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.1.0.tgz", - "integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dev": true, "dependencies": { - "html-minifier-terser": "^7.2.0", - "parse5": "^7.1.2" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">= 18.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/html-minifier-terser": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", - "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "node_modules/jest-haste-map/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-haste-map/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "~5.3.2", - "commander": "^10.0.0", - "entities": "^4.4.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.15.1" - }, - "bin": { - "html-minifier-terser": "cli.js" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": "^14.13.1 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "node_modules/jest-haste-map/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/html-webpack-plugin/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": ">= 12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dev": true, "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dev": true, "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, "engines": { - "node": ">=8.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" + "node": ">=8" }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "agent-base": "6", - "debug": "4" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 6" + "node": ">=7.0.0" } }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=10.17.0" + "node": ">=8" } }, - "node_modules/hyperdyperid": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", - "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=10.18" + "node": ">=8" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true } - ] + } }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "dev": true, "engines": { - "node": ">= 4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dev": true, "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.8.19" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=8" + "node": ">=7.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" + "node": ">=8" } }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=7.0.0" } }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=8" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/jest-runner/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dev": true, "dependencies": { - "binary-extensions": "^2.0.0" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-runner/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "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==", + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", "dev": true, "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "hasown": "^2.0.2" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", "dev": true, "dependencies": { - "is-typed-array": "^1.1.13" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "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==", + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "bin": { - "is-docker": "cli.js" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dev": true, "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "engines": { - "node": ">= 0.4" + "dependencies": { + "color-name": "~1.1.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/is-network-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/is-node-process": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", - "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", - "dev": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-snapshot/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, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=0.12.0" + "node": ">=10" } }, - "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==", + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "isobject": "^3.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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==", + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=7.0.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==", + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "call-bind": "^1.0.7" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "which-typed-array": "^1.1.14" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=7.0.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "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==", + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "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/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "is-inside-container": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=16" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "has-flag": "^4.0.0" }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "engines": { + "node": ">=8" } }, "node_modules/jest-worker": { @@ -9346,6 +13530,119 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, + "node_modules/jsdom": { + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz", + "integrity": "sha512-5O1wWV99Jhq4DV7rCLIoZ/UIhyQeDR7wHVyZAHAshbrvZsLs+Xzz7gtwnlJTJDjleiTKh54F4dXrX70vJQTyJQ==", + "dev": true, + "dependencies": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.4", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -9463,6 +13760,15 @@ "node": ">=0.10.0" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/language-subtag-registry": { "version": "0.3.23", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", @@ -9500,6 +13806,15 @@ "node": "> 0.8" } }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -9665,6 +13980,12 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -9892,6 +14213,15 @@ "yallist": "^3.0.2" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/magic-string": { "version": "0.30.8", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", @@ -9904,6 +14234,48 @@ "node": ">=12" } }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -10015,6 +14387,15 @@ "node": ">=6" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -10331,6 +14712,12 @@ "node": ">= 6.13.0" } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", @@ -10368,6 +14755,12 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/nwsapi": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "dev": true + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -10747,6 +15140,15 @@ "node": ">=8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -10835,6 +15237,15 @@ "node": ">=0.10.0" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -10966,6 +15377,38 @@ "renderkid": "^3.0.0" } }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -10987,7 +15430,20 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, "engines": { - "node": ">=0.4.0" + "node": ">=0.4.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" } }, "node_modules/prop-types": { @@ -11053,6 +15509,22 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -11255,6 +15727,19 @@ "node": ">= 10.13.0" } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -11467,6 +15952,15 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -11520,6 +16014,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true + }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -11625,6 +16125,18 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -11929,6 +16441,12 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -12070,6 +16588,12 @@ "wbuf": "^1.7.3" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", @@ -12095,6 +16619,27 @@ "node": ">=0.10.0" } }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -12131,6 +16676,19 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -12334,6 +16892,18 @@ "node": ">=6" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -12477,6 +17047,12 @@ "webpack": ">=2" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "node_modules/synckit": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", @@ -12560,6 +17136,63 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -12608,6 +17241,12 @@ "node": ">=14.14" } }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -12700,6 +17339,66 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-jest": { + "version": "29.2.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", + "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ts-loader": { "version": "9.5.1", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", @@ -12811,6 +17510,49 @@ "node": ">=8" } }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -12870,6 +17612,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", @@ -13022,6 +17773,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/undici-types": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", @@ -13181,6 +17944,32 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/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/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -13210,6 +17999,27 @@ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/watchpack": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", @@ -13631,6 +18441,39 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -13883,6 +18726,19 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/ws": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", @@ -13904,6 +18760,21 @@ } } }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -13983,6 +18854,15 @@ "fd-slicer": "~1.1.0" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/client/package.json b/client/package.json index b0d9e7ff0..fe7f565ed 100644 --- a/client/package.json +++ b/client/package.json @@ -11,7 +11,8 @@ "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", "cypress-open": "cypress open", - "cypress-run": "cypress run" + "cypress-run": "cypress run", + "test": "jest" }, "keywords": [], "author": "", @@ -19,9 +20,14 @@ "devDependencies": { "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", + "@jest/types": "^29.6.3", "@sentry/webpack-plugin": "^2.22.0", "@svgr/webpack": "^8.1.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.4.8", + "@testing-library/react": "^16.0.0", "@types/dotenv-webpack": "^7.0.7", + "@types/jest": "^29.5.12", "@types/react": "^18.3.3", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.0", @@ -40,12 +46,18 @@ "globals": "^15.8.0", "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jsdom": "^24.1.1", "modify-source-webpack-plugin": "^4.1.0", "msw": "^2.3.5", "prettier": "3.3.2", + "ts-jest": "^29.2.4", "ts-loader": "^9.5.1", - "typescript": "^5.5.3", + "ts-node": "^10.9.2", + "typescript": "^5.5.4", "typescript-eslint": "^7.16.0", + "undici": "^5.28.4", "webpack": "^5.93.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.4", @@ -54,7 +66,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", - "haengdong-design": "^0.1.72", + "haengdong-design": "^0.1.74", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/ErrorProvider.tsx b/client/src/ErrorProvider.tsx index 92b93fb60..c657d9337 100644 --- a/client/src/ErrorProvider.tsx +++ b/client/src/ErrorProvider.tsx @@ -8,6 +8,7 @@ interface ErrorContextType { errorMessage: string; setError: (error: ServerError) => void; clearError: (ms?: number) => void; + error: ServerError | null; } const ErrorContext = createContext<ErrorContextType | undefined>(undefined); @@ -32,6 +33,7 @@ export const ErrorProvider = ({children, callback}: ErrorProviderProps) => { if (error) { if (isUnhandledError(error.errorCode)) { // 에러바운더리로 보내기 + throw error; } @@ -49,6 +51,8 @@ export const ErrorProvider = ({children, callback}: ErrorProviderProps) => { }; const clearError = (ms: number = 0) => { + if (error === null) return; + setTimeout(() => { setHasError(false); setErrorMessage(''); @@ -57,7 +61,9 @@ export const ErrorProvider = ({children, callback}: ErrorProviderProps) => { }; return ( - <ErrorContext.Provider value={{hasError, errorMessage, setError, clearError}}>{children}</ErrorContext.Provider> + <ErrorContext.Provider value={{error, hasError, errorMessage, setError, clearError}}> + {children} + </ErrorContext.Provider> ); }; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 8ca83aab8..01c4bec7f 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -1,5 +1,7 @@ import {ServerError} from 'ErrorProvider'; +import objectToQueryString from '@utils/objectToQueryString'; + import {UNKNOWN_ERROR} from '@constants/errorMessage'; import FetchError from '../errors/FetchError'; @@ -35,13 +37,7 @@ type ErrorHandlerProps = { body: string; }; -const API_BASE_URL = process.env.API_BASE_URL; - -const objectToQueryString = (params: ObjectQueryParams): string => { - return Object.entries(params) - .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) - .join('&'); -}; +const API_BASE_URL = process.env.API_BASE_URL ?? ''; export const requestGet = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { const response = await fetcher({ diff --git a/client/src/apis/request/auth.ts b/client/src/apis/request/auth.ts index 94fb2c55f..9c56d1f6b 100644 --- a/client/src/apis/request/auth.ts +++ b/client/src/apis/request/auth.ts @@ -1,24 +1,20 @@ import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestPostWithResponse, requestPostWithoutResponse} from '@apis/fetcher'; - -export type RequestAuthentication = { - eventId: string; -}; +import {requestPostWithoutResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; export type RequestToken = { - eventId: string; password: string; }; -export const requestAuthentication = async ({eventId}: RequestAuthentication) => { +export const requestPostAuthentication = async ({eventId}: WithEventId) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/auth`, }); }; -export const requestToken = async ({eventId, password}: RequestToken) => { +export const requestPostToken = async ({eventId, password}: WithEventId<RequestToken>) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/login`, diff --git a/client/src/apis/useFetch.ts b/client/src/apis/useFetch.ts deleted file mode 100644 index 512ef4a96..000000000 --- a/client/src/apis/useFetch.ts +++ /dev/null @@ -1,113 +0,0 @@ -import {useState} from 'react'; -import {NavigateFunction, useNavigate} from 'react-router-dom'; - -import sendLogToSentry from '@utils/sendLogToSentry'; -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import {UNKNOWN_ERROR} from '@constants/errorMessage'; -import {ROUTER_URLS} from '@constants/routerUrls'; - -import {ServerError, useError} from '../ErrorProvider'; -import FetchError from '../errors/FetchError'; - -type FetchProps<T> = { - queryFunction: () => Promise<T>; - onSuccess?: () => void; - onError?: () => void; -}; - -export const useFetch = () => { - const {setError, clearError} = useError(); - const [loading, setLoading] = useState(false); - const navigate = useNavigate(); - const eventId = getEventIdByUrl(); - - const fetch = async <T>({queryFunction, onSuccess, onError}: FetchProps<T>): Promise<T> => { - setLoading(true); - clearError(); - - try { - const result = await queryFunction(); - - if (onSuccess) { - onSuccess(); - } - - return result; - } catch (error) { - if (error instanceof Error) { - const errorBody = - error instanceof FetchError ? error.errorBody : {errorCode: error.name, message: error.message}; - - setError(errorBody); - - if (onError) { - onError(); - } - - captureError(error, navigate, eventId); - } else { - setError({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); - captureError(new Error(UNKNOWN_ERROR), navigate, eventId); - - // 에러를 throw 해 에러 바운더리로 보냅니다. 따라서 에러 이름은 중요하지 않음 - throw new Error(UNKNOWN_ERROR); - } - } finally { - setLoading(false); - } - - return {} as T; - }; - - return {loading, fetch}; -}; - -const captureError = async (error: Error, navigate: NavigateFunction, eventId: string) => { - // prod 환경에서만 Sentry capture 실행 - if (process.env.NODE_ENV !== 'production') return; - - const errorBody: ServerError = - error instanceof FetchError ? error.errorBody : {message: error.message, errorCode: error.name}; - - switch (errorBody?.errorCode) { - case 'INTERNAL_SERVER_ERROR': - sendLogToSentry({error, errorBody, level: 'fatal'}); - break; - - case 'FORBIDDEN': - sendLogToSentry({error, errorBody}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); - break; - - case 'TOKEN_INVALID': - sendLogToSentry({error, errorBody}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); - break; - - case 'TOKEN_EXPIRED': - sendLogToSentry({error, errorBody}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); - break; - - case 'TOKEN_NOT_FOUND': - sendLogToSentry({error, errorBody}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); - break; - - // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 - case 'PASSWORD_INVALID': - sendLogToSentry({error, errorBody, level: 'debug'}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); - break; - - // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 - case 'BILL_ACTION_PRICE_INVALID': - sendLogToSentry({error, errorBody, level: 'debug'}); - break; - - default: - sendLogToSentry({error, errorBody, level: 'fatal'}); - break; - } -}; diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx index ac4cd5e5c..1004540fa 100644 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -1,7 +1,7 @@ import {ExpenseList, Flex, Input} from 'haengdong-design'; import React, {useState} from 'react'; -import useSearchMemberReportList from '@hooks/useSearchMemberReportList'; +import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; const MemberReportList = () => { const [name, setName] = useState(''); diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index cc49d5953..0f11852af 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -2,8 +2,8 @@ import {FixedButton, LabelGroupInput} from 'haengdong-design'; import {useEffect} from 'react'; import validatePurchase from '@utils/validate/validatePurchase'; +import {useStepList} from '@hooks/useStepList/useStepList'; -import {useStepList} from '@hooks/useStepList'; import useDynamicBillActionInput from '@hooks/useDynamicBillActionInput'; import style from './AddBillActionListModalContent.style'; @@ -43,23 +43,23 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList elementKey={`${index}`} type="text" value={title} - isError={errorIndexList.includes(index)} onChange={e => handleInputChange(index, 'title', e)} onKeyDown={e => focusNextInputOnEnter(e, index, 'title')} onBlur={() => deleteEmptyInputPairElementOnBlur()} // TODO: (@weadie) 이 블러프롭이 내부적으로 index를 넘기고 있기 때문에 화살표 함수로 써야만하내요.. placeholder="지출 내역" ref={el => (inputRefList.current[index * 2] = el)} + isError={errorIndexList.includes(index)} /> <LabelGroupInput.Element elementKey={`${index}`} type="number" value={price} - isError={errorIndexList.includes(index)} onChange={e => handleInputChange(index, 'price', e)} onKeyDown={e => focusNextInputOnEnter(e, index, 'price')} onBlur={() => deleteEmptyInputPairElementOnBlur()} placeholder="금액" ref={el => (inputRefList.current[index * 2 + 1] = el)} + isError={errorIndexList.includes(index)} /> </div> ))} diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index 5e63b4940..d0fd809d7 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -3,8 +3,8 @@ import type {MemberType} from 'types/serviceType'; import {FixedButton, LabelGroupInput} from 'haengdong-design'; import validateMemberName from '@utils/validate/validateMemberName'; +import {useStepList} from '@hooks/useStepList/useStepList'; -import {useStepList} from '@hooks/useStepList'; import useDynamicInput from '@hooks/useDynamicInput'; import style from './AddMemberActionListModalContent.style'; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx index 18b7e13ac..b4c24afbb 100644 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -3,8 +3,7 @@ import type {MemberAction, MemberType} from 'types/serviceType'; import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; import {useToast} from '@components/Toast/ToastProvider'; - -import useDeleteMemberAction from '@hooks/useDeleteMemberAction'; +import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index 623d9f98f..93fb2eae3 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -1,8 +1,8 @@ import {Text, BottomSheet, FixedButton, LabelGroupInput} from 'haengdong-design'; import validateMemberName from '@utils/validate/validateMemberName'; +import {useStepList} from '@hooks/useStepList/useStepList'; -import {useStepList} from '@hooks/useStepList'; import useDynamicInput from '@hooks/useDynamicInput'; import { diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 9119bda97..1aeb7888e 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,6 +1,6 @@ import {Flex} from 'haengdong-design'; -import {useStepList} from '@hooks/useStepList'; +import {useStepList} from '@hooks/useStepList/useStepList'; import Step from './Step'; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index 71354bd99..42703bdf0 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -23,6 +23,7 @@ export const SERVER_ERROR_MESSAGES: ErrorMessage = { REQUEST_EMPTY: '입력 값은 공백일 수 없습니다.', MESSAGE_NOT_READABLE: '읽을 수 없는 요청입니다.', NO_RESOURCE_REQUEST: '존재하지 않는 자원입니다.', + REQUEST_METHOD_NOT_SUPPORTED: '지원하지 않는 요청 메서드입니다.', INTERNAL_SERVER_ERROR: '서버 내부에 에러가 발생했습니다.', diff --git a/client/src/constants/password.ts b/client/src/constants/password.ts new file mode 100644 index 000000000..cfb26b39c --- /dev/null +++ b/client/src/constants/password.ts @@ -0,0 +1 @@ +export const PASSWORD_LENGTH = 4; diff --git a/client/src/hooks/useAuth.tsx b/client/src/hooks/useAuth.tsx deleted file mode 100644 index 10ea3f973..000000000 --- a/client/src/hooks/useAuth.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import {RequestAuthentication, requestAuthentication, RequestToken, requestToken} from '@apis/request/auth'; - -import {useFetch} from '@apis/useFetch'; - -const useAuth = () => { - const {fetch} = useFetch(); - - const postAuthentication = async ({eventId}: RequestAuthentication) => { - return await fetch({queryFunction: () => requestAuthentication({eventId})}); - }; - - const postLogin = async ({eventId, password}: RequestToken) => { - return await fetch({queryFunction: () => requestToken({eventId, password})}); - }; - - return {postAuthentication, postLogin}; -}; - -export default useAuth; diff --git a/client/src/hooks/useAuth/useAuth.test.tsx b/client/src/hooks/useAuth/useAuth.test.tsx new file mode 100644 index 000000000..48aaade10 --- /dev/null +++ b/client/src/hooks/useAuth/useAuth.test.tsx @@ -0,0 +1,135 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {act} from 'react'; +import {MemoryRouter} from 'react-router-dom'; + +import {PASSWORD_LENGTH} from '@constants/password'; + +import {VALID_PASSWORD_FOR_TEST, VALID_TOKEN_FOR_TEST} from '@mocks/validValueForTest'; + +import {ErrorProvider, useError} from '../../ErrorProvider'; + +import useAuth from './useAuth'; + +describe('useAuth', () => { + const initializeProvider = () => + renderHook( + () => { + return {errorResult: useError(), authResult: useAuth()}; + }, + { + wrapper: ({children}) => ( + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + ), + }, + ); + + describe('auth', () => { + it('쿠키에 토큰이 담겨있지 않다면 인증이 실패한다', async () => { + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.authResult.checkAuthentication()); + }); + + await waitFor(() => { + expect(result.current.errorResult.error?.errorCode).toBe('TOKEN_NOT_FOUND'); + }); + }); + + it('쿠키에 담겨있는 토큰이 올바르다면 인증에 성공한다', async () => { + document.cookie = `eventToken=${VALID_TOKEN_FOR_TEST}`; + + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.authResult.checkAuthentication()); + }); + + await waitFor(() => { + expect(result.current.errorResult.error).toBe(null); + }); + }); + + it('쿠키에 담겨있는 토큰이 유효하지 않다면 인증에 실패한다.', async () => { + document.cookie = 'eventToken=fake-token'; + + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.authResult.checkAuthentication()); + }); + + await waitFor(() => { + expect(result.current.errorResult.error?.errorCode).toBe('TOKEN_INVALID'); + }); + }); + + it('쿠키에 담겨있는 토큰이 만료되었다면 인증에 실패한다.', async () => { + document.cookie = 'eventToken=expired-token'; + + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.authResult.checkAuthentication()); + }); + + await waitFor(() => { + expect(result.current.errorResult.error?.errorCode).toBe('TOKEN_EXPIRED'); + }); + }); + + it('쿠키에 담겨있는 토큰이 forbidden이라면 인증에 실패한다.', async () => { + document.cookie = 'eventToken=forbidden-token'; + + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.authResult.checkAuthentication()); + }); + + await waitFor(() => { + expect(result.current.errorResult.error?.errorCode).toBe('FORBIDDEN'); + }); + }); + }); + + describe('login', () => { + it('비밀 번호가 올바르다면 로그인이 성공한다.', async () => { + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.authResult.loginUser({password: String(VALID_PASSWORD_FOR_TEST)})); + }); + + await waitFor(() => { + expect(result.current.errorResult.error).toBe(null); + }); + }); + + it(`비밀 번호가 ${PASSWORD_LENGTH}자리가 아니라면 로그인에 실패한다.`, async () => { + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.authResult.loginUser({password: '111'})); + }); + + await waitFor(() => { + expect(result.current.errorResult.error?.errorCode).toBe('EVENT_PASSWORD_FORMAT_INVALID'); + }); + }); + + it('비밀 번호가 틀렸다면 로그인에 실패한다.', async () => { + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.authResult.loginUser({password: '9999'})); + }); + + await waitFor(() => { + expect(result.current.errorResult.error?.errorCode).toBe('PASSWORD_INVALID'); + }); + }); + }); +}); diff --git a/client/src/hooks/useAuth/useAuth.tsx b/client/src/hooks/useAuth/useAuth.tsx new file mode 100644 index 000000000..a294f6ad8 --- /dev/null +++ b/client/src/hooks/useAuth/useAuth.tsx @@ -0,0 +1,21 @@ +import {RequestToken, requestPostAuthentication, requestPostToken} from '@apis/request/auth'; +import {useFetch} from '@hooks/useFetch/useFetch'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +const useAuth = () => { + const {fetch} = useFetch(); + const eventId = getEventIdByUrl(); + + const checkAuthentication = async () => { + return await fetch({queryFunction: () => requestPostAuthentication({eventId})}); + }; + + const loginUser = async ({password}: RequestToken) => { + return await fetch({queryFunction: () => requestPostToken({eventId, password})}); + }; + + return {checkAuthentication, loginUser}; +}; + +export default useAuth; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx new file mode 100644 index 000000000..9ca4d7bff --- /dev/null +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -0,0 +1,131 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {act} from 'react'; + +import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; + +import stepListJson from '../../mocks/stepList.json'; +import StepListProvider, {useStepList} from '../useStepList/useStepList'; +import {ErrorProvider} from '../../ErrorProvider'; +import invalidMemberStepListJson from '../../mocks/invalidMemberStepList.json'; + +import useDeleteMemberAction from './useDeleteMemberAction'; + +const stepListMockData = stepListJson as (BillStep | MemberStep)[]; +let memberActionList: MemberAction[] = []; + +// filter로는 type narrowing이 안되어 부득이하게 for 문을 사용했습니다. +for (let i = 0; i < stepListMockData.length; i++) { + const curAction = stepListMockData[i]; + if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); +} + +describe('useDeleteMemberAction', () => { + const initializeProvider = (list: MemberAction[] = memberActionList) => + renderHook( + () => { + return { + stepListResult: useStepList(), + deleteMemberActionList: useDeleteMemberAction({ + memberActionList: list, + setIsBottomSheetOpened: () => {}, + showToastAlreadyExistMemberAction: () => {}, + showToastExistSameMemberFromAfterStep: () => {}, + }), + }; + }, + { + wrapper: ({children}) => ( + <MemoryRouter> + <ErrorProvider> + <StepListProvider>{children}</StepListProvider> + </ErrorProvider> + </MemoryRouter> + ), + }, + ); + + it('멤버를 삭제할 멤버 목록에 추가한다.', async () => { + const {result} = initializeProvider(); + + // stepList 값이 채워지길 대기합니다. + await waitFor(() => { + expect(result.current.stepListResult.stepList).not.toStrictEqual([]); + }); + + await act(async () => { + const memberAction = { + actionId: 1, + name: '망쵸', + price: null, + sequence: 1, + }; + + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + + expect(result.current.deleteMemberActionList.aliveActionList).not.toContainEqual({ + actionId: 1, + name: '망쵸', + price: null, + sequence: 1, + }); + }); + + it('삭제할 멤버 목록에 있는 멤버들을 모두 삭제해 삭제할 멤버 목록을 비운다.', async () => { + const {result} = initializeProvider(); + + // stepList 값이 채워지길 대기합니다. + await waitFor(() => { + expect(result.current.stepListResult.stepList).not.toStrictEqual([]); + }); + + await act(async () => { + memberActionList.forEach(memberAction => { + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + }); + + await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); + + await waitFor(() => { + expect(result.current.deleteMemberActionList.aliveActionList).toHaveLength(0); + }); + }); + + it('삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 처음의 상태로 돌려놓는다.', async () => { + /** + * 이 테스트는 deleteMemberAction을 실행했을 때 오류가 나는 경우를 테스트하기 위해 작성되었습니다. + * 여기서 사용하는 stepList 목데이터는 999 actionId를 가진 MemberAction이 있는 데이터입니다. + * 999 actionId는 현재 모킹되어있는 msw에서 오류를 뱉도록 하는 id입니다. 이는 오류 상황을 시연하기 위한 임의 모킹입니다. + * (999가 아닌 경우는 모두 정상 응답 반환) + */ + + // 999 actionId를 가진 MemberAction이 있는 stepListJson 데이터를 사용해 MemberActions []으로 정제합니다. + const invalidMemberStepListMockData = invalidMemberStepListJson as (BillStep | MemberStep)[]; + let memberActionList: MemberAction[] = []; + + for (let i = 0; i < invalidMemberStepListMockData.length; i++) { + const curAction = invalidMemberStepListMockData[i]; + if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); + } + + // 오류 멤버가 포함된 memberAction[]을 useDeleteMemberAction의 초기값으로 주입합니다. + const {result} = initializeProvider(memberActionList); + + // stepList 값이 채워지길 대기합니다. + await waitFor(() => { + expect(result.current.stepListResult.stepList).not.toStrictEqual([]); + }); + + await act(async () => { + const memberAction = memberActionList[0]; // 현재 0번 참여자는 actionId가 999 이고, 999 actionId는 서버에서 에러를 뱉도록 조작된 상황입니다. + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + + await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); + + // 삭제 요청에서 오류가 발생했기 때문에 aliveActionList를 초기에 주입했던 값으로 다시 돌려놓는지 확인합니다. + expect(result.current.deleteMemberActionList.aliveActionList).toStrictEqual(memberActionList); + }); +}); diff --git a/client/src/hooks/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx similarity index 96% rename from client/src/hooks/useDeleteMemberAction.tsx rename to client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx index be16baf02..265eafecd 100644 --- a/client/src/hooks/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx @@ -3,10 +3,8 @@ import type {MemberAction} from 'types/serviceType'; import {useState} from 'react'; import {requestDeleteMemberAction} from '@apis/request/member'; - -import {useStepList} from '@hooks/useStepList'; - -import {useFetch} from '@apis/useFetch'; +import {useStepList} from '@hooks/useStepList/useStepList'; +import {useFetch} from '@hooks/useFetch/useFetch'; import getEventIdByUrl from '@utils/getEventIdByUrl'; diff --git a/client/src/hooks/useDynamicBillActionInput.tsx b/client/src/hooks/useDynamicBillActionInput.tsx index f21311de8..d07794751 100644 --- a/client/src/hooks/useDynamicBillActionInput.tsx +++ b/client/src/hooks/useDynamicBillActionInput.tsx @@ -14,8 +14,7 @@ export type BillInputType = 'title' | 'price'; const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateResult) => { const [inputPairList, setInputPairList] = useState<InputPair[]>([{title: '', price: '', index: 0}]); const inputRefList = useRef<(HTMLInputElement | null)[]>([]); - const [errorMessage, setErrorMessage] = useState<string | null>(null); - const [errorIndexList, setErrorIndexList] = useState<number[]>([]); + const [errorMessage, setErrorMessage] = useState(''); const [canSubmit, setCanSubmit] = useState(false); useEffect(() => { @@ -34,16 +33,14 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe [field]: value, }); - setErrorMessage(validationResultMessage); - // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수로 분리 - if ( - isLastInputPairFilled({index, field, value}) && - targetInputPair.title.trim().length !== 0 && - targetInputPair.price.trim().length !== 0 - ) { + if (isLastInputPairFilled({index, field, value})) { + setErrorMessage(''); setInputPairList(prevInputPairList => { const updatedInputPairList = [...prevInputPairList]; + const targetInputPair = findInputPairByIndex(index, updatedInputPairList); + + targetInputPair[field] = value; // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 const newIndex = updatedInputPairList[updatedInputPairList.length - 1].index + 1; @@ -51,20 +48,22 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe return finalInputs; }); - } else if (isValidInput) { - // 입력된 값이 유효하면 데이터(inputLis)를 변경합니다. - if (errorIndexList.includes(index)) { - setErrorIndexList(prev => prev.filter(i => i !== index)); - } - - changeInputListValue(index, value, field); - } else if (value.length === 0) { - setErrorMessage(null); - changeErrorIndex(index); - - changeInputListValue(index, value, field); + } else if (isValidInput || value.length === 0) { + setErrorMessage(''); + setInputPairList(prevInputPairList => { + const updatedInputPairList = [...prevInputPairList]; + const targetInputPair = findInputPairByIndex(index, updatedInputPairList); + + targetInputPair[field] = value; + + return updatedInputPairList; + }); } else { - changeErrorIndex(targetInputPair.index); + const targetInput = findInputPairByIndex(index); + + event.target.value = targetInput[field]; + + setErrorMessage(validationResultMessage ?? ''); } handleCanSubmit(); @@ -97,26 +96,6 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe setCanSubmit(inputPairList.length > 0 && getFilledInputPairList().length > 0); }; - const changeInputListValue = (index: number, value: string, field: BillInputType) => { - setInputPairList(prevInputPairList => { - const updatedInputPairList = [...prevInputPairList]; - const targetInputPair = findInputPairByIndex(index, updatedInputPairList); - - targetInputPair[field] = value; - - return updatedInputPairList; - }); - }; - - const changeErrorIndex = (index: number) => { - setErrorIndexList(prev => { - if (!prev.includes(index)) { - return [...prev, index]; - } - return prev; - }); - }; - const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number, field: BillInputType) => { if (e.nativeEvent.isComposing) return; @@ -137,7 +116,7 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe // list 인자를 넘겨주면 그 인자로 찾고, 없다면 InputPairList state를 사용합니다. const getFilledInputPairList = (list?: InputPair[]) => { - return (list ?? inputPairList).filter(({title, price}) => title.trim().length !== 0 && price.trim().length !== 0); + return (list ?? inputPairList).filter(({title, price}) => title !== '' && price !== ''); }; const isLastInputPairFilled = ({index, value}: {index: number; field: BillInputType; value: string}) => { @@ -150,7 +129,6 @@ const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateRe inputPairList, getFilledInputPairList, inputRefList, - errorIndexList, handleInputChange, deleteEmptyInputPairElementOnBlur, errorMessage, diff --git a/client/src/hooks/useEvent/useEvent.test.tsx b/client/src/hooks/useEvent/useEvent.test.tsx new file mode 100644 index 000000000..b6a616b00 --- /dev/null +++ b/client/src/hooks/useEvent/useEvent.test.tsx @@ -0,0 +1,66 @@ +import {renderHook} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {act} from 'react'; + +import {PASSWORD_LENGTH} from '@constants/password'; + +import {VALID_PASSWORD_FOR_TEST} from '@mocks/validValueForTest'; +import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; + +import {ErrorProvider, useError} from '../../ErrorProvider'; + +import useEvent from './useEvent'; + +describe('useEvent', () => { + const initializeProvider = () => + renderHook( + () => { + return {errorResult: useError(), eventResult: useEvent()}; + }, + { + wrapper: ({children}) => ( + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + ), + }, + ); + + it('이름과 비밀번호를 받아 새로운 이벤트를 생성한다.', async () => { + const {result} = initializeProvider(); + + await act(async () => { + expect( + await result.current.eventResult.createNewEvent({eventName: '테스트이름', password: VALID_PASSWORD_FOR_TEST}), + ); + }); + + await act(async () => { + expect(result.current.errorResult.error).toBe(null); + }); + }); + + it(`이름 길이가 ${VALID_EVENT_NAME_LENGTH_IN_SERVER.min} ~ ${VALID_EVENT_NAME_LENGTH_IN_SERVER.max}사이가 아닌 경우 이벤트를 생성할 수 없다.`, async () => { + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.eventResult.createNewEvent({eventName: '', password: VALID_PASSWORD_FOR_TEST})); + }); + + await act(async () => { + expect(result.current.errorResult.error?.errorCode).toBe('EVENT_NAME_LENGTH_INVALID'); + }); + }); + + it(`비밀번호가 ${PASSWORD_LENGTH}자리수가 아닌 경우 이벤트를 생성할 수 없다`, async () => { + const {result} = initializeProvider(); + + await act(async () => { + expect(await result.current.eventResult.createNewEvent({eventName: '테스트이름', password: 1})); + }); + + await act(async () => { + expect(result.current.errorResult.error?.errorCode).toBe('EVENT_PASSWORD_FORMAT_INVALID'); + }); + }); +}); diff --git a/client/src/hooks/useEvent.tsx b/client/src/hooks/useEvent/useEvent.tsx similarity index 89% rename from client/src/hooks/useEvent.tsx rename to client/src/hooks/useEvent/useEvent.tsx index 13aee0b56..736476e52 100644 --- a/client/src/hooks/useEvent.tsx +++ b/client/src/hooks/useEvent/useEvent.tsx @@ -1,6 +1,5 @@ import {RequestPostNewEvent, ResponsePostNewEvent, requestPostNewEvent} from '@apis/request/event'; - -import {useFetch} from '@apis/useFetch'; +import {useFetch} from '@hooks/useFetch/useFetch'; const useEvent = () => { const {fetch} = useFetch(); diff --git a/client/src/hooks/useFetch/useFetch.test.tsx b/client/src/hooks/useFetch/useFetch.test.tsx new file mode 100644 index 000000000..253d60b6e --- /dev/null +++ b/client/src/hooks/useFetch/useFetch.test.tsx @@ -0,0 +1,154 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {act} from 'react'; + +import FetchError from '@errors/FetchError'; + +import {requestPostWithoutResponse} from '@apis/fetcher'; + +import {captureError} from '@utils/captureError'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; + +import {ErrorProvider, useError} from '../../ErrorProvider'; + +import {useFetch} from './useFetch'; + +describe('useFetch', () => { + const initializeProvider = () => + renderHook( + () => { + return {errorResult: useError(), fetchResult: useFetch()}; + }, + { + wrapper: ({children}) => ( + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + ), + }, + ); + + describe('요청이 성공하는 경우', () => { + it('요청이 성공했다면 그대로 api response body를 반환한다.', async () => { + const {result} = initializeProvider(); + const mockQueryFunction = jest.fn().mockResolvedValue('mocked data'); + + let data; + + await act(async () => { + data = await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); + }); + + expect(data).toBe('mocked data'); + }); + + it('onSuccess 콜백을 넘겨준 경우 콜백을 실행한다.', async () => { + const {result} = initializeProvider(); + const mockQueryFunction = jest.fn().mockResolvedValue('mocked data'); + const onSuccess = jest.fn(); + + await act(async () => { + await result.current.fetchResult.fetch({queryFunction: mockQueryFunction, onSuccess}); + }); + + expect(onSuccess).toHaveBeenCalled(); + }); + }); + + describe('요청이 실패하는 경우', () => { + describe('발생한 에러가 Error 인스턴스인 경우', () => { + const errorThrowFunction = () => requestPostWithoutResponse({endpoint: '/throw-handle-error'}); + + it('FetchError가 발생하면 해당 에러의 errorBody를 사용해 상태를 저장한다.', async () => { + const {result} = initializeProvider(); + const fetchError = new FetchError({ + errorBody: {errorCode: 'UNHANDLED', message: 'Fetch error occurred'}, + name: 'UNHANDLED', + message: 'Fetch error occurred', + requestBody: '', + status: 400, + endpoint: '', + method: 'POST', + }); + const mockQueryFunction = jest.fn().mockRejectedValue(fetchError); + + await act(async () => { + await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); + }); + + await waitFor(() => { + expect(result.current.errorResult.error?.errorCode).toBe('UNHANDLED'); + expect(result.current.errorResult.error?.message).toBe('Fetch error occurred'); + }); + }); + + it('일반 Error가 발생하면 해당 에러의 name과 message를 사용해 상태를 저장한다.', async () => { + const {result} = initializeProvider(); + const mockError = new Error('일반 에러 발생'); + const mockQueryFunction = jest.fn().mockRejectedValue(mockError); + + try { + await act(async () => { + await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); + }); + } catch (error) { + // 에러 바운더리로 보내지는 에러라서 throw하는데 이를 받아줄 에러 바운더리를 호출하지 않았으므로 catch문에서 별다른 로직을 작성하지 않음 + } + + await waitFor(() => { + expect(result.current.errorResult.error?.errorCode).toBe('Error'); + expect(result.current.errorResult.error?.message).toBe('일반 에러 발생'); + }); + }); + + it('onError 콜백을 넘겨준 경우 onError를 실행한다.', async () => { + const {result} = initializeProvider(); + const onError = jest.fn(); + + await act(async () => { + await result.current.fetchResult.fetch({queryFunction: errorThrowFunction, onError}); + }); + + expect(onError).toHaveBeenCalled(); + }); + + it('에러가 발생하면 로그를 보낸다.', async () => { + const {result} = initializeProvider(); + + await act(async () => { + await result.current.fetchResult.fetch({queryFunction: errorThrowFunction}); + }); + + expect(captureError).toHaveBeenCalled(); + }); + }); + + describe('발생한 에러가 Error 인스턴스가 아닌 경우', () => { + const mockQueryFunction = jest.fn().mockRejectedValue('unexpected error'); + + it(`에러가 발생하면 그 에러를 던진다.`, async () => { + const {result} = initializeProvider(); + + // 에러가 발생하고 에러를 던지는지 확인 + await expect( + act(async () => { + await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); + }), + ).rejects.toThrow(new Error(UNKNOWN_ERROR)); + }); + + it('에러가 발생하면 로그를 보낸다.', async () => { + const {result} = initializeProvider(); + + await expect( + act(async () => { + await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); + }), + ).rejects.toThrow(new Error(UNKNOWN_ERROR)); + + expect(captureError).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/client/src/hooks/useFetch/useFetch.ts b/client/src/hooks/useFetch/useFetch.ts new file mode 100644 index 000000000..2d034fa5e --- /dev/null +++ b/client/src/hooks/useFetch/useFetch.ts @@ -0,0 +1,64 @@ +import {useState} from 'react'; +import {useNavigate} from 'react-router-dom'; + +import FetchError from '@errors/FetchError'; + +import {captureError} from '@utils/captureError'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; + +import {useError} from '../../ErrorProvider'; + +type FetchProps<T> = { + queryFunction: () => Promise<T>; + onSuccess?: () => void; + onError?: () => void; +}; + +export const useFetch = () => { + const {setError, clearError} = useError(); + const [loading, setLoading] = useState(false); + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); + + const fetch = async <T>({queryFunction, onSuccess, onError}: FetchProps<T>): Promise<T> => { + setLoading(true); + + clearError(); + try { + const result = await queryFunction(); + + if (onSuccess) { + onSuccess(); + } + + return result; + } catch (error) { + if (error instanceof Error) { + const errorBody = + error instanceof FetchError ? error.errorBody : {errorCode: error.name, message: error.message}; + + setError(errorBody); + + if (onError) { + onError(); + } + + captureError(error, navigate, eventId); + } else { + setError({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); + captureError(new Error(UNKNOWN_ERROR), navigate, eventId); + + // 에러를 throw 해 에러 바운더리로 보냅니다. 따라서 에러 이름은 중요하지 않음 + throw new Error(UNKNOWN_ERROR); + } + } finally { + setLoading(false); + } + + return {} as T; + }; + + return {loading, fetch}; +}; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 925f591e8..d7e2e40c3 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -5,15 +5,15 @@ import {useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; import {requestDeleteBillAction, requestPutBillAction} from '@apis/request/bill'; -import {useStepList} from '@hooks/useStepList'; import {BillInputType, InputPair} from '@hooks/useDynamicBillActionInput'; -import {useFetch} from '@apis/useFetch'; - import getEventIdByUrl from '@utils/getEventIdByUrl'; import {ERROR_MESSAGE} from '@constants/errorMessage'; +import {useStepList} from './useStepList/useStepList'; +import {useFetch} from './useFetch/useFetch'; + const usePutAndDeleteBillAction = ( initialValue: InputPair, validateFunc: (inputPair: Bill) => ValidateResult, diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index ed7df41a3..04b334101 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -1,8 +1,7 @@ import {useEffect, useState} from 'react'; import {requestGetCurrentInMemberList} from '@apis/request/member'; - -import {useFetch} from '@apis/useFetch'; +import {useFetch} from '@hooks/useFetch/useFetch'; import getEventIdByUrl from '@utils/getEventIdByUrl'; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx new file mode 100644 index 000000000..2688a9a04 --- /dev/null +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx @@ -0,0 +1,34 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; + +import reportListJson from '../../mocks/reportList.json'; +import {ErrorProvider} from '../../ErrorProvider'; + +import useSearchMemberReportList from './useSearchMemberReportList'; + +describe('useSearchMemberReportList', () => { + const initializeProvider = (name: string) => + renderHook(() => useSearchMemberReportList({name}), { + wrapper: ({children}) => ( + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + ), + }); + + it('빈 값을 검색한다면 검색 목록은 비어있다.', async () => { + const {result} = initializeProvider(''); + + await waitFor(() => expect(result.current.memberReportSearchList).toStrictEqual(reportListJson)); + }); + + it('검색어의 일부와 일치하는 이름이 있다면 해당 이름을 목록에 반환한다.', async () => { + const keyword = '소'; + const {result} = initializeProvider(keyword); + const expectedMemberReportSearchList = reportListJson.filter(memberReport => memberReport.name.includes(keyword)); + + await waitFor(() => { + expect(result.current.memberReportSearchList).toStrictEqual(expectedMemberReportSearchList); + }); + }); +}); diff --git a/client/src/hooks/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx similarity index 96% rename from client/src/hooks/useSearchMemberReportList.tsx rename to client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx index ccbc5358f..98f682dc2 100644 --- a/client/src/hooks/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -4,10 +4,10 @@ import {useEffect, useState} from 'react'; import {requestGetMemberReportList} from '@apis/request/report'; -import {useFetch} from '@apis/useFetch'; - import getEventIdByUrl from '@utils/getEventIdByUrl'; +import {useFetch} from '../useFetch/useFetch'; + type UseSearchMemberReportListParams = { name: string; }; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index 69fd4ba96..8811996cf 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -3,13 +3,11 @@ import {useEffect, useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; import {MemberChange, requestDeleteAllMemberList, requestPutAllMemberList} from '@apis/request/member'; -import {useFetch} from '@apis/useFetch'; - import isArraysEqual from '@utils/isArraysEqual'; import getEventIdByUrl from '@utils/getEventIdByUrl'; -import {useStepList} from './useStepList'; -import useInput from './useInput'; +import {useStepList} from './useStepList/useStepList'; +import {useFetch} from './useFetch/useFetch'; interface UseSetAllMemberListProps { validateFunc: (name: string) => ValidateResult; @@ -17,37 +15,18 @@ interface UseSetAllMemberListProps { handleCloseAllMemberListModal: () => void; } -interface UseSetAllMemberListReturns { - editedAllMemberList: string[]; - canSubmit: boolean; - errorMessage: string; - errorIndexList: number[]; - handleNameChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; - handleClickDeleteButton: (index: number) => Promise<void>; - handlePutAllMemberList: () => Promise<void>; -} - const useSetAllMemberList = ({ validateFunc, allMemberList, handleCloseAllMemberListModal, -}: UseSetAllMemberListProps): UseSetAllMemberListReturns => { - const initialInputList = allMemberList.map((name, index) => ({index, value: name})); - const { - inputList, - errorMessage, - errorIndexList, - canSubmit, - handleChange, - setInputList: setEditedAllMemberList, - setCanSubmit, - } = useInput({validateFunc, initialInputList}); - +}: UseSetAllMemberListProps) => { + const [editedAllMemberList, setEditedAllMemberList] = useState<string[]>(allMemberList); + const [errorMessage, setErrorMessage] = useState(''); + const [errorIndexList, setErrorIndexList] = useState<number[]>([]); + const [canSubmit, setCanSubmit] = useState(false); const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); - const editedAllMemberList = inputList.map(input => input.value); - const {refreshStepList} = useStepList(); const eventId = getEventIdByUrl(); const {fetch} = useFetch(); @@ -58,8 +37,35 @@ const useSetAllMemberList = ({ const handleNameChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; + const {isValid, errorMessage: validationResultMessage} = validateFunc(value); + + if (isValid && value.length !== 0) { + setErrorMessage(''); + + setEditedAllMemberList(prev => { + const newList = [...prev]; + newList[index] = value; + return newList; + }); - handleChange(index, value); + setErrorIndexList(prev => prev.filter(i => i !== index)); + + setCanSubmit(true); + } else if (value.length === 0) { + setErrorMessage(''); + + setEditedAllMemberList(prev => { + const newList = [...prev]; + newList[index] = value; + return newList; + }); + + changeErrorIndex(index); + } else { + setErrorMessage(validationResultMessage ?? ''); + + changeErrorIndex(index); + } }; const handleClickDeleteButton = async (index: number) => { @@ -103,6 +109,15 @@ const useSetAllMemberList = ({ }); }; + const changeErrorIndex = (index: number) => { + setErrorIndexList(prev => { + if (!prev.includes(index)) { + return [...prev, index]; + } + return prev; + }); + }; + return { editedAllMemberList, canSubmit, diff --git a/client/src/hooks/useSetPassword.ts b/client/src/hooks/useSetPassword.ts index 8e8cf9c8c..7b24e70dc 100644 --- a/client/src/hooks/useSetPassword.ts +++ b/client/src/hooks/useSetPassword.ts @@ -2,11 +2,10 @@ import {useState} from 'react'; import validateEventPassword from '@utils/validate/validateEventPassword'; -import {useFetch} from '@apis/useFetch'; - import RULE from '@constants/rule'; -import useEvent from './useEvent'; +import {useFetch} from './useFetch/useFetch'; +import useEvent from './useEvent/useEvent'; const useSetPassword = (eventName: string) => { const {fetch} = useFetch(); diff --git a/client/src/hooks/useStepList/useStepList.test.tsx b/client/src/hooks/useStepList/useStepList.test.tsx new file mode 100644 index 000000000..81963b73a --- /dev/null +++ b/client/src/hooks/useStepList/useStepList.test.tsx @@ -0,0 +1,111 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {act} from 'react'; + +import {Bill} from 'types/serviceType'; + +import StepListProvider, {useStepList} from '../useStepList/useStepList'; +import stepListJson from '../../mocks/stepList.json'; +import {ErrorProvider} from '../../ErrorProvider'; + +const stepListMockData = stepListJson; + +describe('useStepList', () => { + const initializeProvider = () => + renderHook( + () => { + return { + stepListResult: useStepList(), + }; + }, + { + wrapper: ({children}) => ( + <MemoryRouter> + <ErrorProvider> + <StepListProvider>{children}</StepListProvider> + </ErrorProvider> + </MemoryRouter> + ), + }, + ); + + const getMemberNameList = () => + stepListJson + .filter(({type}) => type !== 'BILL') + .map(({actions}) => actions.map(({name}) => name)) + .flat(); + + it('처음 호출하면 stepList 값을 요청해 받아온다.', async () => { + const {result} = initializeProvider(); + + await waitFor(() => expect(result.current.stepListResult.stepList).toStrictEqual(stepListMockData)); + }); + + it('처음 호출하면 모든 멤버의 목록을 요청해 받아온다.', async () => { + const {result} = initializeProvider(); + const allMemberList = getMemberNameList(); + + await waitFor(() => expect(result.current.stepListResult.allMemberList).toStrictEqual(allMemberList)); + }); + + it('지출 내역의 총액을 계산한다.', async () => { + const {result} = initializeProvider(); + const totalPrice = stepListJson.reduce((sum, {type, actions}) => { + if (type === 'BILL') { + return sum + actions.reduce((sum, {price}) => sum + price!, 0); + } + return sum; + }, 0); + + // 값이 세팅되기까지 대기하기 위함. 그래서 아래 한 줄 없으면 에러남 + await waitFor(() => expect(result.current.stepListResult.stepList).toStrictEqual(stepListMockData)); + + expect(result.current.stepListResult.getTotalPrice()).toStrictEqual(totalPrice); + }); + + it('들어옴 멤버를 추가한다.', async () => { + const {result} = initializeProvider(); + const type = 'IN'; + const memberNameList = ['망고젤리', '리치젤리']; + + const prevNameList = getMemberNameList(); + const updatedNameList = [...prevNameList, ...memberNameList]; + + await act(async () => result.current.stepListResult.updateMemberList({type, memberNameList})); + + expect(result.current.stepListResult.allMemberList).toStrictEqual(updatedNameList); + }); + + it('지출 내역을 새로 추가한다.', async () => { + const {result} = initializeProvider(); + const billList: Bill[] = [ + {title: '마라', price: 20000}, + {title: '엽떡', price: 1000}, + ]; + + const updatedStepList = [ + ...stepListJson, + { + type: 'BILL', + stepName: '밥스카이', + members: [], + actions: billList.map(({title, price}) => ({ + actionId: 999, + name: title, + price, + sequence: 999, + })), + }, + ]; + + await act(async () => result.current.stepListResult.addBill(billList, () => {})); + + expect(result.current.stepListResult.stepList).toStrictEqual(updatedStepList); + }); + + it('provider안에서 호출되지 않으면 에러를 던진다.', () => { + expect(() => { + const {result} = renderHook(() => useStepList()); + }).toThrow('useStepList는 StepListProvider 내에서 사용되어야 합니다.'); + }); +}); diff --git a/client/src/hooks/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx similarity index 92% rename from client/src/hooks/useStepList.tsx rename to client/src/hooks/useStepList/useStepList.tsx index 4898925a6..ffc05c59d 100644 --- a/client/src/hooks/useStepList.tsx +++ b/client/src/hooks/useStepList/useStepList.tsx @@ -6,10 +6,10 @@ import {requestPostBillList} from '@apis/request/bill'; import {requestGetAllMemberList, requestPostMemberList} from '@apis/request/member'; import {requestGetStepList} from '@apis/request/stepList'; -import {useFetch} from '@apis/useFetch'; - import getEventIdByUrl from '@utils/getEventIdByUrl'; +import {useFetch} from '../useFetch/useFetch'; + interface StepListContextProps { stepList: (BillStep | MemberStep)[]; allMemberList: string[]; @@ -39,13 +39,9 @@ const StepListProvider = ({children}: PropsWithChildren) => { }, []); const updateMemberList = async ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => { - try { - await fetch({queryFunction: () => requestPostMemberList({eventId, type, memberNameList})}); + await fetch({queryFunction: () => requestPostMemberList({eventId, type, memberNameList})}); - refreshStepList(); - } catch (error) { - alert(error); - } + refreshStepList(); }; const getAllMemberList = async () => { diff --git a/client/src/mocks/handlers.ts b/client/src/mocks/handlers.ts index c5b88a98b..f20429263 100644 --- a/client/src/mocks/handlers.ts +++ b/client/src/mocks/handlers.ts @@ -1,12 +1,7 @@ -import {http, HttpResponse} from 'msw'; +import {authHandler} from './handlers/authHandlers'; +import {eventHandler} from './handlers/eventHandlers'; +import {reportHandlers} from './handlers/reportHandlers'; +import {stepListHandler} from './handlers/stepListHandler'; +import {testHandler} from './handlers/testHandlers'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; - -export const handlers = [ - http.post(`${process.env.API_BASE_URL!}${TEMP_PREFIX}`, ({request}) => { - return HttpResponse.json( - {errorCode: 'ACTION_NOT_FOUND', message: 'msw모킹함수의 에러메세지입니다.'}, - {status: 404}, - ); - }), -]; +export const handlers = [...authHandler, ...eventHandler, ...testHandler, ...stepListHandler, ...reportHandlers]; diff --git a/client/src/mocks/handlers/authHandlers.ts b/client/src/mocks/handlers/authHandlers.ts new file mode 100644 index 000000000..31532eea7 --- /dev/null +++ b/client/src/mocks/handlers/authHandlers.ts @@ -0,0 +1,104 @@ +import {HttpResponse, http} from 'msw'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import {PASSWORD_LENGTH} from '@constants/password'; + +import { + EXPIRED_TOKEN_FOR_TEST, + FORBIDDEN_TOKEN_FOR_TEST, + VALID_PASSWORD_FOR_TEST, + VALID_TOKEN_FOR_TEST, +} from '@mocks/validValueForTest'; + +type PostLoginParams = { + eventId: string; +}; + +type PostLoginRequestBody = { + password: string; +}; + +export const authHandler = [ + http.post(`${TEMP_PREFIX}/:eventId/auth`, ({cookies}) => { + const token = cookies['eventToken']; + + if (token === VALID_TOKEN_FOR_TEST) { + return new HttpResponse(null, { + status: 200, + }); + } else if (token === EXPIRED_TOKEN_FOR_TEST) { + return HttpResponse.json( + { + errorCode: 'TOKEN_EXPIRED', + message: '만료된 토큰입니다.', + }, + {status: 401}, + ); + } else if (token === FORBIDDEN_TOKEN_FOR_TEST) { + return HttpResponse.json( + { + errorCode: 'FORBIDDEN', + message: '접근할 수 없는 행사입니다.', + }, + {status: 401}, + ); + } else if (token === undefined) { + return HttpResponse.json( + { + errorCode: 'TOKEN_NOT_FOUND', + message: '토큰이 존재하지 않습니다.', + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + errorCode: 'TOKEN_INVALID', + message: '유효하지 않은 토큰입니다.', + }, + {status: 401}, + ); + } + }), + + // TODO: (@weadie) any를 사용한 이유는.. any가 있는 위치가 이 handler함수의 responseBody타입인데, 아래처럼 return하는 것에 대한 예시가 공문에 없습니다. 함수를 까면 되겠지만 시간이 아깝고 알아낸다고 해서 이 responseBody 타입은 사실 중요한게 아니기 때문에 any로 대체하였습니다. + http.post<PostLoginParams, PostLoginRequestBody, any, `${typeof TEMP_PREFIX}/:eventId/login`>( + `${TEMP_PREFIX}/:eventId/login`, + async ({request}) => { + const {password} = await request.json(); + + if (password === String(VALID_PASSWORD_FOR_TEST)) { + return new HttpResponse(null, { + headers: { + 'Set-Cookie': 'eventToken=abc-123', + }, + }); + } else if (password.length < PASSWORD_LENGTH) { + return HttpResponse.json( + { + errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', + message: `비밀번호는 ${PASSWORD_LENGTH}자리 숫자만 가능합니다.`, + }, + {status: 401}, + ); + } else if (password === undefined) { + return HttpResponse.json( + { + errorCode: 'REQUEST_EMPTY', + message: '비밀번호는 공백일 수 없습니다.', + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + errorCode: 'PASSWORD_INVALID', + message: '비밀번호가 일치하지 않습니다.', + }, + {status: 401}, + ); + } + }, + ), +]; diff --git a/client/src/mocks/handlers/eventHandlers.ts b/client/src/mocks/handlers/eventHandlers.ts new file mode 100644 index 000000000..351993e16 --- /dev/null +++ b/client/src/mocks/handlers/eventHandlers.ts @@ -0,0 +1,55 @@ +import {HttpResponse, http} from 'msw'; + +import {RequestPostNewEvent, ResponsePostNewEvent} from '@apis/request/event'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import {PASSWORD_LENGTH} from '@constants/password'; + +import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; + +type ErrorResponseBody = { + errorCode: string; + message: string; +}; + +export const eventHandler = [ + http.post<any, RequestPostNewEvent, ResponsePostNewEvent | ErrorResponseBody, `${typeof TEMP_PREFIX}`>( + `${TEMP_PREFIX}`, + async ({request}) => { + const {eventName, password} = await request.json(); + + if (String(password).length < PASSWORD_LENGTH) { + return HttpResponse.json( + { + errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', + message: '비밀번호는 4자리 숫자만 가능합니다.', + }, + {status: 401}, + ); + } else if ( + eventName.length < VALID_EVENT_NAME_LENGTH_IN_SERVER.min || + eventName.length > VALID_EVENT_NAME_LENGTH_IN_SERVER.max + ) { + return HttpResponse.json( + { + errorCode: 'EVENT_NAME_LENGTH_INVALID', + message: `행사 이름은 2자 이상 30자 이하만 입력 가능합니다. 입력한 이름 길이 : ${eventName.length}`, + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + eventId: 'eventId', + }, + { + headers: { + 'Set-Cookie': 'eventToken=abc-123', + }, + }, + ); + } + }, + ), +]; diff --git a/client/src/mocks/handlers/reportHandlers.ts b/client/src/mocks/handlers/reportHandlers.ts new file mode 100644 index 000000000..6b256d7d3 --- /dev/null +++ b/client/src/mocks/handlers/reportHandlers.ts @@ -0,0 +1,13 @@ +import {HttpResponse, http} from 'msw'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import reportListJson from '../reportList.json'; + +export const reportHandlers = [ + http.get(`${TEMP_PREFIX}/:eventId/actions/reports`, () => { + return HttpResponse.json({ + reports: reportListJson, + }); + }), +]; diff --git a/client/src/mocks/handlers/stepListHandler.ts b/client/src/mocks/handlers/stepListHandler.ts new file mode 100644 index 000000000..e771d71c0 --- /dev/null +++ b/client/src/mocks/handlers/stepListHandler.ts @@ -0,0 +1,111 @@ +import {HttpResponse, http} from 'msw'; + +import {Bill, MemberType, StepList} from 'types/serviceType'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import stepListJson from '../stepList.json'; + +type StepListResponseBody = { + step: StepList; +}; + +type PostMemberListRequestBody = { + members: string[]; + status: MemberType; +}; + +type PostBillListRequestBody = { + actions: Bill[]; +}; + +let stepListMockData = stepListJson; + +export const stepListHandler = [ + http.get<any, StepListResponseBody, any, `${typeof TEMP_PREFIX}/:eventId/actions`>( + `${TEMP_PREFIX}/:eventId/actions`, + () => { + return HttpResponse.json({ + steps: stepListMockData, + }); + }, + ), + + http.get(`${TEMP_PREFIX}/:eventId/members`, () => { + return HttpResponse.json({ + memberNames: stepListMockData + .filter(({type}) => type !== 'BILL') + .map(({actions}) => actions.map(({name}) => name)) + .flat(), + }); + }), + + http.delete<{actionId: string}>(`${TEMP_PREFIX}/:eventId/member-actions/:actionId`, ({params}) => { + const {actionId} = params; + + if (parseInt(actionId) === 999) { + return HttpResponse.json( + { + errorCode: 'MEMBER_ACTION_STATUS_INVALID', + message: 'actionId는 999일 수 없습니다.(고의로 만든 에러임)', + }, + {status: 401}, + ); + } else { + return HttpResponse.json({ + status: 200, + }); + } + }), + + http.post<any, PostMemberListRequestBody, any, `${typeof TEMP_PREFIX}/:eventId/member-actions`>( + `${TEMP_PREFIX}/:eventId/member-actions`, + async ({request}) => { + const {members, status} = await request.json(); + stepListMockData = [ + ...stepListJson, + { + type: status, + stepName: '영차영차', + members: status === 'IN' ? members : [], + actions: members.map(name => ({ + actionId: 999, + name, + price: 0, + sequence: 999, + })), + }, + ]; + + return HttpResponse.json({ + status: 200, + }); + }, + ), + + http.post<any, PostBillListRequestBody, any, `${typeof TEMP_PREFIX}/:eventId/bill-actions`>( + `${TEMP_PREFIX}/:eventId/bill-actions`, + async ({request}) => { + const {actions} = await request.json(); + + stepListMockData = [ + ...stepListJson, + { + type: 'BILL', + stepName: '밥스카이', + members: [], + actions: actions.map(({title, price}) => ({ + actionId: 999, + name: title, + price, + sequence: 999, + })), + }, + ]; + + return HttpResponse.json({ + status: 200, + }); + }, + ), +]; diff --git a/client/src/mocks/handlers/testHandlers.ts b/client/src/mocks/handlers/testHandlers.ts new file mode 100644 index 000000000..fda96a1f0 --- /dev/null +++ b/client/src/mocks/handlers/testHandlers.ts @@ -0,0 +1,23 @@ +import {HttpResponse, http} from 'msw'; + +export const testHandler = [ + http.post(`/throw-handle-error`, () => { + return HttpResponse.json( + { + errorCode: 'TOKEN_NOT_FOUND', + message: '핸들링되는 테스트 에러입니다.', + }, + {status: 400}, + ); + }), + + http.post(`/throw-unhandle-error`, () => { + return HttpResponse.json( + { + errorCode: 'strange error', + message: '핸들링이 안되는 테스트 에러입니다.', + }, + {status: 500}, + ); + }), +]; diff --git a/client/src/mocks/invalidMemberStepList.json b/client/src/mocks/invalidMemberStepList.json new file mode 100644 index 000000000..5c4d7fee1 --- /dev/null +++ b/client/src/mocks/invalidMemberStepList.json @@ -0,0 +1,91 @@ +[ + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 999, + "name": "망쵸", + "price": null, + "sequence": 1 + }, + { + "actionId": 2, + "name": "백호", + "price": null, + "sequence": 2 + } + ] + }, + { + "type": "BILL", + "stepName": "1차", + "members": ["망쵸", "백호"], + "actions": [ + { + "actionId": 3, + "name": "감자탕", + "price": 10000, + "sequence": 3 + }, + { + "actionId": 4, + "name": "인생네컷", + "price": 10000, + "sequence": 4 + } + ] + }, + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 5, + "name": "소하", + "price": null, + "sequence": 5 + }, + { + "actionId": 6, + "name": "웨디", + "price": null, + "sequence": 6 + } + ] + }, + { + "type": "BILL", + "stepName": "2차", + "members": ["소하", "웨디"], + "actions": [ + { + "actionId": 9, + "name": "노래방", + "price": 20000, + "sequence": 10 + } + ] + }, + { + "type": "OUT", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 7, + "name": "망쵸", + "price": null, + "sequence": 7 + }, + { + "actionId": 8, + "name": "백호", + "price": null, + "sequence": 8 + } + ] + } +] diff --git a/client/src/mocks/memberActionStepList.json b/client/src/mocks/memberActionStepList.json new file mode 100644 index 000000000..578dfdd11 --- /dev/null +++ b/client/src/mocks/memberActionStepList.json @@ -0,0 +1,21 @@ +[ + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 1, + "name": "망쵸", + "price": null, + "sequence": 1 + }, + { + "actionId": 2, + "name": "백호", + "price": null, + "sequence": 2 + } + ] + } +] diff --git a/client/src/mocks/reportList.json b/client/src/mocks/reportList.json new file mode 100644 index 000000000..a663eb9fd --- /dev/null +++ b/client/src/mocks/reportList.json @@ -0,0 +1,18 @@ +[ + { + "name": "소하", + "price": 40000 + }, + { + "name": "감자", + "price": 20000 + }, + { + "name": "쿠키", + "price": 40000 + }, + { + "name": "토다리", + "price": 0 + } +] diff --git a/client/src/mocks/server.ts b/client/src/mocks/server.ts new file mode 100644 index 000000000..157a298e0 --- /dev/null +++ b/client/src/mocks/server.ts @@ -0,0 +1,5 @@ +import {setupServer} from 'msw/node'; + +import {handlers} from './handlers'; + +export const server = setupServer(...handlers); diff --git a/client/src/mocks/serverConstants.ts b/client/src/mocks/serverConstants.ts new file mode 100644 index 000000000..1063a2f75 --- /dev/null +++ b/client/src/mocks/serverConstants.ts @@ -0,0 +1,4 @@ +export const VALID_EVENT_NAME_LENGTH_IN_SERVER = { + min: 2, + max: 30, +}; diff --git a/client/src/mocks/validValueForTest.ts b/client/src/mocks/validValueForTest.ts new file mode 100644 index 000000000..31f587134 --- /dev/null +++ b/client/src/mocks/validValueForTest.ts @@ -0,0 +1,4 @@ +export const VALID_PASSWORD_FOR_TEST = 1111; +export const VALID_TOKEN_FOR_TEST = 'valid-token'; +export const FORBIDDEN_TOKEN_FOR_TEST = 'forbidden-token'; +export const EXPIRED_TOKEN_FOR_TEST = 'expired-token'; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index a3572d24d..ecef5d710 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -1,4 +1,4 @@ -import {useEffect, useState} from 'react'; +import {useEffect} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; @@ -6,6 +6,7 @@ import useSetPassword from '@hooks/useSetPassword'; import RULE from '@constants/rule'; import {ROUTER_URLS} from '@constants/routerUrls'; +import {PASSWORD_LENGTH} from '@constants/password'; const SetEventPasswordPage = () => { const navigate = useNavigate(); @@ -32,7 +33,10 @@ const SetEventPasswordPage = () => { <TopNav> <Back /> </TopNav> - <Title title="행사 비밀번호 설정" description="행사 관리에 필요한 4 자리의 숫자 비밀번호를 입력해 주세요." /> + <Title + title="행사 비밀번호 설정" + description={`행사 관리에 필요한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} + /> <form onSubmit={onSubmit} style={{padding: '0 1rem'}}> <LabelInput labelText="비밀번호" diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index ac0d85c05..7ece41751 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -4,26 +4,25 @@ import {useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; import {ModalBasedOnMemberCount} from '@components/Modal/index'; - -import {useStepList} from '@hooks/useStepList'; -import useAuth from '@hooks/useAuth'; +import {useStepList} from '@hooks/useStepList/useStepList'; +import useAuth from '@hooks/useAuth/useAuth'; import {EventPageContextProps} from '../EventPageLayout'; import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; const AdminPage = () => { - const {eventId, eventName} = useOutletContext<EventPageContextProps>(); + const {eventName} = useOutletContext<EventPageContextProps>(); const [isOpenFixedButtonBottomSheet, setIsOpenFixedBottomBottomSheet] = useState(false); const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); const {getTotalPrice, allMemberList} = useStepList(); - const {postAuthentication} = useAuth(); + const {checkAuthentication} = useAuth(); useEffect(() => { const postAuth = async () => { - await postAuthentication({eventId: eventId}); + await checkAuthentication(); }; postAuth(); diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index d9c8c2128..721165f8e 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -3,14 +3,15 @@ import {useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Switch} from 'haengdong-design'; import validateEventPassword from '@utils/validate/validateEventPassword'; +import useAuth from '@hooks/useAuth/useAuth'; -import useAuth from '@hooks/useAuth'; import useNavSwitch from '@hooks/useNavSwitch'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import RULE from '@constants/rule'; import {ROUTER_URLS} from '@constants/routerUrls'; +import {PASSWORD_LENGTH} from '@constants/password'; const EventLoginPage = () => { const [password, setPassword] = useState(''); @@ -19,13 +20,13 @@ const EventLoginPage = () => { const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); const eventId = getEventIdByUrl(); - const {postLogin} = useAuth(); + const {loginUser} = useAuth(); const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); try { - await postLogin({eventId, password}); + await loginUser({password}); navigate(`${ROUTER_URLS.event}/${eventId}/admin`); } catch (error) { setErrorMessage('잘못된 비밀번호에요'); @@ -55,7 +56,7 @@ const EventLoginPage = () => { </TopNav> <Title title="행사 비밀번호 입력" - description="관리를 위해선 비밀번호가 필요해요. 행사 생성 시 설정한 4 자리의 숫자 비밀번호를 입력해 주세요." + description={`관리를 위해선 비밀번호가 필요해요. 행사 생성 시 설정한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} /> <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> <LabelInput diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 771422087..5aa61a570 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -5,9 +5,9 @@ import CopyToClipboard from 'react-copy-to-clipboard'; import {useToast} from '@components/Toast/ToastProvider'; import {requestGetEventName} from '@apis/request/event'; +import StepListProvider from '@hooks/useStepList/useStepList'; import useNavSwitch from '@hooks/useNavSwitch'; -import StepListProvider from '@hooks/useStepList'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 1d7561a0c..875bb4ff6 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -1,12 +1,9 @@ import {Tab, Tabs, Title} from 'haengdong-design'; -import {useEffect, useState} from 'react'; import {useOutletContext} from 'react-router-dom'; import MemberReportList from '@components/MemberReportList/MemberReportList'; import StepList from '@components/StepList/StepList'; -import {requestGetEventName} from '@apis/request/event'; - -import {useStepList} from '@hooks/useStepList'; +import {useStepList} from '@hooks/useStepList/useStepList'; import {EventPageContextProps} from '../EventPageLayout'; diff --git a/client/src/utils/captureError.ts b/client/src/utils/captureError.ts new file mode 100644 index 000000000..d0af34729 --- /dev/null +++ b/client/src/utils/captureError.ts @@ -0,0 +1,57 @@ +import {NavigateFunction} from 'react-router-dom'; + +import FetchError from '@errors/FetchError'; +import {ServerError} from 'ErrorProvider'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +import sendLogToSentry from './sendLogToSentry'; + +export const captureError = async (error: Error, navigate: NavigateFunction, eventId: string) => { + // prod 환경에서만 Sentry capture 실행 + if (process.env.NODE_ENV !== 'production') return; + + const errorBody: ServerError = + error instanceof FetchError ? error.errorBody : {message: error.message, errorCode: error.name}; + + switch (errorBody?.errorCode) { + case 'INTERNAL_SERVER_ERROR': + sendLogToSentry({error, errorBody, level: 'fatal'}); + break; + + case 'FORBIDDEN': + sendLogToSentry({error, errorBody}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; + + case 'TOKEN_INVALID': + sendLogToSentry({error, errorBody}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; + + case 'TOKEN_EXPIRED': + sendLogToSentry({error, errorBody}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; + + case 'TOKEN_NOT_FOUND': + sendLogToSentry({error, errorBody}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; + + // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 + case 'PASSWORD_INVALID': + sendLogToSentry({error, errorBody, level: 'debug'}); + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; + + // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 + case 'BILL_ACTION_PRICE_INVALID': + sendLogToSentry({error, errorBody, level: 'debug'}); + break; + + default: + sendLogToSentry({error, errorBody, level: 'fatal'}); + break; + } +}; diff --git a/client/src/utils/objectToQueryString.ts b/client/src/utils/objectToQueryString.ts new file mode 100644 index 000000000..cc40fb076 --- /dev/null +++ b/client/src/utils/objectToQueryString.ts @@ -0,0 +1,9 @@ +import {ObjectQueryParams} from '@apis/fetcher'; + +const objectToQueryString = (params: ObjectQueryParams): string => { + return Object.entries(params) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) + .join('&'); +}; + +export default objectToQueryString; diff --git a/client/tsconfig.json b/client/tsconfig.json index f409ed6f5..7c749b6f5 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -20,7 +20,7 @@ // "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "types": ["node", "cypress"], + "types": ["jest", "node", "cypress"], "esModuleInterop": true, "strictNullChecks": true, "strictFunctionTypes": true, @@ -48,5 +48,5 @@ "outDir": "./dist" }, "node": true, - "include": ["src", "cypress/**/*.ts"] + "include": ["src", "jest.config.ts", "jest.setup.ts", "cypress/**/*.ts"] } From 0173142d304c5e8277b0c1cf789fd366dac08519 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:58:39 +0900 Subject: [PATCH 168/273] =?UTF-8?q?refactor:=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EC=95=A1=EC=85=98=20=EC=82=AD=EC=A0=9C=20=ED=9B=85=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20(#383)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. --- .../AddBillActionListModalContent.tsx | 3 --- .../useDeleteMemberAction.test.tsx | 2 +- .../useDeleteMemberAction.tsx | 18 ++++++++---------- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index 0f11852af..e5165804e 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -17,7 +17,6 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList inputPairList, inputRefList, errorMessage, - errorIndexList, handleInputChange, getFilledInputPairList, deleteEmptyInputPairElementOnBlur, @@ -48,7 +47,6 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList onBlur={() => deleteEmptyInputPairElementOnBlur()} // TODO: (@weadie) 이 블러프롭이 내부적으로 index를 넘기고 있기 때문에 화살표 함수로 써야만하내요.. placeholder="지출 내역" ref={el => (inputRefList.current[index * 2] = el)} - isError={errorIndexList.includes(index)} /> <LabelGroupInput.Element elementKey={`${index}`} @@ -59,7 +57,6 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList onBlur={() => deleteEmptyInputPairElementOnBlur()} placeholder="금액" ref={el => (inputRefList.current[index * 2 + 1] = el)} - isError={errorIndexList.includes(index)} /> </div> ))} diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx index 9ca4d7bff..bb0809046 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -53,7 +53,7 @@ describe('useDeleteMemberAction', () => { expect(result.current.stepListResult.stepList).not.toStrictEqual([]); }); - await act(async () => { + act(() => { const memberAction = { actionId: 1, name: '망쵸', diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx index 265eafecd..323ee9be6 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx @@ -22,7 +22,7 @@ const useDeleteMemberAction = ({ showToastExistSameMemberFromAfterStep, }: UseDeleteMemberActionProps) => { const {stepList, refreshStepList} = useStepList(); - const [aliveActionList, setAliveActionList] = useState<MemberAction[]>(memberActionList); + const [deleteActionList, setDeleteActionList] = useState<MemberAction[]>([]); const eventId = getEventIdByUrl(); const {fetch} = useFetch(); @@ -34,20 +34,15 @@ const useDeleteMemberAction = ({ setIsBottomSheetOpened(false); }, onError: () => { - setAliveActionList(memberActionList); + setDeleteActionList([]); }, }); }; // TODO: (@cookie: 추후에 반복문으로 delete하는 것이 아니라 한 번에 모아서 delete 처리하기 (backend에 문의)) const deleteMemberActionList = async () => { - const aliveActionIdList = aliveActionList.map(({actionId}) => actionId); - const deleteMemberActionIdList = memberActionList - .filter(({actionId}) => !aliveActionIdList.includes(actionId)) - .map(({actionId}) => actionId); - - for (const deleteMemberActionId of deleteMemberActionIdList) { - await deleteMemberAction(deleteMemberActionId); + for (const {actionId} of deleteActionList) { + await deleteMemberAction(actionId); } }; @@ -66,7 +61,7 @@ const useDeleteMemberAction = ({ const addDeleteMemberAction = (memberAction: MemberAction) => { checkAlreadyExistMemberAction(memberAction, showToastAlreadyExistMemberAction); checkExistSameMemberFromAfterStep(memberAction, () => showToastExistSameMemberFromAfterStep(memberAction.name)); - setAliveActionList(prev => prev.filter(aliveMember => aliveMember.actionId !== memberAction.actionId)); + setDeleteActionList(prev => [...prev, memberAction]); }; const isExistSameMemberFromAfterStep = (memberAction: MemberAction) => { @@ -81,6 +76,9 @@ const useDeleteMemberAction = ({ return memberNameList.filter(member => member === memberAction.name).length >= 2; }; + const aliveActionList = memberActionList.filter( + memberAction => !deleteActionList.some(deleteAction => deleteAction.actionId === memberAction.actionId), + ); return {aliveActionList, deleteMemberActionList, addDeleteMemberAction}; }; From 7cac9f3ecd20542c2a7ace4d5e4cf5dcb7069f1f Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:58:58 +0900 Subject: [PATCH 169/273] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20(#385)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 --- client/src/hooks/useSetEventName.ts | 32 +++++++++++++++++++ .../CompleteCreateEventPage.tsx | 2 +- .../CreateEventPage/SetEventNamePage.tsx | 26 +++------------ .../CreateEventPage/SetEventPasswordPage.tsx | 2 +- 4 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 client/src/hooks/useSetEventName.ts diff --git a/client/src/hooks/useSetEventName.ts b/client/src/hooks/useSetEventName.ts new file mode 100644 index 000000000..b36820735 --- /dev/null +++ b/client/src/hooks/useSetEventName.ts @@ -0,0 +1,32 @@ +import {useState} from 'react'; + +import validateEventName from '@utils/validate/validateEventName'; + +const useSetEventName = () => { + const [eventName, setEventName] = useState(''); + const [errorMessage, setErrorMessage] = useState<string | null>(null); + const [canSubmit, setCanSubmit] = useState(false); + + const handleEventNameChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + const validation = validateEventName(newValue); + + setCanSubmit(newValue.length !== 0); + setErrorMessage(validation.errorMessage); + + if (validation.isValid) { + setEventName(newValue); + } else { + event.target.value = eventName; + } + }; + + return { + eventName, + errorMessage, + canSubmit, + handleEventNameChange, + }; +}; + +export default useSetEventName; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index d33f5b6e7..75d4ca7b2 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -22,7 +22,7 @@ const CompleteCreateEventPage = () => { return ( <MainLayout> - <TopNav children={<></>} /> + <TopNav /> <Title title="행사 개시" description="행사가 성공적으로 개시됐어요 :) 행사 링크를 통해서 지출 내역 공유와 참여자 관리가 가능해요." diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index 68f57a242..8dfa6966f 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -1,38 +1,20 @@ -import {useState} from 'react'; import {useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; -import validateEventName from '@utils/validate/validateEventName'; +import useSetEventName from '@hooks/useSetEventName'; import {ROUTER_URLS} from '@constants/routerUrls'; const SetEventNamePage = () => { - const [eventName, setEventName] = useState(''); - const [errorMessage, setErrorMessage] = useState(''); - const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); + const {eventName, errorMessage, canSubmit, handleEventNameChange} = useSetEventName(); - const submitEventName = async (event: React.FormEvent<HTMLFormElement>) => { + const submitEventName = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); }; - const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { - const newValue = event.target.value; - const validation = validateEventName(newValue); - - setCanSubmit(newValue.length !== 0); - - if (validation.isValid) { - setEventName(newValue); - setErrorMessage(''); - } else { - event.target.value = eventName; - setErrorMessage(validation.errorMessage ?? ''); - } - }; - return ( <MainLayout> <TopNav> @@ -46,7 +28,7 @@ const SetEventNamePage = () => { value={eventName} type="text" placeholder="행사 이름" - onChange={e => handleChange(e)} + onChange={handleEventNameChange} isError={!!errorMessage} autoFocus ></LabelInput> diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index ecef5d710..85bb44e0d 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -25,7 +25,7 @@ const SetEventPasswordPage = () => { const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => { const eventId = await submitPassword(event); - navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`); + navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`, {replace: true}); }; return ( From 0472cf793c8fbf4b790070c7c699027344f6b642 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:59:32 +0900 Subject: [PATCH 170/273] =?UTF-8?q?test:=20useError,=20useToast=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20(#387)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers<HTMLElement>' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 --- client/jest.config.ts | 3 +- client/jest.setup.ts | 1 + client/package-lock.json | 11 ++ client/package.json | 1 + client/src/App.tsx | 4 +- client/src/ErrorProvider.tsx | 83 ------------ client/src/apis/fetcher.ts | 12 +- .../DeleteMemberActionModal.tsx | 2 +- client/src/components/Toast/Toast.tsx | 2 +- client/src/errors/FetchError.ts | 8 +- client/src/hooks/useAuth/useAuth.test.tsx | 20 +-- .../useDeleteMemberAction.test.tsx | 2 +- client/src/hooks/useError/ErrorProvider.tsx | 69 ++++++++++ client/src/hooks/useError/useError.test.tsx | 121 ++++++++++++++++++ client/src/hooks/useError/useError.tsx | 12 ++ client/src/hooks/useEvent/useEvent.test.tsx | 10 +- client/src/hooks/useFetch/useFetch.test.tsx | 13 +- client/src/hooks/useFetch/useFetch.ts | 13 +- .../useSearchMemberReportList.test.tsx | 2 +- .../hooks/useStepList/useStepList.test.tsx | 4 +- .../useToast}/ToastProvider.tsx | 30 ++--- client/src/hooks/useToast/useToast.test.tsx | 99 ++++++++++++++ client/src/hooks/useToast/useToast.tsx | 13 ++ client/src/mocks/svg.ts | 2 + .../CompleteCreateEventPage.tsx | 2 +- .../src/pages/EventPage/EventPageLayout.tsx | 2 +- client/src/types/fetchErrorType.ts | 4 +- client/src/utils/captureError.ts | 24 ++-- client/src/utils/sendLogToSentry.ts | 8 +- client/tsconfig.json | 2 +- 30 files changed, 409 insertions(+), 170 deletions(-) delete mode 100644 client/src/ErrorProvider.tsx create mode 100644 client/src/hooks/useError/ErrorProvider.tsx create mode 100644 client/src/hooks/useError/useError.test.tsx create mode 100644 client/src/hooks/useError/useError.tsx rename client/src/{components/Toast => hooks/useToast}/ToastProvider.tsx (73%) create mode 100644 client/src/hooks/useToast/useToast.test.tsx create mode 100644 client/src/hooks/useToast/useToast.tsx create mode 100644 client/src/mocks/svg.ts diff --git a/client/jest.config.ts b/client/jest.config.ts index 7d54d6b1d..a618bce0c 100644 --- a/client/jest.config.ts +++ b/client/jest.config.ts @@ -17,7 +17,7 @@ const config: Config = { '<rootDir>/src/request/', '<rootDir>/src/constants/', '<rootDir>/src/errors/', - '<rootDir>/src/ErrorProvider.tsx', + '<rootDir>/src/components/', ], verbose: true, @@ -34,6 +34,7 @@ const config: Config = { '^@types/(.*)$': '<rootDir>/src/types/$1', '^@errors/(.*)$': '<rootDir>/src/errors/$1', '^@mocks/(.*)$': '<rootDir>/src/mocks/$1', + '\\.svg$': '<rootDir>/src/mocks/svg.ts', }, testEnvironmentOptions: { customExportConditions: [''], diff --git a/client/jest.setup.ts b/client/jest.setup.ts index d3ff94078..9fe320b2c 100644 --- a/client/jest.setup.ts +++ b/client/jest.setup.ts @@ -1,5 +1,6 @@ import {server} from './src/mocks/server'; import * as router from 'react-router'; +import '@testing-library/jest-dom'; // toBeInTheDocument를 인식하기 위해 @testing-library/jest-dom/extend-expect추가 beforeAll(() => { server.listen(); diff --git a/client/package-lock.json b/client/package-lock.json index ca9b099ba..34f7700fa 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -32,6 +32,7 @@ "@types/react": "^18.3.3", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.0", + "@types/testing-library__jest-dom": "^6.0.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "cypress": "^13.13.2", @@ -5007,6 +5008,16 @@ "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", "dev": true }, + "node_modules/@types/testing-library__jest-dom": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-6.0.0.tgz", + "integrity": "sha512-bnreXCgus6IIadyHNlN/oI5FfX4dWgvGhOPvpr7zzCYDGAPIfvyIoAozMBINmhmsVuqV0cncejF2y5KC7ScqOg==", + "deprecated": "This is a stub types definition. @testing-library/jest-dom provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "@testing-library/jest-dom": "*" + } + }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", diff --git a/client/package.json b/client/package.json index fe7f565ed..775c14c0b 100644 --- a/client/package.json +++ b/client/package.json @@ -31,6 +31,7 @@ "@types/react": "^18.3.3", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-dom": "^18.3.0", + "@types/testing-library__jest-dom": "^6.0.0", "@typescript-eslint/eslint-plugin": "^7.16.0", "@typescript-eslint/parser": "^7.16.0", "cypress": "^13.13.2", diff --git a/client/src/App.tsx b/client/src/App.tsx index 64de1e68c..e3b8e69d6 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -2,11 +2,11 @@ import {Outlet} from 'react-router-dom'; import {HDesignProvider} from 'haengdong-design'; import {Global} from '@emotion/react'; -import {ToastProvider} from '@components/Toast/ToastProvider'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; import {GlobalStyle} from './GlobalStyle'; // import toast from 'react-simple-toasts'; -import {ErrorProvider} from './ErrorProvider'; +import {ErrorProvider} from './hooks/useError/ErrorProvider'; import UnhandledErrorBoundary from './UnhandledErrorBoundary'; const App: React.FC = () => { diff --git a/client/src/ErrorProvider.tsx b/client/src/ErrorProvider.tsx deleted file mode 100644 index c657d9337..000000000 --- a/client/src/ErrorProvider.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import {createContext, useState, useContext, useEffect, ReactNode} from 'react'; - -import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; - -// 에러 컨텍스트 생성 -interface ErrorContextType { - hasError: boolean; - errorMessage: string; - setError: (error: ServerError) => void; - clearError: (ms?: number) => void; - error: ServerError | null; -} - -const ErrorContext = createContext<ErrorContextType | undefined>(undefined); - -// 에러 컨텍스트를 제공하는 프로바이더 컴포넌트 -interface ErrorProviderProps { - children: ReactNode; - callback?: (message: string) => void; -} - -export type ServerError = { - errorCode: string; - message: string; -}; - -export const ErrorProvider = ({children, callback}: ErrorProviderProps) => { - const [hasError, setHasError] = useState(false); - const [errorMessage, setErrorMessage] = useState(''); - const [error, setErrorState] = useState<ServerError | null>(null); - - useEffect(() => { - if (error) { - if (isUnhandledError(error.errorCode)) { - // 에러바운더리로 보내기 - - throw error; - } - - setHasError(true); - const message = SERVER_ERROR_MESSAGES[error.errorCode]; - setErrorMessage(message); - // callback(message); - } - }, [error, callback]); - - const setError = (error: ServerError) => { - setHasError(true); - setErrorMessage(''); - setErrorState(error); - }; - - const clearError = (ms: number = 0) => { - if (error === null) return; - - setTimeout(() => { - setHasError(false); - setErrorMessage(''); - setErrorState(null); - }, ms); - }; - - return ( - <ErrorContext.Provider value={{error, hasError, errorMessage, setError, clearError}}> - {children} - </ErrorContext.Provider> - ); -}; - -// 에러 컨텍스트를 사용하는 커스텀 훅 -export const useError = (): ErrorContextType => { - const context = useContext(ErrorContext); - if (!context) { - throw new Error('useError must be used within an ErrorProvider'); - } - return context; -}; - -const isUnhandledError = (errorCode: string) => { - if (errorCode === 'INTERNAL_SERVER_ERROR') return true; - - return SERVER_ERROR_MESSAGES[errorCode] === undefined; -}; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 01c4bec7f..e87e3d395 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -1,4 +1,4 @@ -import {ServerError} from 'ErrorProvider'; +import {ErrorInfo} from '@hooks/useError/ErrorProvider'; import objectToQueryString from '@utils/objectToQueryString'; @@ -96,15 +96,15 @@ const errorHandler = async ({url, options, body}: ErrorHandlerProps) => { const response: Response = await fetch(url, options); if (!response.ok) { - const serverErrorBody: ServerError = await response.json(); + const serverErrorInfo: ErrorInfo = await response.json(); throw new FetchError({ status: response.status, requestBody: body, endpoint: response.url, - errorBody: serverErrorBody, - name: serverErrorBody.errorCode, - message: serverErrorBody.message || '', + errorInfo: serverErrorInfo, + name: serverErrorInfo.errorCode, + message: serverErrorInfo.message || '', method: options.method, }); } @@ -112,7 +112,7 @@ const errorHandler = async ({url, options, body}: ErrorHandlerProps) => { return response; } catch (error) { if (error instanceof Error) { - throw error; + throw error; // 그대로 FetchError || Error 인스턴스를 던집니다. } throw new Error(UNKNOWN_ERROR); diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx index b4c24afbb..04242fad1 100644 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -2,8 +2,8 @@ import type {MemberAction, MemberType} from 'types/serviceType'; import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; -import {useToast} from '@components/Toast/ToastProvider'; import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; +import {useToast} from '@hooks/useToast/useToast'; import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx index d19b11ca3..edb17400d 100644 --- a/client/src/components/Toast/Toast.tsx +++ b/client/src/components/Toast/Toast.tsx @@ -51,7 +51,7 @@ const Toast = ({ }; return createPortal( - <div css={toastMarginStyle({...styleProps})} {...htmlProps} onClick={handleClickToClose}> + <div css={toastMarginStyle({...styleProps})} {...htmlProps} onClick={handleClickToClose} id="toast"> <div css={toastStyle(isVisible)}> <Flex justifyContent="spaceBetween" alignItems="center"> <Flex alignItems="center" gap="0.5rem"> diff --git a/client/src/errors/FetchError.ts b/client/src/errors/FetchError.ts index f7bf21fe9..9123a80b5 100644 --- a/client/src/errors/FetchError.ts +++ b/client/src/errors/FetchError.ts @@ -4,16 +4,16 @@ class FetchError extends Error { requestBody; status; endpoint; - errorBody; + errorInfo; method; - constructor({requestBody, status, endpoint, errorBody, method, name, message}: FetchErrorType) { - super(errorBody.errorCode); + constructor({requestBody, status, endpoint, errorInfo, method, name, message}: FetchErrorType) { + super(errorInfo.errorCode); this.requestBody = requestBody; this.status = status; this.endpoint = endpoint; - this.errorBody = errorBody; + this.errorInfo = errorInfo; this.method = method; this.name = name; this.message = message; diff --git a/client/src/hooks/useAuth/useAuth.test.tsx b/client/src/hooks/useAuth/useAuth.test.tsx index 48aaade10..130aa73f2 100644 --- a/client/src/hooks/useAuth/useAuth.test.tsx +++ b/client/src/hooks/useAuth/useAuth.test.tsx @@ -2,11 +2,13 @@ import {renderHook, waitFor} from '@testing-library/react'; import {act} from 'react'; import {MemoryRouter} from 'react-router-dom'; +import {useError} from '@hooks/useError/useError'; + import {PASSWORD_LENGTH} from '@constants/password'; import {VALID_PASSWORD_FOR_TEST, VALID_TOKEN_FOR_TEST} from '@mocks/validValueForTest'; -import {ErrorProvider, useError} from '../../ErrorProvider'; +import {ErrorProvider} from '../useError/ErrorProvider'; import useAuth from './useAuth'; @@ -34,7 +36,7 @@ describe('useAuth', () => { }); await waitFor(() => { - expect(result.current.errorResult.error?.errorCode).toBe('TOKEN_NOT_FOUND'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('TOKEN_NOT_FOUND'); }); }); @@ -48,7 +50,7 @@ describe('useAuth', () => { }); await waitFor(() => { - expect(result.current.errorResult.error).toBe(null); + expect(result.current.errorResult.errorInfo).toBe(null); }); }); @@ -62,7 +64,7 @@ describe('useAuth', () => { }); await waitFor(() => { - expect(result.current.errorResult.error?.errorCode).toBe('TOKEN_INVALID'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('TOKEN_INVALID'); }); }); @@ -76,7 +78,7 @@ describe('useAuth', () => { }); await waitFor(() => { - expect(result.current.errorResult.error?.errorCode).toBe('TOKEN_EXPIRED'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('TOKEN_EXPIRED'); }); }); @@ -90,7 +92,7 @@ describe('useAuth', () => { }); await waitFor(() => { - expect(result.current.errorResult.error?.errorCode).toBe('FORBIDDEN'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('FORBIDDEN'); }); }); }); @@ -104,7 +106,7 @@ describe('useAuth', () => { }); await waitFor(() => { - expect(result.current.errorResult.error).toBe(null); + expect(result.current.errorResult.errorInfo).toBe(null); }); }); @@ -116,7 +118,7 @@ describe('useAuth', () => { }); await waitFor(() => { - expect(result.current.errorResult.error?.errorCode).toBe('EVENT_PASSWORD_FORMAT_INVALID'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('EVENT_PASSWORD_FORMAT_INVALID'); }); }); @@ -128,7 +130,7 @@ describe('useAuth', () => { }); await waitFor(() => { - expect(result.current.errorResult.error?.errorCode).toBe('PASSWORD_INVALID'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('PASSWORD_INVALID'); }); }); }); diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx index bb0809046..ca595719a 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -6,7 +6,7 @@ import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; import stepListJson from '../../mocks/stepList.json'; import StepListProvider, {useStepList} from '../useStepList/useStepList'; -import {ErrorProvider} from '../../ErrorProvider'; +import {ErrorProvider} from '../useError/ErrorProvider'; import invalidMemberStepListJson from '../../mocks/invalidMemberStepList.json'; import useDeleteMemberAction from './useDeleteMemberAction'; diff --git a/client/src/hooks/useError/ErrorProvider.tsx b/client/src/hooks/useError/ErrorProvider.tsx new file mode 100644 index 000000000..e1466cf4c --- /dev/null +++ b/client/src/hooks/useError/ErrorProvider.tsx @@ -0,0 +1,69 @@ +import {createContext, useState, useEffect, ReactNode} from 'react'; + +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; + +// 에러 컨텍스트 생성 +export interface ErrorContextType { + clientErrorMessage: string; + setErrorInfo: (error: ErrorInfo) => void; + clearError: (ms?: number) => void; + errorInfo: ErrorInfo | null; +} + +export const ErrorContext = createContext<ErrorContextType | undefined>(undefined); + +// 에러 컨텍스트를 제공하는 프로바이더 컴포넌트 +interface ErrorProviderProps { + children: ReactNode; + callback?: (message: string) => void; +} + +export type ErrorInfo = { + errorCode: string; + message: string; +}; + +export const ErrorProvider = ({children, callback}: ErrorProviderProps) => { + const [clientErrorMessage, setClientErrorMessage] = useState(''); + const [errorInfo, setErrorState] = useState<ErrorInfo | null>(null); + + useEffect(() => { + if (errorInfo) { + if (isUnhandledError(errorInfo.errorCode)) { + // 에러바운더리로 보내기 + + throw errorInfo; + } + + const message = SERVER_ERROR_MESSAGES[errorInfo.errorCode]; + setClientErrorMessage(message); + // callback(message); + } + }, [errorInfo, callback]); + + const setErrorInfo = (error: ErrorInfo) => { + setClientErrorMessage(''); + setErrorState(error); + }; + + const clearError = (ms: number = 0) => { + if (errorInfo === null) return; + + setTimeout(() => { + setClientErrorMessage(''); + setErrorState(null); + }, ms); + }; + + return ( + <ErrorContext.Provider value={{errorInfo, clientErrorMessage, setErrorInfo, clearError}}> + {children} + </ErrorContext.Provider> + ); +}; + +const isUnhandledError = (errorCode: string) => { + if (errorCode === 'INTERNAL_SERVER_ERROR') return true; + + return SERVER_ERROR_MESSAGES[errorCode] === undefined; +}; diff --git a/client/src/hooks/useError/useError.test.tsx b/client/src/hooks/useError/useError.test.tsx new file mode 100644 index 000000000..7c39d0e95 --- /dev/null +++ b/client/src/hooks/useError/useError.test.tsx @@ -0,0 +1,121 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {act} from 'react'; +import {HDesignProvider} from 'haengdong-design'; + +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; + +import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; + +import {ErrorInfo, ErrorProvider} from './ErrorProvider'; +import {useError} from './useError'; + +describe('useError', () => { + const initializeProvider = () => + renderHook(() => useError(), { + wrapper: ({children}) => ( + <HDesignProvider> + <UnhandledErrorBoundary> + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + </UnhandledErrorBoundary> + </HDesignProvider> + ), + }); + + /** + * useError, ErrorProvider, UnhandledErrorBoundary에서 사용되는 `핸들링 가능한 에러`의 정의 + * + * : 서버에서 미리 정의한 에러 코드와 에러 메세지를 던져주는 경우 이를 `핸들링 가능한 에러`로 합니다. + * 다만 예외적으로 INTERNAL_SERVER_ERROR는 핸들링 `불가능`한 에러로 합니다. + */ + const errorCode = 'EVENT_NOT_FOUND'; + const errorInfo: ErrorInfo = {errorCode, message: '메세지입니다.'}; + const expectedClientErrorMessage = SERVER_ERROR_MESSAGES[errorCode]; + + describe('저장된 에러를 초기화한다.', () => { + it('에러 초기화 함수에 인자를 넘겨주지 않은 경우 바로 에러를 초기화한다.', async () => { + const {result} = initializeProvider(); + + await act(async () => result.current.setErrorInfo(errorInfo)); + + // 에러 메세지가 세팅되기 까지 대기 (없어도 통과하나 제대로 값이 들어간 후 초기화됨을 확인하기 위함) + await waitFor(() => { + expect(result.current.clientErrorMessage).toEqual(expectedClientErrorMessage); + }); + + await act(async () => result.current.clearError()); + + await waitFor(() => expect(result.current.errorInfo).toBe(null)); + }); + + it('저장된 에러가 없는데 초기화 함수를 호출할 경우 그냥 종료한다.', async () => { + const {result} = initializeProvider(); + + await act(async () => result.current.clearError()); + + await waitFor(() => expect(result.current.errorInfo).toBe(null)); + }); + }); + + describe('핸들링 가능한 에러', () => { + it('핸들링 가능한 에러인 경우 에러 메세지를 미리 정의된 에러 메세지로 세팅한다.', async () => { + const {result} = initializeProvider(); + + await act(async () => result.current.setErrorInfo(errorInfo)); + + await waitFor(() => expect(result.current.clientErrorMessage).toEqual(expectedClientErrorMessage)); + }); + }); + + describe('핸들링 불가능한 에러', () => { + it('에러 코드가 INTERNAL_SERVER_ERROR인 경우 핸들링 불가능한 에러로 판단하고 에러를 외부로 던진다.', async () => { + const {result} = initializeProvider(); + const errorCode = 'INTERNAL_SERVER_ERROR'; + const errorInfo: ErrorInfo = {errorCode, message: '서버 에러입니다.'}; + + await act(async () => { + try { + result.current.setErrorInfo(errorInfo); + } catch (error) { + expect(error).toBe(errorInfo); + } + }); + }); + + it('에러 코드가 UNHANDLED인 경우 핸들링 불가능한 에러로 판단하고 에러를 외부로 던진다.', async () => { + const {result} = initializeProvider(); + const errorCode = 'UNHANDLED'; + const errorInfo: ErrorInfo = {errorCode, message: '알 수 없는 에러입니다.'}; + + await act(async () => { + try { + result.current.setErrorInfo(errorInfo); + } catch (error) { + expect(error).toBe(errorInfo); + } + }); + }); + + it('에러 코드에 대응하는 에러메세지가 없는 에러인 경우 핸들링 불가능한 에러로 판단하고 에러를 외부로 던진다.', async () => { + const {result} = initializeProvider(); + const errorCode = 'something strange error...'; + const errorInfo: ErrorInfo = {errorCode, message: '정말 모르겠다.'}; + + await act(async () => { + try { + result.current.setErrorInfo(errorInfo); + } catch (error) { + expect(error).toBe(errorInfo); + } + }); + }); + }); + + it('Provider없이 useError를 사용할 경우 에러를 던진다.', () => { + expect(() => { + const _ = renderHook(() => useError()); + }).toThrow('useError must be used within an ErrorProvider'); + }); +}); diff --git a/client/src/hooks/useError/useError.tsx b/client/src/hooks/useError/useError.tsx new file mode 100644 index 000000000..ee7176233 --- /dev/null +++ b/client/src/hooks/useError/useError.tsx @@ -0,0 +1,12 @@ +import {useContext} from 'react'; + +import {ErrorContext, ErrorContextType} from './ErrorProvider'; + +// 에러 컨텍스트를 사용하는 커스텀 훅 +export const useError = (): ErrorContextType => { + const context = useContext(ErrorContext); + if (!context) { + throw new Error('useError must be used within an ErrorProvider'); + } + return context; +}; diff --git a/client/src/hooks/useEvent/useEvent.test.tsx b/client/src/hooks/useEvent/useEvent.test.tsx index b6a616b00..8e952a0db 100644 --- a/client/src/hooks/useEvent/useEvent.test.tsx +++ b/client/src/hooks/useEvent/useEvent.test.tsx @@ -2,12 +2,14 @@ import {renderHook} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; import {act} from 'react'; +import {useError} from '@hooks/useError/useError'; + import {PASSWORD_LENGTH} from '@constants/password'; import {VALID_PASSWORD_FOR_TEST} from '@mocks/validValueForTest'; import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; -import {ErrorProvider, useError} from '../../ErrorProvider'; +import {ErrorProvider} from '../useError/ErrorProvider'; import useEvent from './useEvent'; @@ -36,7 +38,7 @@ describe('useEvent', () => { }); await act(async () => { - expect(result.current.errorResult.error).toBe(null); + expect(result.current.errorResult.errorInfo).toBe(null); }); }); @@ -48,7 +50,7 @@ describe('useEvent', () => { }); await act(async () => { - expect(result.current.errorResult.error?.errorCode).toBe('EVENT_NAME_LENGTH_INVALID'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('EVENT_NAME_LENGTH_INVALID'); }); }); @@ -60,7 +62,7 @@ describe('useEvent', () => { }); await act(async () => { - expect(result.current.errorResult.error?.errorCode).toBe('EVENT_PASSWORD_FORMAT_INVALID'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('EVENT_PASSWORD_FORMAT_INVALID'); }); }); }); diff --git a/client/src/hooks/useFetch/useFetch.test.tsx b/client/src/hooks/useFetch/useFetch.test.tsx index 253d60b6e..b4748125a 100644 --- a/client/src/hooks/useFetch/useFetch.test.tsx +++ b/client/src/hooks/useFetch/useFetch.test.tsx @@ -3,6 +3,7 @@ import {MemoryRouter} from 'react-router-dom'; import {act} from 'react'; import FetchError from '@errors/FetchError'; +import {useError} from '@hooks/useError/useError'; import {requestPostWithoutResponse} from '@apis/fetcher'; @@ -10,7 +11,7 @@ import {captureError} from '@utils/captureError'; import {UNKNOWN_ERROR} from '@constants/errorMessage'; -import {ErrorProvider, useError} from '../../ErrorProvider'; +import {ErrorProvider} from '../useError/ErrorProvider'; import {useFetch} from './useFetch'; @@ -63,7 +64,7 @@ describe('useFetch', () => { it('FetchError가 발생하면 해당 에러의 errorBody를 사용해 상태를 저장한다.', async () => { const {result} = initializeProvider(); const fetchError = new FetchError({ - errorBody: {errorCode: 'UNHANDLED', message: 'Fetch error occurred'}, + errorInfo: {errorCode: 'UNHANDLED', message: 'Fetch error occurred'}, name: 'UNHANDLED', message: 'Fetch error occurred', requestBody: '', @@ -78,8 +79,8 @@ describe('useFetch', () => { }); await waitFor(() => { - expect(result.current.errorResult.error?.errorCode).toBe('UNHANDLED'); - expect(result.current.errorResult.error?.message).toBe('Fetch error occurred'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('UNHANDLED'); + expect(result.current.errorResult.errorInfo?.message).toBe('Fetch error occurred'); }); }); @@ -97,8 +98,8 @@ describe('useFetch', () => { } await waitFor(() => { - expect(result.current.errorResult.error?.errorCode).toBe('Error'); - expect(result.current.errorResult.error?.message).toBe('일반 에러 발생'); + expect(result.current.errorResult.errorInfo?.errorCode).toBe('Error'); + expect(result.current.errorResult.errorInfo?.message).toBe('일반 에러 발생'); }); }); diff --git a/client/src/hooks/useFetch/useFetch.ts b/client/src/hooks/useFetch/useFetch.ts index 2d034fa5e..35bf18a33 100644 --- a/client/src/hooks/useFetch/useFetch.ts +++ b/client/src/hooks/useFetch/useFetch.ts @@ -2,14 +2,13 @@ import {useState} from 'react'; import {useNavigate} from 'react-router-dom'; import FetchError from '@errors/FetchError'; +import {useError} from '@hooks/useError/useError'; import {captureError} from '@utils/captureError'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import {UNKNOWN_ERROR} from '@constants/errorMessage'; -import {useError} from '../../ErrorProvider'; - type FetchProps<T> = { queryFunction: () => Promise<T>; onSuccess?: () => void; @@ -17,7 +16,7 @@ type FetchProps<T> = { }; export const useFetch = () => { - const {setError, clearError} = useError(); + const {setErrorInfo, clearError} = useError(); const [loading, setLoading] = useState(false); const navigate = useNavigate(); const eventId = getEventIdByUrl(); @@ -36,10 +35,10 @@ export const useFetch = () => { return result; } catch (error) { if (error instanceof Error) { - const errorBody = - error instanceof FetchError ? error.errorBody : {errorCode: error.name, message: error.message}; + const errorInfo = + error instanceof FetchError ? error.errorInfo : {errorCode: error.name, message: error.message}; - setError(errorBody); + setErrorInfo(errorInfo); if (onError) { onError(); @@ -47,7 +46,7 @@ export const useFetch = () => { captureError(error, navigate, eventId); } else { - setError({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); + setErrorInfo({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); captureError(new Error(UNKNOWN_ERROR), navigate, eventId); // 에러를 throw 해 에러 바운더리로 보냅니다. 따라서 에러 이름은 중요하지 않음 diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx index 2688a9a04..667f0bfb6 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx @@ -2,7 +2,7 @@ import {renderHook, waitFor} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; import reportListJson from '../../mocks/reportList.json'; -import {ErrorProvider} from '../../ErrorProvider'; +import {ErrorProvider} from '../useError/ErrorProvider'; import useSearchMemberReportList from './useSearchMemberReportList'; diff --git a/client/src/hooks/useStepList/useStepList.test.tsx b/client/src/hooks/useStepList/useStepList.test.tsx index 81963b73a..ae4cca978 100644 --- a/client/src/hooks/useStepList/useStepList.test.tsx +++ b/client/src/hooks/useStepList/useStepList.test.tsx @@ -6,7 +6,7 @@ import {Bill} from 'types/serviceType'; import StepListProvider, {useStepList} from '../useStepList/useStepList'; import stepListJson from '../../mocks/stepList.json'; -import {ErrorProvider} from '../../ErrorProvider'; +import {ErrorProvider} from '../useError/ErrorProvider'; const stepListMockData = stepListJson; @@ -105,7 +105,7 @@ describe('useStepList', () => { it('provider안에서 호출되지 않으면 에러를 던진다.', () => { expect(() => { - const {result} = renderHook(() => useStepList()); + const _ = renderHook(() => useStepList()); }).toThrow('useStepList는 StepListProvider 내에서 사용되어야 합니다.'); }); }); diff --git a/client/src/components/Toast/ToastProvider.tsx b/client/src/hooks/useToast/ToastProvider.tsx similarity index 73% rename from client/src/components/Toast/ToastProvider.tsx rename to client/src/hooks/useToast/ToastProvider.tsx index d842a3a08..eed006967 100644 --- a/client/src/components/Toast/ToastProvider.tsx +++ b/client/src/hooks/useToast/ToastProvider.tsx @@ -1,12 +1,12 @@ /** @jsxImportSource @emotion/react */ import {createContext, useContext, useEffect, useState} from 'react'; -import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; +import {useError} from '@hooks/useError/useError'; -import {useError} from '../../ErrorProvider'; +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; -import {ToastProps} from './Toast.type'; -import Toast from './Toast'; +import {ToastProps} from '../../components/Toast/Toast.type'; +import Toast from '../../components/Toast/Toast'; export const ToastContext = createContext<ToastContextProps | null>(null); @@ -21,9 +21,9 @@ type ShowToast = ToastProps & { isAlwaysOn?: boolean; }; -const ToastProvider = ({children}: React.PropsWithChildren) => { +export const ToastProvider = ({children}: React.PropsWithChildren) => { const [currentToast, setCurrentToast] = useState<ShowToast | null>(null); - const {hasError, errorMessage, clearError} = useError(); + const {errorInfo, clearError, clientErrorMessage} = useError(); const showToast = ({showingTime = DEFAULT_TIME, isAlwaysOn = false, ...toastProps}: ShowToast) => { setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); @@ -34,9 +34,9 @@ const ToastProvider = ({children}: React.PropsWithChildren) => { }; useEffect(() => { - if (hasError) { + if (errorInfo !== null) { showToast({ - message: errorMessage || SERVER_ERROR_MESSAGES.UNHANDLED, + message: clientErrorMessage || SERVER_ERROR_MESSAGES.UNHANDLED, showingTime: DEFAULT_TIME, // TODO: (@weadie) 나중에 토스트 프로바이더를 제거한 토스트를 만들 것이기 때문에 많이 리펙터링 안함 isAlwaysOn: false, position: 'bottom', @@ -47,7 +47,7 @@ const ToastProvider = ({children}: React.PropsWithChildren) => { clearError(DEFAULT_TIME); } - }, [errorMessage, hasError]); + }, [errorInfo, clientErrorMessage]); useEffect(() => { if (!currentToast) return; @@ -70,15 +70,3 @@ const ToastProvider = ({children}: React.PropsWithChildren) => { </ToastContext.Provider> ); }; - -const useToast = () => { - const context = useContext(ToastContext); - - if (!context) { - throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); - } - - return context; -}; - -export {ToastProvider, useToast}; diff --git a/client/src/hooks/useToast/useToast.test.tsx b/client/src/hooks/useToast/useToast.test.tsx new file mode 100644 index 000000000..6f9522a24 --- /dev/null +++ b/client/src/hooks/useToast/useToast.test.tsx @@ -0,0 +1,99 @@ +import {render, screen, waitFor} from '@testing-library/react'; +import {act, ReactNode} from 'react'; +import {HDesignProvider} from 'haengdong-design'; + +import {useError} from '@hooks/useError/useError'; + +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; + +import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; +import {ErrorInfo, ErrorProvider} from '../../hooks/useError/ErrorProvider'; // useError 경로에 맞게 설정 + +import {ToastProvider} from './ToastProvider'; // 위 코드에 해당하는 ToastProvider 경로 + +// 테스트용 헬퍼 컴포넌트 +const TestComponent = ({errorInfo}: {errorInfo: ErrorInfo}) => { + const {setErrorInfo} = useError(); + + // 테스트에서 직접 에러를 설정합니다. + const triggerError = () => { + setErrorInfo(errorInfo); + }; + + return <button onClick={triggerError}>Trigger Error</button>; +}; + +const setup = (ui: ReactNode) => + render( + <HDesignProvider> + <UnhandledErrorBoundary> + <ErrorProvider> + <ToastProvider>{ui}</ToastProvider> + </ErrorProvider> + </UnhandledErrorBoundary> + </HDesignProvider>, + ); + +beforeEach(() => { + jest.useFakeTimers(); +}); + +afterEach(() => { + jest.useRealTimers(); +}); + +describe('useToast', () => { + describe('error의 경우 자동으로 토스트를 띄워준다.', () => { + it('핸들링 가능한 에러인 경우 토스트가 뜬다.', async () => { + const errorCode = 'ACTION_NOT_FOUND'; + + setup( + <TestComponent + errorInfo={{ + errorCode, + message: '서버의 에러메세지', + }} + />, + ); + const errorMessage = SERVER_ERROR_MESSAGES[errorCode]; + + act(() => { + // 에러 트리거 버튼을 클릭 + screen.getByText('Trigger Error').click(); + }); + + // 토스트가 표시되는지 확인 + await waitFor(() => { + expect(screen.getByText(errorMessage)).toBeInTheDocument(); + }); + + // 타이머가 지나서 토스트가 사라지는지 확인 + jest.runAllTimers(); // Jest의 타이머를 실행 + await waitFor(() => { + expect(screen.queryByText(errorMessage)).not.toBeInTheDocument(); + }); + }); + + it('핸들링 불가능한 에러인 경우 토스트가 안뜬다.', async () => { + const errorCode = '핸들링이 안되는 에러 코드'; + + setup( + <TestComponent + errorInfo={{ + errorCode, + message: '핸들링이 안되는 에러 메세지', + }} + />, + ); + + act(() => { + // 에러 트리거 버튼을 클릭 + screen.getByText('Trigger Error').click(); + }); + + await waitFor(() => { + expect(document.getElementById('toast')).not.toBeInTheDocument(); + }); + }); + }); +}); diff --git a/client/src/hooks/useToast/useToast.tsx b/client/src/hooks/useToast/useToast.tsx new file mode 100644 index 000000000..189847405 --- /dev/null +++ b/client/src/hooks/useToast/useToast.tsx @@ -0,0 +1,13 @@ +import {useContext} from 'react'; + +import {ToastContext} from './ToastProvider'; + +export const useToast = () => { + const context = useContext(ToastContext); + + if (!context) { + throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); + } + + return context; +}; diff --git a/client/src/mocks/svg.ts b/client/src/mocks/svg.ts new file mode 100644 index 000000000..ffe2050a0 --- /dev/null +++ b/client/src/mocks/svg.ts @@ -0,0 +1,2 @@ +export default 'SvgrURL'; +export const ReactComponent = 'div'; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 75d4ca7b2..093d2a52a 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -3,7 +3,7 @@ import {Button, FixedButton, Flex, Input, MainLayout, Text, Title, TopNav} from import {CopyToClipboard} from 'react-copy-to-clipboard'; import {css} from '@emotion/react'; -import {useToast} from '@components/Toast/ToastProvider'; +import {useToast} from '@hooks/useToast/useToast'; import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 5aa61a570..0c67454ac 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -3,9 +3,9 @@ import {Outlet, useMatch} from 'react-router-dom'; import {useEffect, useState} from 'react'; import CopyToClipboard from 'react-copy-to-clipboard'; -import {useToast} from '@components/Toast/ToastProvider'; import {requestGetEventName} from '@apis/request/event'; import StepListProvider from '@hooks/useStepList/useStepList'; +import {useToast} from '@hooks/useToast/useToast'; import useNavSwitch from '@hooks/useNavSwitch'; diff --git a/client/src/types/fetchErrorType.ts b/client/src/types/fetchErrorType.ts index 2ab327e19..664fa368b 100644 --- a/client/src/types/fetchErrorType.ts +++ b/client/src/types/fetchErrorType.ts @@ -1,4 +1,4 @@ -import {ServerError} from 'ErrorProvider'; +import {ErrorInfo} from '@hooks/useError/ErrorProvider'; import {Method} from '@apis/fetcher'; @@ -6,6 +6,6 @@ export type FetchErrorType = Error & { requestBody: string; status: number; endpoint: string; - errorBody: ServerError; + errorInfo: ErrorInfo; method: Method; }; diff --git a/client/src/utils/captureError.ts b/client/src/utils/captureError.ts index d0af34729..ce70da972 100644 --- a/client/src/utils/captureError.ts +++ b/client/src/utils/captureError.ts @@ -1,7 +1,7 @@ import {NavigateFunction} from 'react-router-dom'; import FetchError from '@errors/FetchError'; -import {ServerError} from 'ErrorProvider'; +import {ErrorInfo} from '@hooks/useError/ErrorProvider'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -11,47 +11,47 @@ export const captureError = async (error: Error, navigate: NavigateFunction, eve // prod 환경에서만 Sentry capture 실행 if (process.env.NODE_ENV !== 'production') return; - const errorBody: ServerError = - error instanceof FetchError ? error.errorBody : {message: error.message, errorCode: error.name}; + const errorInfo: ErrorInfo = + error instanceof FetchError ? error.errorInfo : {message: error.message, errorCode: error.name}; - switch (errorBody?.errorCode) { + switch (errorInfo?.errorCode) { case 'INTERNAL_SERVER_ERROR': - sendLogToSentry({error, errorBody, level: 'fatal'}); + sendLogToSentry({error, errorInfo, level: 'fatal'}); break; case 'FORBIDDEN': - sendLogToSentry({error, errorBody}); + sendLogToSentry({error, errorInfo}); navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; case 'TOKEN_INVALID': - sendLogToSentry({error, errorBody}); + sendLogToSentry({error, errorInfo}); navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; case 'TOKEN_EXPIRED': - sendLogToSentry({error, errorBody}); + sendLogToSentry({error, errorInfo}); navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; case 'TOKEN_NOT_FOUND': - sendLogToSentry({error, errorBody}); + sendLogToSentry({error, errorInfo}); navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 case 'PASSWORD_INVALID': - sendLogToSentry({error, errorBody, level: 'debug'}); + sendLogToSentry({error, errorInfo, level: 'debug'}); navigate(`${ROUTER_URLS.event}/${eventId}/login`); break; // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 case 'BILL_ACTION_PRICE_INVALID': - sendLogToSentry({error, errorBody, level: 'debug'}); + sendLogToSentry({error, errorInfo, level: 'debug'}); break; default: - sendLogToSentry({error, errorBody, level: 'fatal'}); + sendLogToSentry({error, errorInfo, level: 'fatal'}); break; } }; diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts index 165cf323b..d93e526a4 100644 --- a/client/src/utils/sendLogToSentry.ts +++ b/client/src/utils/sendLogToSentry.ts @@ -1,6 +1,6 @@ import * as Sentry from '@sentry/react'; -import {ServerError} from 'ErrorProvider'; +import {ErrorInfo} from '@hooks/useError/ErrorProvider'; import {UNKNOWN_ERROR} from '@constants/errorMessage'; @@ -21,12 +21,12 @@ type SentryLevel = 'fatal' | 'error' | 'warning' | 'info' | 'debug' | 'log'; type SendLogToSentry = { level?: SentryLevel; error: Error; - errorBody: ServerError; + errorInfo: ErrorInfo; }; -const sendLogToSentry = ({level = 'error', error, errorBody}: SendLogToSentry) => { +const sendLogToSentry = ({level = 'error', error, errorInfo}: SendLogToSentry) => { Sentry.withScope(scope => { - const {errorCode, message} = errorBody; + const {errorCode, message} = errorInfo; scope.setLevel(level); scope.setTag('environment', process.env.NODE_ENV); diff --git a/client/tsconfig.json b/client/tsconfig.json index 7c749b6f5..8b7b30d14 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -20,7 +20,7 @@ // "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "types": ["jest", "node", "cypress"], + "types": ["jest", "@testing-library/jest-dom", "node", "cypress"], "esModuleInterop": true, "strictNullChecks": true, "strictFunctionTypes": true, From 325e9436e0b19e7b43a8bd1b3cc2a17d8c65cdb9 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Mon, 19 Aug 2024 17:00:20 +0900 Subject: [PATCH 171/273] =?UTF-8?q?feat:=20Zustand,=20react-query=20?= =?UTF-8?q?=EB=8F=84=EC=9E=85=20=EB=B0=8F=20=EC=A0=81=EC=9A=A9=20(#388)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> --- client/eslint.config.mjs | 9 +- client/jest.config.ts | 2 + client/package-lock.json | 63 +++++++++- client/package.json | 6 +- client/src/App.tsx | 26 ++-- client/src/apis/request/member.ts | 2 +- .../AddBillActionListModalContent.tsx | 13 +- .../AddMemberActionListModalContent.tsx | 8 +- .../PutAndDeleteBillActionModal.tsx | 2 +- .../SetInitialMemberListModal.tsx | 8 +- client/src/components/StepList/StepList.tsx | 8 +- client/src/constants/queryKeys.ts | 9 ++ .../queries/useRequestDeleteAllMemberList.ts | 27 +++++ .../queries/useRequestDeleteBillAction.ts | 26 ++++ .../queries/useRequestDeleteMemberAction.ts | 27 +++++ .../queries/useRequestGetAllMemberList.ts | 18 +++ .../useRequestGetCurrentInMemberList.ts | 18 +++ .../hooks/queries/useRequestGetEventName.ts | 18 +++ .../queries/useRequestGetMemberReportList.ts | 17 +++ .../hooks/queries/useRequestGetStepList.ts | 32 +++++ .../queries/useRequestPostAuthentication.ts | 23 ++++ .../hooks/queries/useRequestPostBillList.ts | 27 +++++ .../src/hooks/queries/useRequestPostEvent.ts | 16 +++ .../src/hooks/queries/useRequestPostLogin.ts | 26 ++++ .../hooks/queries/useRequestPostMemberList.ts | 37 ++++++ .../queries/useRequestPutAllMemberList.ts | 27 +++++ .../hooks/queries/useRequestPutBillAction.ts | 29 +++++ client/src/hooks/useAuth/useAuth.test.tsx | 16 ++- .../useDeleteMemberAction.test.tsx | 35 ++++-- .../useDeleteMemberAction.tsx | 29 ++--- client/src/hooks/useEvent/useEvent.test.tsx | 17 ++- client/src/hooks/useEvent/useEvent.tsx | 2 + client/src/hooks/usePutAndDeleteBillAction.ts | 32 ++--- client/src/hooks/useSearchInMemberList.ts | 22 +--- .../useSearchMemberReportList.test.tsx | 17 ++- .../useSearchMemberReportList.tsx | 37 +----- client/src/hooks/useSetAllMemberList.tsx | 42 +++---- client/src/hooks/useSetEventPasswordPage.ts | 60 ++++++++++ client/src/hooks/useSetPassword.ts | 47 -------- .../hooks/useStepList/useStepList.test.tsx | 111 ------------------ client/src/hooks/useStepList/useStepList.tsx | 102 ---------------- .../CreateEventPage/SetEventNamePage.tsx | 3 +- .../CreateEventPage/SetEventPasswordPage.tsx | 28 +---- .../pages/EventPage/AdminPage/AdminPage.tsx | 33 +++--- .../EventPage/AdminPage/EventLoginPage.tsx | 17 +-- .../src/pages/EventPage/EventPageLayout.tsx | 68 ++++------- .../src/pages/EventPage/HomePage/HomePage.tsx | 7 +- client/src/store/stepListStore.ts | 16 +++ client/src/store/totalExpenseAmountStore.ts | 14 +++ client/src/types/serviceType.ts | 14 +++ client/src/utils/caculateExpense.ts | 14 +++ client/src/utils/getEventIdByUrl.ts | 2 +- client/src/utils/groupActions.ts | 27 +++++ client/src/utils/stepListToActions.ts | 23 ++++ client/tsconfig.json | 1 + client/webpack.common.mjs | 1 + 56 files changed, 831 insertions(+), 530 deletions(-) create mode 100644 client/src/constants/queryKeys.ts create mode 100644 client/src/hooks/queries/useRequestDeleteAllMemberList.ts create mode 100644 client/src/hooks/queries/useRequestDeleteBillAction.ts create mode 100644 client/src/hooks/queries/useRequestDeleteMemberAction.ts create mode 100644 client/src/hooks/queries/useRequestGetAllMemberList.ts create mode 100644 client/src/hooks/queries/useRequestGetCurrentInMemberList.ts create mode 100644 client/src/hooks/queries/useRequestGetEventName.ts create mode 100644 client/src/hooks/queries/useRequestGetMemberReportList.ts create mode 100644 client/src/hooks/queries/useRequestGetStepList.ts create mode 100644 client/src/hooks/queries/useRequestPostAuthentication.ts create mode 100644 client/src/hooks/queries/useRequestPostBillList.ts create mode 100644 client/src/hooks/queries/useRequestPostEvent.ts create mode 100644 client/src/hooks/queries/useRequestPostLogin.ts create mode 100644 client/src/hooks/queries/useRequestPostMemberList.ts create mode 100644 client/src/hooks/queries/useRequestPutAllMemberList.ts create mode 100644 client/src/hooks/queries/useRequestPutBillAction.ts create mode 100644 client/src/hooks/useSetEventPasswordPage.ts delete mode 100644 client/src/hooks/useSetPassword.ts delete mode 100644 client/src/hooks/useStepList/useStepList.test.tsx delete mode 100644 client/src/hooks/useStepList/useStepList.tsx create mode 100644 client/src/store/stepListStore.ts create mode 100644 client/src/store/totalExpenseAmountStore.ts create mode 100644 client/src/utils/caculateExpense.ts create mode 100644 client/src/utils/groupActions.ts create mode 100644 client/src/utils/stepListToActions.ts diff --git a/client/eslint.config.mjs b/client/eslint.config.mjs index 106f6ccde..4ca5abb89 100644 --- a/client/eslint.config.mjs +++ b/client/eslint.config.mjs @@ -56,6 +56,11 @@ export default [ group: 'internal', position: 'after', }, + { + pattern: '@store/*', + group: 'internal', + position: 'after', + }, { pattern: '@pages/*', group: 'internal', @@ -67,12 +72,12 @@ export default [ position: 'after', }, { - pattern: '@assets/*', + pattern: '@utils/*', group: 'internal', position: 'after', }, { - pattern: '@utils/*', + pattern: '@assets/*', group: 'internal', position: 'after', }, diff --git a/client/jest.config.ts b/client/jest.config.ts index a618bce0c..4bb1dbd3e 100644 --- a/client/jest.config.ts +++ b/client/jest.config.ts @@ -18,6 +18,7 @@ const config: Config = { '<rootDir>/src/constants/', '<rootDir>/src/errors/', '<rootDir>/src/components/', + '<rootDir>/src/store/', ], verbose: true, @@ -34,6 +35,7 @@ const config: Config = { '^@types/(.*)$': '<rootDir>/src/types/$1', '^@errors/(.*)$': '<rootDir>/src/errors/$1', '^@mocks/(.*)$': '<rootDir>/src/mocks/$1', + '^@store/(.*)$': '<rootDir>/src/store/$1', '\\.svg$': '<rootDir>/src/mocks/svg.ts', }, testEnvironmentOptions: { diff --git a/client/package-lock.json b/client/package-lock.json index 34f7700fa..d01bee964 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,12 +11,14 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", + "@tanstack/react-query": "^5.51.23", "haengdong-design": "^0.1.74", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", "react-error-boundary": "^4.0.13", - "react-router-dom": "^6.24.1" + "react-router-dom": "^6.24.1", + "zustand": "^4.5.5" }, "devDependencies": { "@eslint/compat": "^1.1.0", @@ -4324,6 +4326,30 @@ "@swc/counter": "^0.1.3" } }, + "node_modules/@tanstack/query-core": { + "version": "5.51.21", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.21.tgz", + "integrity": "sha512-POQxm42IUp6n89kKWF4IZi18v3fxQWFRolvBA6phNVmA8psdfB1MvDnGacCJdS+EOX12w/CyHM62z//rHmYmvw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.51.23", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.23.tgz", + "integrity": "sha512-CfJCfX45nnVIZjQBRYYtvVMIsGgWLKLYC4xcUiYEey671n1alvTZoCBaU9B85O8mF/tx9LPyrI04A6Bs2THv4A==", + "dependencies": { + "@tanstack/query-core": "5.51.21" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, "node_modules/@testing-library/dom": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", @@ -17925,6 +17951,14 @@ "requires-port": "^1.0.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -18897,6 +18931,33 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", + "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", + "dependencies": { + "use-sync-external-store": "1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } } } } diff --git a/client/package.json b/client/package.json index 775c14c0b..5de424ec7 100644 --- a/client/package.json +++ b/client/package.json @@ -67,15 +67,17 @@ "dependencies": { "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", + "@tanstack/react-query": "^5.51.23", "haengdong-design": "^0.1.74", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", "react-error-boundary": "^4.0.13", - "react-router-dom": "^6.24.1" + "react-router-dom": "^6.24.1", + "zustand": "^4.5.5" }, "engines": { "npm": ">=10.7.0", "node": ">=20.15.1" } -} +} \ No newline at end of file diff --git a/client/src/App.tsx b/client/src/App.tsx index e3b8e69d6..3a8b7f0f2 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,26 +1,30 @@ import {Outlet} from 'react-router-dom'; import {HDesignProvider} from 'haengdong-design'; import {Global} from '@emotion/react'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; import {ToastProvider} from '@hooks/useToast/ToastProvider'; +import {ErrorProvider} from '@hooks/useError/ErrorProvider'; import {GlobalStyle} from './GlobalStyle'; -// import toast from 'react-simple-toasts'; -import {ErrorProvider} from './hooks/useError/ErrorProvider'; import UnhandledErrorBoundary from './UnhandledErrorBoundary'; +const queryClient = new QueryClient(); + const App: React.FC = () => { return ( <HDesignProvider> - <UnhandledErrorBoundary> - <Global styles={GlobalStyle} /> - <ErrorProvider> - {/* <ErrorProvider callback={toast}> */} - <ToastProvider> - <Outlet /> - </ToastProvider> - </ErrorProvider> - </UnhandledErrorBoundary> + <QueryClientProvider client={queryClient}> + <UnhandledErrorBoundary> + <Global styles={GlobalStyle} /> + <ErrorProvider> + {/* <ErrorProvider callback={toast}> */} + <ToastProvider> + <Outlet /> + </ToastProvider> + </ErrorProvider> + </UnhandledErrorBoundary> + </QueryClientProvider> </HDesignProvider> ); }; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 141061bc1..dd7152575 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -76,7 +76,7 @@ export type ResponseGetCurrentInMemberList = { memberNames: string[]; }; -export const requestGetCurrentInMemberList = async (eventId: string) => { +export const requestGetCurrentInMemberList = async ({eventId}: WithEventId) => { return await requestGet<ResponseGetCurrentInMemberList>({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/members/current`, diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx index e5165804e..553a7ae15 100644 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx @@ -1,8 +1,7 @@ import {FixedButton, LabelGroupInput} from 'haengdong-design'; -import {useEffect} from 'react'; import validatePurchase from '@utils/validate/validatePurchase'; -import {useStepList} from '@hooks/useStepList/useStepList'; +import useRequestPostBillList from '@hooks/queries/useRequestPostBillList'; import useDynamicBillActionInput from '@hooks/useDynamicBillActionInput'; @@ -13,6 +12,7 @@ interface AddBillActionListModalContentProps { } const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionListModalContentProps) => { + // useDynamicBillActionInput에서 errorIndexList 반환하지 않음 const { inputPairList, inputRefList, @@ -22,14 +22,13 @@ const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionList deleteEmptyInputPairElementOnBlur, focusNextInputOnEnter, } = useDynamicBillActionInput(validatePurchase); - const {addBill} = useStepList(); + + const {mutate: postBillList} = useRequestPostBillList(); const handleSetPurchaseSubmit = () => { // TODO: (@weadie) 요청 실패시 오류 핸들 필요 - addBill( - getFilledInputPairList().map(({title, price}) => ({title, price: Number(price)})), - () => setIsOpenBottomSheet(false), - ); // TODO: (@weadie) DTO같은게 다이내믹에 필요할까? + postBillList({billList: getFilledInputPairList().map(({title, price}) => ({title, price: Number(price)}))}); + setIsOpenBottomSheet(false); }; return ( diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index d0fd809d7..b14e6ffc0 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -3,7 +3,7 @@ import type {MemberType} from 'types/serviceType'; import {FixedButton, LabelGroupInput} from 'haengdong-design'; import validateMemberName from '@utils/validate/validateMemberName'; -import {useStepList} from '@hooks/useStepList/useStepList'; +import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; import useDynamicInput from '@hooks/useDynamicInput'; @@ -20,17 +20,17 @@ const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: Ad const dynamicProps = useDynamicInput(validateMemberName); const {inputList, getFilledInputList, errorMessage, canSubmit} = dynamicProps; - const {updateMemberList} = useStepList(); + const {mutate: postMemberList} = useRequestPostMemberList(); const handleUpdateMemberListSubmit = () => { - updateMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); + postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); setIsOpenBottomSheet(false); }; return ( <div css={style.container}> <div css={style.inputGroup}> - <LabelGroupInput labelText="이름" errorText={errorMessage}> + <LabelGroupInput labelText="이름" errorText={errorMessage ?? ''}> {inOutAction === 'IN' ? <InMember dynamicProps={dynamicProps} /> : <OutMember dynamicProps={dynamicProps} />} </LabelGroupInput> </div> diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index f9fa58594..d60e7fc61 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -33,7 +33,7 @@ const PutAndDeleteBillActionModal = ({ <Text size="bodyBold">지출 내역 수정하기</Text> </h2> <fieldset css={inputContainerStyle}> - <LabelGroupInput labelText="지출내역 / 금액" errorText={errorMessage}> + <LabelGroupInput labelText="지출내역 / 금액" errorText={errorMessage ?? ''}> <LabelGroupInput.Element aria-label="지출 내역" elementKey={'title'} diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index 93fb2eae3..223f725e8 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -1,7 +1,7 @@ import {Text, BottomSheet, FixedButton, LabelGroupInput} from 'haengdong-design'; import validateMemberName from '@utils/validate/validateMemberName'; -import {useStepList} from '@hooks/useStepList/useStepList'; +import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; import useDynamicInput from '@hooks/useDynamicInput'; @@ -27,10 +27,10 @@ const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: Se errorIndexList, focusNextInputOnEnter, } = useDynamicInput(validateMemberName); - const {updateMemberList} = useStepList(); + const {mutate: postMemberList} = useRequestPostMemberList(); const handleSubmit = () => { - updateMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); + postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); setIsOpenBottomSheet(false); }; @@ -39,7 +39,7 @@ const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: Se <div css={setInitialMemberListModalStyle}> <Text size="bodyBold">시작 인원 추가하기</Text> <div css={setInitialMemberListModalInputGroupStyle}> - <LabelGroupInput labelText="이름" errorText={errorMessage}> + <LabelGroupInput labelText="이름" errorText={errorMessage ?? ''}> {inputList.map(({value, index}) => ( <LabelGroupInput.Element key={`${index}`} diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 1aeb7888e..3d37788cf 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,11 +1,15 @@ import {Flex} from 'haengdong-design'; -import {useStepList} from '@hooks/useStepList/useStepList'; +import {BillStep, MemberStep} from 'types/serviceType'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; import Step from './Step'; const StepList = () => { - const {stepList} = useStepList(); + // const {stepList} = useStepList(); + + const {data: stepListData} = useRequestGetStepList(); + const stepList = stepListData ?? ([] as (MemberStep | BillStep)[]); // TODO: (@weadie) if else 구문이 지저분하므로 리펙터링이 필요합니다. return ( diff --git a/client/src/constants/queryKeys.ts b/client/src/constants/queryKeys.ts new file mode 100644 index 000000000..23ae4b90e --- /dev/null +++ b/client/src/constants/queryKeys.ts @@ -0,0 +1,9 @@ +const QUERY_KEYS = { + stepList: 'stepList', + eventName: 'eventName', + allMemberList: 'allMemberList', + currentInMember: 'currentInMember', + memberReport: 'memberReport', +}; + +export default QUERY_KEYS; diff --git a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts new file mode 100644 index 000000000..a6b761e99 --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts @@ -0,0 +1,27 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteAllMemberListMutationProps { + memberName: string; +} + +const useRequestDeleteAllMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({memberName}: DeleteAllMemberListMutationProps) => requestDeleteAllMemberList({eventId, memberName}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestDeleteAllMemberList; diff --git a/client/src/hooks/queries/useRequestDeleteBillAction.ts b/client/src/hooks/queries/useRequestDeleteBillAction.ts new file mode 100644 index 000000000..28be9dfd1 --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteBillAction.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteBillAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteBillActionMutationProps { + actionId: number; +} + +const useRequestDeleteBillAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId}: DeleteBillActionMutationProps) => requestDeleteBillAction({eventId, actionId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestDeleteBillAction; diff --git a/client/src/hooks/queries/useRequestDeleteMemberAction.ts b/client/src/hooks/queries/useRequestDeleteMemberAction.ts new file mode 100644 index 000000000..46ac65204 --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteMemberAction.ts @@ -0,0 +1,27 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteMemberAction} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteMemberActionMutationProps { + actionId: number; +} + +const useRequestDeleteMemberAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId}: DeleteMemberActionMutationProps) => requestDeleteMemberAction({eventId, actionId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + }, + }); +}; + +export default useRequestDeleteMemberAction; diff --git a/client/src/hooks/queries/useRequestGetAllMemberList.ts b/client/src/hooks/queries/useRequestGetAllMemberList.ts new file mode 100644 index 000000000..531285fd6 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetAllMemberList.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetAllMemberList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.allMemberList], + queryFn: () => requestGetAllMemberList({eventId}), + }); +}; + +export default useRequestGetAllMemberList; diff --git a/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts b/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts new file mode 100644 index 000000000..31dc058c2 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetCurrentInMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetCurrentInMemberList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.currentInMember], + queryFn: () => requestGetCurrentInMemberList({eventId}), + }); +}; + +export default useRequestGetCurrentInMemberList; diff --git a/client/src/hooks/queries/useRequestGetEventName.ts b/client/src/hooks/queries/useRequestGetEventName.ts new file mode 100644 index 000000000..6ddb21858 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetEventName.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetEventName} from '@apis/request/event'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetEventName = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.eventName], + queryFn: () => requestGetEventName({eventId}), + }); +}; + +export default useRequestGetEventName; diff --git a/client/src/hooks/queries/useRequestGetMemberReportList.ts b/client/src/hooks/queries/useRequestGetMemberReportList.ts new file mode 100644 index 000000000..fe3372d35 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetMemberReportList.ts @@ -0,0 +1,17 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetMemberReportList} from '@apis/request/report'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetMemberReportList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.memberReport], + queryFn: () => requestGetMemberReportList({eventId}), + }); +}; +export default useRequestGetMemberReportList; diff --git a/client/src/hooks/queries/useRequestGetStepList.ts b/client/src/hooks/queries/useRequestGetStepList.ts new file mode 100644 index 000000000..d4357974f --- /dev/null +++ b/client/src/hooks/queries/useRequestGetStepList.ts @@ -0,0 +1,32 @@ +import {useQuery} from '@tanstack/react-query'; +import {useEffect} from 'react'; + +import {requestGetStepList} from '@apis/request/stepList'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; +import {getTotalExpenseAmount} from '@utils/caculateExpense'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetStepList = () => { + const eventId = getEventIdByUrl(); + const {updateTotalExpenseAmount} = useTotalExpenseAmountStore(); + + const queryResult = useQuery({ + queryKey: [QUERY_KEYS.stepList], + queryFn: () => requestGetStepList({eventId}), + }); + + useEffect(() => { + if (queryResult.isSuccess && queryResult.data) { + const totalExpenseAmount = getTotalExpenseAmount(queryResult.data); + updateTotalExpenseAmount(totalExpenseAmount); + } + }, [queryResult.data, queryResult.isSuccess, updateTotalExpenseAmount]); + + return queryResult; +}; + +export default useRequestGetStepList; diff --git a/client/src/hooks/queries/useRequestPostAuthentication.ts b/client/src/hooks/queries/useRequestPostAuthentication.ts new file mode 100644 index 000000000..e533a501b --- /dev/null +++ b/client/src/hooks/queries/useRequestPostAuthentication.ts @@ -0,0 +1,23 @@ +import {useMutation} from '@tanstack/react-query'; +import {useNavigate} from 'react-router-dom'; + +import {requestPostAuthentication} from '@apis/request/auth'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const useRequestPostAuthenticate = () => { + const eventId = getEventIdByUrl(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: () => requestPostAuthentication({eventId}), + onError: () => { + // 에러가 발생하면 로그인 페이지로 리다이렉트 + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + }, + }); +}; + +export default useRequestPostAuthenticate; diff --git a/client/src/hooks/queries/useRequestPostBillList.ts b/client/src/hooks/queries/useRequestPostBillList.ts new file mode 100644 index 000000000..676da9d85 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostBillList.ts @@ -0,0 +1,27 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPostBillList} from '@apis/request/bill'; +import {Bill} from 'types/serviceType'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PostBillActionMutationProps { + billList: Bill[]; +} + +const useRequestPostBillList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({billList}: PostBillActionMutationProps) => requestPostBillList({eventId, billList}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPostBillList; diff --git a/client/src/hooks/queries/useRequestPostEvent.ts b/client/src/hooks/queries/useRequestPostEvent.ts new file mode 100644 index 000000000..5327710fc --- /dev/null +++ b/client/src/hooks/queries/useRequestPostEvent.ts @@ -0,0 +1,16 @@ +import {useMutation} from '@tanstack/react-query'; + +import {requestPostNewEvent} from '@apis/request/event'; + +interface PostEventMutationProps { + eventName: string; + password: number; +} + +const usePostEvent = () => { + return useMutation({ + mutationFn: ({eventName, password}: PostEventMutationProps) => requestPostNewEvent({eventName, password}), + }); +}; + +export default usePostEvent; diff --git a/client/src/hooks/queries/useRequestPostLogin.ts b/client/src/hooks/queries/useRequestPostLogin.ts new file mode 100644 index 000000000..21dce1791 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostLogin.ts @@ -0,0 +1,26 @@ +import {useMutation} from '@tanstack/react-query'; +import {useNavigate} from 'react-router-dom'; + +import {requestPostToken} from '@apis/request/auth'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +interface PostLoginMutationProps { + password: string; +} + +const useRequestPostLogin = () => { + const eventId = getEventIdByUrl(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: ({password}: PostLoginMutationProps) => requestPostToken({eventId, password}), + onSuccess: () => { + navigate(`${ROUTER_URLS.event}/${eventId}/admin`); + }, + }); +}; + +export default useRequestPostLogin; diff --git a/client/src/hooks/queries/useRequestPostMemberList.ts b/client/src/hooks/queries/useRequestPostMemberList.ts new file mode 100644 index 000000000..8ed69db08 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostMemberList.ts @@ -0,0 +1,37 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {MemberType} from 'types/serviceType'; +import {requestPostMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PostMemberListMutationProps { + type: MemberType; + memberNameList: string[]; +} + +const useRequestPostMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({type, memberNameList}: PostMemberListMutationProps) => + requestPostMemberList({eventId, type, memberNameList}), + // TODO: (@todari) : 낙관적 업데이트 적고 있었어용 + // onMutate: async ({type, memberNameList}) => { + // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.stepList]}); + // const previousStepList = queryClient.getQueryData([QUERY_KEYS.stepList]); + // queryClient.setQueryData([QUERY_KEYS.stepList], (prev: (MemberStep | BillStep)[]) => prev && { + // }); + // }, + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPostMemberList; diff --git a/client/src/hooks/queries/useRequestPutAllMemberList.ts b/client/src/hooks/queries/useRequestPutAllMemberList.ts new file mode 100644 index 000000000..d7e25ff73 --- /dev/null +++ b/client/src/hooks/queries/useRequestPutAllMemberList.ts @@ -0,0 +1,27 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {MemberChange, requestPutAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PutAllMemberListMutationProps { + members: MemberChange[]; +} + +const useRequestPutAllMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({members}: PutAllMemberListMutationProps) => requestPutAllMemberList({eventId, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPutAllMemberList; diff --git a/client/src/hooks/queries/useRequestPutBillAction.ts b/client/src/hooks/queries/useRequestPutBillAction.ts new file mode 100644 index 000000000..a58da8ea4 --- /dev/null +++ b/client/src/hooks/queries/useRequestPutBillAction.ts @@ -0,0 +1,29 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPutBillAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PutBillActionMutationProps { + actionId: number; + title: string; + price: number; +} + +const useRequestPutBillAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId, title, price}: PutBillActionMutationProps) => + requestPutBillAction({eventId, actionId, title, price}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPutBillAction; diff --git a/client/src/hooks/useAuth/useAuth.test.tsx b/client/src/hooks/useAuth/useAuth.test.tsx index 130aa73f2..ab520543f 100644 --- a/client/src/hooks/useAuth/useAuth.test.tsx +++ b/client/src/hooks/useAuth/useAuth.test.tsx @@ -1,4 +1,5 @@ import {renderHook, waitFor} from '@testing-library/react'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; import {act} from 'react'; import {MemoryRouter} from 'react-router-dom'; @@ -13,6 +14,13 @@ import {ErrorProvider} from '../useError/ErrorProvider'; import useAuth from './useAuth'; describe('useAuth', () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: 0, + }, + }, + }); const initializeProvider = () => renderHook( () => { @@ -20,9 +28,11 @@ describe('useAuth', () => { }, { wrapper: ({children}) => ( - <MemoryRouter> - <ErrorProvider>{children}</ErrorProvider> - </MemoryRouter> + <QueryClientProvider client={queryClient}> + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + </QueryClientProvider> ), }, ); diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx index ca595719a..00436cafa 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -1,13 +1,14 @@ import {renderHook, waitFor} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; import {act} from 'react'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; +import {ErrorProvider} from '@hooks/useError/ErrorProvider'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import stepListJson from '../../mocks/stepList.json'; -import StepListProvider, {useStepList} from '../useStepList/useStepList'; -import {ErrorProvider} from '../useError/ErrorProvider'; -import invalidMemberStepListJson from '../../mocks/invalidMemberStepList.json'; +import stepListJson from '@mocks/stepList.json'; +import invalidMemberStepListJson from '@mocks/invalidMemberStepList.json'; import useDeleteMemberAction from './useDeleteMemberAction'; @@ -21,11 +22,19 @@ for (let i = 0; i < stepListMockData.length; i++) { } describe('useDeleteMemberAction', () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: 0, + }, + }, + }); + const initializeProvider = (list: MemberAction[] = memberActionList) => renderHook( () => { return { - stepListResult: useStepList(), + stepListResult: useRequestGetStepList(), deleteMemberActionList: useDeleteMemberAction({ memberActionList: list, setIsBottomSheetOpened: () => {}, @@ -36,11 +45,11 @@ describe('useDeleteMemberAction', () => { }, { wrapper: ({children}) => ( - <MemoryRouter> - <ErrorProvider> - <StepListProvider>{children}</StepListProvider> - </ErrorProvider> - </MemoryRouter> + <QueryClientProvider client={queryClient}> + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + </QueryClientProvider> ), }, ); @@ -50,7 +59,7 @@ describe('useDeleteMemberAction', () => { // stepList 값이 채워지길 대기합니다. await waitFor(() => { - expect(result.current.stepListResult.stepList).not.toStrictEqual([]); + expect(result.current.stepListResult.data).not.toStrictEqual([]); }); act(() => { @@ -77,7 +86,7 @@ describe('useDeleteMemberAction', () => { // stepList 값이 채워지길 대기합니다. await waitFor(() => { - expect(result.current.stepListResult.stepList).not.toStrictEqual([]); + expect(result.current.stepListResult.data).not.toStrictEqual([]); }); await act(async () => { @@ -115,7 +124,7 @@ describe('useDeleteMemberAction', () => { // stepList 값이 채워지길 대기합니다. await waitFor(() => { - expect(result.current.stepListResult.stepList).not.toStrictEqual([]); + expect(result.current.stepListResult.data).not.toStrictEqual([]); }); await act(async () => { diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx index 323ee9be6..913087a59 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx @@ -2,9 +2,8 @@ import type {MemberAction} from 'types/serviceType'; import {useState} from 'react'; -import {requestDeleteMemberAction} from '@apis/request/member'; -import {useStepList} from '@hooks/useStepList/useStepList'; -import {useFetch} from '@hooks/useFetch/useFetch'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useRequestDeleteMemberAction from '@hooks/queries/useRequestDeleteMemberAction'; import getEventIdByUrl from '@utils/getEventIdByUrl'; @@ -21,22 +20,24 @@ const useDeleteMemberAction = ({ showToastAlreadyExistMemberAction, showToastExistSameMemberFromAfterStep, }: UseDeleteMemberActionProps) => { - const {stepList, refreshStepList} = useStepList(); + const {data: stepListData} = useRequestGetStepList(); + const stepList = stepListData ?? []; + const {mutate: deleteMemberActionMutate} = useRequestDeleteMemberAction(); + const [deleteActionList, setDeleteActionList] = useState<MemberAction[]>([]); + const eventId = getEventIdByUrl(); - const {fetch} = useFetch(); const deleteMemberAction = async (actionId: number) => { - await fetch({ - queryFunction: () => requestDeleteMemberAction({actionId, eventId}), - onSuccess: () => { - refreshStepList(); - setIsBottomSheetOpened(false); - }, - onError: () => { - setDeleteActionList([]); + deleteMemberActionMutate( + {actionId}, + { + onError: () => { + setDeleteActionList([]); + }, }, - }); + ); + setIsBottomSheetOpened(false); }; // TODO: (@cookie: 추후에 반복문으로 delete하는 것이 아니라 한 번에 모아서 delete 처리하기 (backend에 문의)) diff --git a/client/src/hooks/useEvent/useEvent.test.tsx b/client/src/hooks/useEvent/useEvent.test.tsx index 8e952a0db..c636d49f8 100644 --- a/client/src/hooks/useEvent/useEvent.test.tsx +++ b/client/src/hooks/useEvent/useEvent.test.tsx @@ -1,6 +1,7 @@ import {renderHook} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; import {act} from 'react'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; import {useError} from '@hooks/useError/useError'; @@ -14,6 +15,14 @@ import {ErrorProvider} from '../useError/ErrorProvider'; import useEvent from './useEvent'; describe('useEvent', () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: 0, + }, + }, + }); + const initializeProvider = () => renderHook( () => { @@ -21,9 +30,11 @@ describe('useEvent', () => { }, { wrapper: ({children}) => ( - <MemoryRouter> - <ErrorProvider>{children}</ErrorProvider> - </MemoryRouter> + <QueryClientProvider client={queryClient}> + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + </QueryClientProvider> ), }, ); diff --git a/client/src/hooks/useEvent/useEvent.tsx b/client/src/hooks/useEvent/useEvent.tsx index 736476e52..e58733fc0 100644 --- a/client/src/hooks/useEvent/useEvent.tsx +++ b/client/src/hooks/useEvent/useEvent.tsx @@ -1,3 +1,5 @@ +// TODO: (@todari) useEvent는 이제 쓰지 않긴 해요...! + import {RequestPostNewEvent, ResponsePostNewEvent, requestPostNewEvent} from '@apis/request/event'; import {useFetch} from '@hooks/useFetch/useFetch'; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index d7e2e40c3..02f738904 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -3,31 +3,27 @@ import type {Bill} from 'types/serviceType'; import {useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; -import {requestDeleteBillAction, requestPutBillAction} from '@apis/request/bill'; import {BillInputType, InputPair} from '@hooks/useDynamicBillActionInput'; -import getEventIdByUrl from '@utils/getEventIdByUrl'; - import {ERROR_MESSAGE} from '@constants/errorMessage'; -import {useStepList} from './useStepList/useStepList'; -import {useFetch} from './useFetch/useFetch'; +import usePutBillAction from './queries/useRequestPutBillAction'; +import useDeleteBillAction from './queries/useRequestDeleteBillAction'; const usePutAndDeleteBillAction = ( initialValue: InputPair, validateFunc: (inputPair: Bill) => ValidateResult, onClose: () => void, ) => { - const eventId = getEventIdByUrl(); - const {refreshStepList} = useStepList(); - const {fetch} = useFetch(); - const [inputPair, setInputPair] = useState<InputPair>(initialValue); const [canSubmit, setCanSubmit] = useState(false); const [errorInfo, setErrorInfo] = useState<Record<string, boolean>>({title: false, price: false}); const [errorMessage, setErrorMessage] = useState<string | null>(null); + const {mutate: putBillAction} = usePutBillAction(); + const {mutate: deleteBillAction} = useDeleteBillAction(); + const handleInputChange = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; @@ -89,23 +85,13 @@ const usePutAndDeleteBillAction = ( const {title, price} = inputPair; - await fetch({ - queryFunction: () => requestPutBillAction({eventId, actionId, title, price: Number(price)}), - onSuccess: () => { - refreshStepList(); - onClose(); - }, - }); + putBillAction({actionId, title, price: Number(price)}); + onClose(); }; const onDelete = async (actionId: number) => { - await fetch({ - queryFunction: () => requestDeleteBillAction({eventId, actionId}), - onSuccess: () => { - refreshStepList(); - onClose(); - }, - }); + deleteBillAction({actionId}); + onClose(); }; return { diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts index 04b334101..09f227b8e 100644 --- a/client/src/hooks/useSearchInMemberList.ts +++ b/client/src/hooks/useSearchInMemberList.ts @@ -1,9 +1,6 @@ -import {useEffect, useState} from 'react'; +import {useState} from 'react'; -import {requestGetCurrentInMemberList} from '@apis/request/member'; -import {useFetch} from '@hooks/useFetch/useFetch'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; +import useRequestGetCurrentInMemberList from './queries/useRequestGetCurrentInMemberList'; export type ReturnUseSearchInMemberList = { currentInputIndex: number; @@ -14,26 +11,15 @@ export type ReturnUseSearchInMemberList = { }; const useSearchInMemberList = (handleChange: (index: number, value: string) => void): ReturnUseSearchInMemberList => { - const eventId = getEventIdByUrl(); - - const {fetch} = useFetch(); const [currentInputIndex, setCurrentInputIndex] = useState(-1); // 서버에서 가져온 전체 리스트 - const [currentInMemberList, setCurrentInMemberList] = useState<Array<string>>([]); + const {data} = useRequestGetCurrentInMemberList(); + const currentInMemberList = data?.memberNames ?? []; // 검색된 리스트 (따로 둔 이유는 검색 후 클릭했을 때 리스트를 비워주어야하기 때문) const [filteredInMemberList, setFilteredInMemberList] = useState<Array<string>>([]); - useEffect(() => { - const getCurrentInMembers = async () => { - const currentInMemberListFromServer = await fetch({queryFunction: () => requestGetCurrentInMemberList(eventId)}); - setCurrentInMemberList(currentInMemberListFromServer.memberNames); - }; - - getCurrentInMembers(); - }, []); - const filterMatchItems = (keyword: string) => { if (keyword.trim() === '') return []; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx index 667f0bfb6..a2b0de89d 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx @@ -1,5 +1,6 @@ import {renderHook, waitFor} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; import reportListJson from '../../mocks/reportList.json'; import {ErrorProvider} from '../useError/ErrorProvider'; @@ -7,12 +8,22 @@ import {ErrorProvider} from '../useError/ErrorProvider'; import useSearchMemberReportList from './useSearchMemberReportList'; describe('useSearchMemberReportList', () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: 0, + }, + }, + }); + const initializeProvider = (name: string) => renderHook(() => useSearchMemberReportList({name}), { wrapper: ({children}) => ( - <MemoryRouter> - <ErrorProvider>{children}</ErrorProvider> - </MemoryRouter> + <QueryClientProvider client={queryClient}> + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + </QueryClientProvider> ), }); diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx index 98f682dc2..4a967e45c 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -1,44 +1,15 @@ -import type {MemberReport} from 'types/serviceType'; - -import {useEffect, useState} from 'react'; - -import {requestGetMemberReportList} from '@apis/request/report'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import {useFetch} from '../useFetch/useFetch'; +import useRequestGetMemberReportList from '@hooks/queries/useRequestGetMemberReportList'; type UseSearchMemberReportListParams = { name: string; }; const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { - const [memberReportList, setMemberReportList] = useState<MemberReport[]>([]); - const [memberReportSearchList, setMemberReportSearchList] = useState<MemberReport[]>([]); - const eventId = getEventIdByUrl(); - const {fetch} = useFetch(); - - useEffect(() => { - const fetchMemberReportList = async () => { - // TODO: (@weadie) cors 고쳐지면 주석 풀게요. - // TODO: (@weadie) eventId에 의존하는 두 개의 훅에 대한 리펙토링 필요 - - const memberReportListData = await fetch({queryFunction: () => requestGetMemberReportList({eventId})}); - setMemberReportList(memberReportListData); - }; - - fetchMemberReportList(); - }, []); - - // TODO: (@weadie) 글자가 완성될 때마다 아래 로직이 실행되어야 합니다. - useEffect(() => { - if (name === '') setMemberReportSearchList(memberReportList); - - setMemberReportSearchList(memberReportList.filter(memberReport => memberReport.name.includes(name))); - }, [name, memberReportList]); + const {data} = useRequestGetMemberReportList(); + const memberReportList = data ?? []; return { - memberReportSearchList, + memberReportSearchList: memberReportList.filter(memberReport => memberReport.name.includes(name)), }; }; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index 8811996cf..3ec5fac73 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -1,13 +1,12 @@ import {useEffect, useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; -import {MemberChange, requestDeleteAllMemberList, requestPutAllMemberList} from '@apis/request/member'; +import {MemberChange} from '@apis/request/member'; import isArraysEqual from '@utils/isArraysEqual'; -import getEventIdByUrl from '@utils/getEventIdByUrl'; -import {useStepList} from './useStepList/useStepList'; -import {useFetch} from './useFetch/useFetch'; +import useDeleteAllMemberList from './queries/useRequestDeleteAllMemberList'; +import usePutAllMemberList from './queries/useRequestPutAllMemberList'; interface UseSetAllMemberListProps { validateFunc: (name: string) => ValidateResult; @@ -27,9 +26,8 @@ const useSetAllMemberList = ({ const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); - const {refreshStepList} = useStepList(); - const eventId = getEventIdByUrl(); - const {fetch} = useFetch(); + const {mutate: deleteAllMemberList} = useDeleteAllMemberList(); + const {mutate: putAllMemberList} = usePutAllMemberList(); useEffect(() => { setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); @@ -71,23 +69,24 @@ const useSetAllMemberList = ({ const handleClickDeleteButton = async (index: number) => { const memberToDelete = editedAllMemberList[index]; - await fetch({ - queryFunction: () => requestDeleteAllMemberList({eventId, memberName: memberToDelete}), - onSuccess: () => { - setDeleteMemberList(prev => [...prev, memberToDelete]); - setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - - setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - refreshStepList(); + deleteAllMemberList( + {memberName: memberToDelete}, + { + onSuccess: () => { + setDeleteMemberList(prev => [...prev, memberToDelete]); + setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + }, }, - }); + ); + handleCloseAllMemberListModal(); }; const handlePutAllMemberList = async () => { // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) if (deleteMemberList.length > 0) { for (const deleteMember of deleteMemberList) { - await fetch({queryFunction: () => requestDeleteAllMemberList({eventId, memberName: deleteMember})}); + deleteAllMemberList({memberName: deleteMember}); } } @@ -100,13 +99,8 @@ const useSetAllMemberList = ({ }) .filter(item => item !== null); // null인 항목을 필터링하여 제거 - await fetch({ - queryFunction: () => requestPutAllMemberList({eventId, members: editedMemberName}), - onSuccess: () => { - refreshStepList(); - handleCloseAllMemberListModal(); - }, - }); + putAllMemberList({members: editedMemberName}); + handleCloseAllMemberListModal(); }; const changeErrorIndex = (index: number) => { diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts new file mode 100644 index 000000000..3a97a587b --- /dev/null +++ b/client/src/hooks/useSetEventPasswordPage.ts @@ -0,0 +1,60 @@ +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import {ROUTER_URLS} from '@constants/routerUrls'; +import RULE from '@constants/rule'; + +import usePostEvent from './queries/useRequestPostEvent'; + +const useSetEventPasswordPage = () => { + const [eventName, setEventName] = useState(''); + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const navigate = useNavigate(); + const location = useLocation(); + const {mutate: postEvent} = usePostEvent(); + + useEffect(() => { + if (!location.state) { + navigate(ROUTER_URLS.main); + } else { + setEventName(location.state.eventName); + } + }, []); + + const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + postEvent( + {eventName, password: parseInt(password)}, + { + onSuccess: data => { + navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId: data.eventId})}`, { + replace: true, + }); + }, + }, + ); + }; + + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (validation.isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + + return {submitPassword, errorMessage, password, handleChange, canSubmit}; +}; +export default useSetEventPasswordPage; diff --git a/client/src/hooks/useSetPassword.ts b/client/src/hooks/useSetPassword.ts deleted file mode 100644 index 7b24e70dc..000000000 --- a/client/src/hooks/useSetPassword.ts +++ /dev/null @@ -1,47 +0,0 @@ -import {useState} from 'react'; - -import validateEventPassword from '@utils/validate/validateEventPassword'; - -import RULE from '@constants/rule'; - -import {useFetch} from './useFetch/useFetch'; -import useEvent from './useEvent/useEvent'; - -const useSetPassword = (eventName: string) => { - const {fetch} = useFetch(); - const [password, setPassword] = useState(''); - const [errorMessage, setErrorMessage] = useState<string | null>(null); - const [canSubmit, setCanSubmit] = useState(false); - const {createNewEvent} = useEvent(); - - const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - - const {eventId} = await fetch({queryFunction: () => createNewEvent({eventName, password: parseInt(password)})}); - return eventId; - }; - - const handlePasswordChange = (event: React.ChangeEvent<HTMLInputElement>) => { - const newValue = event.target.value; - const {isValid, errorMessage} = validateEventPassword(newValue); - - setCanSubmit(newValue.length === RULE.maxEventPasswordLength); - setErrorMessage(errorMessage); - - if (isValid) { - setPassword(newValue); - } else { - event.target.value = password; - } - }; - - return { - password, - errorMessage, - canSubmit, - submitPassword, - handlePasswordChange, - }; -}; - -export default useSetPassword; diff --git a/client/src/hooks/useStepList/useStepList.test.tsx b/client/src/hooks/useStepList/useStepList.test.tsx deleted file mode 100644 index ae4cca978..000000000 --- a/client/src/hooks/useStepList/useStepList.test.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import {renderHook, waitFor} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; -import {act} from 'react'; - -import {Bill} from 'types/serviceType'; - -import StepListProvider, {useStepList} from '../useStepList/useStepList'; -import stepListJson from '../../mocks/stepList.json'; -import {ErrorProvider} from '../useError/ErrorProvider'; - -const stepListMockData = stepListJson; - -describe('useStepList', () => { - const initializeProvider = () => - renderHook( - () => { - return { - stepListResult: useStepList(), - }; - }, - { - wrapper: ({children}) => ( - <MemoryRouter> - <ErrorProvider> - <StepListProvider>{children}</StepListProvider> - </ErrorProvider> - </MemoryRouter> - ), - }, - ); - - const getMemberNameList = () => - stepListJson - .filter(({type}) => type !== 'BILL') - .map(({actions}) => actions.map(({name}) => name)) - .flat(); - - it('처음 호출하면 stepList 값을 요청해 받아온다.', async () => { - const {result} = initializeProvider(); - - await waitFor(() => expect(result.current.stepListResult.stepList).toStrictEqual(stepListMockData)); - }); - - it('처음 호출하면 모든 멤버의 목록을 요청해 받아온다.', async () => { - const {result} = initializeProvider(); - const allMemberList = getMemberNameList(); - - await waitFor(() => expect(result.current.stepListResult.allMemberList).toStrictEqual(allMemberList)); - }); - - it('지출 내역의 총액을 계산한다.', async () => { - const {result} = initializeProvider(); - const totalPrice = stepListJson.reduce((sum, {type, actions}) => { - if (type === 'BILL') { - return sum + actions.reduce((sum, {price}) => sum + price!, 0); - } - return sum; - }, 0); - - // 값이 세팅되기까지 대기하기 위함. 그래서 아래 한 줄 없으면 에러남 - await waitFor(() => expect(result.current.stepListResult.stepList).toStrictEqual(stepListMockData)); - - expect(result.current.stepListResult.getTotalPrice()).toStrictEqual(totalPrice); - }); - - it('들어옴 멤버를 추가한다.', async () => { - const {result} = initializeProvider(); - const type = 'IN'; - const memberNameList = ['망고젤리', '리치젤리']; - - const prevNameList = getMemberNameList(); - const updatedNameList = [...prevNameList, ...memberNameList]; - - await act(async () => result.current.stepListResult.updateMemberList({type, memberNameList})); - - expect(result.current.stepListResult.allMemberList).toStrictEqual(updatedNameList); - }); - - it('지출 내역을 새로 추가한다.', async () => { - const {result} = initializeProvider(); - const billList: Bill[] = [ - {title: '마라', price: 20000}, - {title: '엽떡', price: 1000}, - ]; - - const updatedStepList = [ - ...stepListJson, - { - type: 'BILL', - stepName: '밥스카이', - members: [], - actions: billList.map(({title, price}) => ({ - actionId: 999, - name: title, - price, - sequence: 999, - })), - }, - ]; - - await act(async () => result.current.stepListResult.addBill(billList, () => {})); - - expect(result.current.stepListResult.stepList).toStrictEqual(updatedStepList); - }); - - it('provider안에서 호출되지 않으면 에러를 던진다.', () => { - expect(() => { - const _ = renderHook(() => useStepList()); - }).toThrow('useStepList는 StepListProvider 내에서 사용되어야 합니다.'); - }); -}); diff --git a/client/src/hooks/useStepList/useStepList.tsx b/client/src/hooks/useStepList/useStepList.tsx deleted file mode 100644 index ffc05c59d..000000000 --- a/client/src/hooks/useStepList/useStepList.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import type {MemberType, Bill, BillAction, BillStep, MemberStep} from 'types/serviceType.ts'; - -import {PropsWithChildren, createContext, useContext, useEffect, useState} from 'react'; - -import {requestPostBillList} from '@apis/request/bill'; -import {requestGetAllMemberList, requestPostMemberList} from '@apis/request/member'; -import {requestGetStepList} from '@apis/request/stepList'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import {useFetch} from '../useFetch/useFetch'; - -interface StepListContextProps { - stepList: (BillStep | MemberStep)[]; - allMemberList: string[]; - getTotalPrice: () => number; - addBill: (billList: Bill[], onSuccess: () => void) => Promise<void>; - updateMemberList: ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => Promise<void>; - refreshStepList: () => Promise<void>; -} - -export const StepListContext = createContext<StepListContextProps | null>(null); // TODO: (@weadie) 인자를 어떻게 줘야 하는지 고민하기. - -const StepListProvider = ({children}: PropsWithChildren) => { - const {fetch} = useFetch(); - const [stepList, setStepList] = useState<(BillStep | MemberStep)[]>([]); - const [allMemberList, setAllMemberList] = useState<string[]>([]); - const eventId = getEventIdByUrl(); - - const refreshStepList = async () => { - const stepList = await fetch({queryFunction: () => requestGetStepList({eventId})}); - - getAllMemberList(); - setStepList(stepList); - }; - - useEffect(() => { - refreshStepList(); - }, []); - - const updateMemberList = async ({type, memberNameList}: {type: MemberType; memberNameList: string[]}) => { - await fetch({queryFunction: () => requestPostMemberList({eventId, type, memberNameList})}); - - refreshStepList(); - }; - - const getAllMemberList = async () => { - const allMembers = await requestGetAllMemberList({eventId}); - - setAllMemberList(allMembers.memberNames); - }; - - const addBill = async (billList: Bill[], onSuccess: () => void) => { - // TODO: (@weadie) 에러 처리 - await fetch({ - queryFunction: () => requestPostBillList({eventId, billList}), - onSuccess: () => { - refreshStepList(); - onSuccess(); - }, - }); - }; - - const calculateBillSum = (actions: BillAction[]) => { - return actions.reduce((sum, {price}) => sum + price, 0); - }; - - const getTotalPrice = () => { - return stepList.reduce((sum, {type, actions}) => { - if (type === 'BILL') { - return sum + calculateBillSum(actions); - } - return sum; - }, 0); - }; - - return ( - <StepListContext.Provider - value={{ - addBill, - getTotalPrice, - updateMemberList, - stepList, - allMemberList, - refreshStepList, - }} - > - {children} - </StepListContext.Provider> - ); -}; - -export const useStepList = () => { - const context = useContext(StepListContext); - - if (!context) { - throw new Error('useStepList는 StepListProvider 내에서 사용되어야 합니다.'); - } - return context; -}; - -export default StepListProvider; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index 8dfa6966f..fc6830467 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -1,5 +1,6 @@ import {useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; +import {css} from '@emotion/react'; import useSetEventName from '@hooks/useSetEventName'; @@ -21,7 +22,7 @@ const SetEventNamePage = () => { <Back /> </TopNav> <Title title="행사 이름 입력" description="시작할 행사 이름을 입력해 주세요." /> - <form onSubmit={submitEventName} style={{padding: '0 1rem'}}> + <form onSubmit={submitEventName} css={css({padding: '0 1rem'})}> <LabelInput labelText="행사 이름" errorText={errorMessage} diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 85bb44e0d..0a1fd7c5e 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -1,32 +1,12 @@ -import {useEffect} from 'react'; -import {useLocation, useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; -import useSetPassword from '@hooks/useSetPassword'; +import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; import RULE from '@constants/rule'; -import {ROUTER_URLS} from '@constants/routerUrls'; import {PASSWORD_LENGTH} from '@constants/password'; const SetEventPasswordPage = () => { - const navigate = useNavigate(); - const location = useLocation(); - - useEffect(() => { - if (!location.state) { - navigate(ROUTER_URLS.main); - } - }, [location.state]); - - const {password, errorMessage, canSubmit, submitPassword, handlePasswordChange} = useSetPassword( - location.state?.eventName, - ); - - const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => { - const eventId = await submitPassword(event); - - navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId})}`, {replace: true}); - }; + const {submitPassword, errorMessage, password, handleChange, canSubmit} = useSetEventPasswordPage(); return ( <MainLayout> @@ -37,7 +17,7 @@ const SetEventPasswordPage = () => { title="행사 비밀번호 설정" description={`행사 관리에 필요한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} /> - <form onSubmit={onSubmit} style={{padding: '0 1rem'}}> + <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> <LabelInput labelText="비밀번호" errorText={errorMessage} @@ -45,7 +25,7 @@ const SetEventPasswordPage = () => { type="secret" maxLength={RULE.maxEventPasswordLength} placeholder="비밀번호" - onChange={handlePasswordChange} + onChange={handleChange} isError={!!errorMessage} autoFocus /> diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 7ece41751..9fd10f8ef 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -4,32 +4,33 @@ import {useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; import {ModalBasedOnMemberCount} from '@components/Modal/index'; -import {useStepList} from '@hooks/useStepList/useStepList'; -import useAuth from '@hooks/useAuth/useAuth'; +import useRequestGetAllMemberList from '@hooks/queries/useRequestGetAllMemberList'; +import useRequestPostAuthenticate from '@hooks/queries/useRequestPostAuthentication'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; import {EventPageContextProps} from '../EventPageLayout'; import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; const AdminPage = () => { + const [isOpenFixedButtonBottomSheet, setIsOpenFixedButtonBottomSheet] = useState(false); + const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); + const {eventName} = useOutletContext<EventPageContextProps>(); + const {data: allMemberListData} = useRequestGetAllMemberList(); + const allMemberList = allMemberListData?.memberNames ?? []; - const [isOpenFixedButtonBottomSheet, setIsOpenFixedBottomBottomSheet] = useState(false); - const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); + const {totalExpenseAmount} = useTotalExpenseAmountStore(); - const {getTotalPrice, allMemberList} = useStepList(); - const {checkAuthentication} = useAuth(); + const {mutate: postAuthentication} = useRequestPostAuthenticate(); useEffect(() => { - const postAuth = async () => { - await checkAuthentication(); - }; - - postAuth(); - }, []); + postAuthentication(); + }, [postAuthentication]); const handleOpenAllMemberListButton = () => { - setIsOpenFixedBottomBottomSheet(prev => !prev); + setIsOpenFixedButtonBottomSheet(prev => !prev); setIsOpenAllMemberListButton(prev => !prev); }; @@ -43,7 +44,7 @@ const AdminPage = () => { return ( <> <div css={titleAndListButtonContainerStyle}> - <Title title={eventName} description={getTitleDescriptionByInitialMemberSetting()} price={getTotalPrice()} /> + <Title title={eventName} description={getTitleDescriptionByInitialMemberSetting()} price={totalExpenseAmount} /> {allMemberList.length !== 0 && ( <ListButton prefix="전체 참여자" @@ -56,12 +57,12 @@ const AdminPage = () => { <StepList /> <FixedButton children={allMemberList.length === 0 ? '시작인원 추가하기' : '행동 추가하기'} - onClick={() => setIsOpenFixedBottomBottomSheet(prev => !prev)} + onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} /> {isOpenFixedButtonBottomSheet && ( <ModalBasedOnMemberCount allMemberList={allMemberList} - setIsOpenBottomSheet={setIsOpenFixedBottomBottomSheet} + setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} isOpenBottomSheet={isOpenFixedButtonBottomSheet} isOpenAllMemberListButton={isOpenAllMemberListButton} setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index 721165f8e..974ad44d4 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,16 +1,12 @@ import {useState} from 'react'; -import {useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Switch} from 'haengdong-design'; import validateEventPassword from '@utils/validate/validateEventPassword'; -import useAuth from '@hooks/useAuth/useAuth'; +import useRequestPostLogin from '@hooks/queries/useRequestPostLogin'; import useNavSwitch from '@hooks/useNavSwitch'; -import getEventIdByUrl from '@utils/getEventIdByUrl'; - import RULE from '@constants/rule'; -import {ROUTER_URLS} from '@constants/routerUrls'; import {PASSWORD_LENGTH} from '@constants/password'; const EventLoginPage = () => { @@ -18,19 +14,12 @@ const EventLoginPage = () => { const {nav, paths, onChange} = useNavSwitch(); const [errorMessage, setErrorMessage] = useState(''); const [canSubmit, setCanSubmit] = useState(false); - const navigate = useNavigate(); - const eventId = getEventIdByUrl(); - const {loginUser} = useAuth(); + const {mutate: postLogin} = useRequestPostLogin(); const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); - try { - await loginUser({password}); - navigate(`${ROUTER_URLS.event}/${eventId}/admin`); - } catch (error) { - setErrorMessage('잘못된 비밀번호에요'); - } + postLogin({password}, {onError: () => setErrorMessage('비밀번호가 틀렸어요')}); }; const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 0c67454ac..589f9ab52 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,11 +1,9 @@ -import {MainLayout, TopNav, Switch, Button, Flex} from 'haengdong-design'; +import {MainLayout, TopNav, Switch, Button} from 'haengdong-design'; import {Outlet, useMatch} from 'react-router-dom'; -import {useEffect, useState} from 'react'; import CopyToClipboard from 'react-copy-to-clipboard'; -import {requestGetEventName} from '@apis/request/event'; -import StepListProvider from '@hooks/useStepList/useStepList'; import {useToast} from '@hooks/useToast/useToast'; +import useRequestGetEventName from '@hooks/queries/useRequestGetEventName'; import useNavSwitch from '@hooks/useNavSwitch'; @@ -16,31 +14,19 @@ import {ROUTER_URLS} from '@constants/routerUrls'; export type EventPageContextProps = { isAdmin: boolean; - eventId: string; eventName: string; }; const EventPageLayout = () => { const {nav, paths, onChange} = useNavSwitch(); - - const [eventName, setEventName] = useState(''); + const {data} = useRequestGetEventName(); + const eventName = data?.eventName ?? ''; const eventId = getEventIdByUrl(); - useEffect(() => { - const getEventName = async () => { - const {eventName} = await requestGetEventName({eventId: eventId}); - - setEventName(eventName); - }; - - getEventName(); - }, []); - const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; const outletContext: EventPageContextProps = { isAdmin, - eventId, eventName, }; @@ -48,30 +34,28 @@ const EventPageLayout = () => { const url = getEventPageUrlByEnvironment(eventId, 'home'); return ( - <StepListProvider> - <MainLayout backgroundColor="gray"> - <TopNav> - <Switch value={nav} values={paths} onChange={onChange} /> - <CopyToClipboard - text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\n${url}`} - onCopy={() => - showToast({ - showingTime: 3000, - message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', - type: 'confirm', - position: 'bottom', - bottom: '8rem', - }) - } - > - <Button size="small" variants="secondary"> - 정산 초대하기 - </Button> - </CopyToClipboard> - </TopNav> - <Outlet context={outletContext} /> - </MainLayout> - </StepListProvider> + <MainLayout backgroundColor="gray"> + <TopNav> + <Switch value={nav} values={paths} onChange={onChange} /> + <CopyToClipboard + text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\n${url}`} + onCopy={() => + showToast({ + showingTime: 3000, + message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', + type: 'confirm', + position: 'bottom', + bottom: '8rem', + }) + } + > + <Button size="small" variants="secondary"> + 정산 초대하기 + </Button> + </CopyToClipboard> + </TopNav> + <Outlet context={outletContext} /> + </MainLayout> ); }; diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 875bb4ff6..214526f39 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -3,17 +3,18 @@ import {useOutletContext} from 'react-router-dom'; import MemberReportList from '@components/MemberReportList/MemberReportList'; import StepList from '@components/StepList/StepList'; -import {useStepList} from '@hooks/useStepList/useStepList'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; import {EventPageContextProps} from '../EventPageLayout'; const HomePage = () => { const {eventName} = useOutletContext<EventPageContextProps>(); - const {getTotalPrice} = useStepList(); + const {totalExpenseAmount} = useTotalExpenseAmountStore(); return ( <div> - <Title title={eventName} price={getTotalPrice()} /> + <Title title={eventName} price={totalExpenseAmount} /> <Tabs tabsContainerStyle={{gap: '1rem'}}> <Tab label="전체 지출 내역" content={<StepList />} /> <Tab label="참여자 별 내역" content={<MemberReportList />} /> diff --git a/client/src/store/stepListStore.ts b/client/src/store/stepListStore.ts new file mode 100644 index 000000000..07f3b107f --- /dev/null +++ b/client/src/store/stepListStore.ts @@ -0,0 +1,16 @@ +import {create} from 'zustand'; + +import {ConvertedAction} from 'types/serviceType'; + +type State = { + stepList: ConvertedAction[]; +}; + +type Action = { + updateStepList: (stepList: State['stepList']) => void; +}; + +export const useStepListStore = create<State & Action>(set => ({ + stepList: [], + updateStepList: stepList => set(() => ({stepList})), +})); diff --git a/client/src/store/totalExpenseAmountStore.ts b/client/src/store/totalExpenseAmountStore.ts new file mode 100644 index 000000000..56b7587d4 --- /dev/null +++ b/client/src/store/totalExpenseAmountStore.ts @@ -0,0 +1,14 @@ +import {create} from 'zustand'; + +type State = { + totalExpenseAmount: number; +}; + +type Action = { + updateTotalExpenseAmount: (totalExpenseAmount: State['totalExpenseAmount']) => void; +}; + +export const useTotalExpenseAmountStore = create<State & Action>(set => ({ + totalExpenseAmount: 0, + updateTotalExpenseAmount: totalExpenseAmount => set(() => ({totalExpenseAmount})), +})); diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts index a668ee694..bddb36329 100644 --- a/client/src/types/serviceType.ts +++ b/client/src/types/serviceType.ts @@ -52,3 +52,17 @@ export type Member = { name: string; status: MemberType; }; + +export type ActionType = 'IN' | 'OUT' | 'BILL'; + +// export type StepList = { +// actions: Action[]; +// }; + +export type ConvertedAction = { + actionId: number; + name: string; + price: string | null; + sequence: number; + type: ActionType; +}; diff --git a/client/src/utils/caculateExpense.ts b/client/src/utils/caculateExpense.ts new file mode 100644 index 000000000..8b41af8c3 --- /dev/null +++ b/client/src/utils/caculateExpense.ts @@ -0,0 +1,14 @@ +import {BillAction, BillStep, MemberStep} from 'types/serviceType'; + +export const calculateStepExpense = (actions: BillAction[]) => { + return actions.reduce((sum, {price}) => sum + price, 0); +}; + +export const getTotalExpenseAmount = (stepList: (MemberStep | BillStep)[]) => { + return stepList.reduce((sum, {type, actions}) => { + if (type === 'BILL') { + return sum + calculateStepExpense(actions); + } + return sum; + }, 0); +}; diff --git a/client/src/utils/getEventIdByUrl.ts b/client/src/utils/getEventIdByUrl.ts index f52885215..1cdb16c8f 100644 --- a/client/src/utils/getEventIdByUrl.ts +++ b/client/src/utils/getEventIdByUrl.ts @@ -7,7 +7,7 @@ const extractEventIdFromUrl = (url: string) => { }; const getEventIdByUrl = () => { - return extractEventIdFromUrl(window.location.pathname) || ''; + return extractEventIdFromUrl(window.location.pathname) ?? ''; }; export default getEventIdByUrl; diff --git a/client/src/utils/groupActions.ts b/client/src/utils/groupActions.ts new file mode 100644 index 000000000..a6347167d --- /dev/null +++ b/client/src/utils/groupActions.ts @@ -0,0 +1,27 @@ +import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; + +import stepListToAction from './stepListToActions'; + +const groupActions = (stepList: (BillStep | MemberStep)[]) => { + const actions = stepListToAction(stepList); + const groupedActions: ConvertedAction[][] = []; + + let group: ConvertedAction[] = []; + + actions.forEach((action, index) => { + if (group.length === 0 || group[group.length - 1].type === action.type) { + group.push(action); + } else { + groupedActions.push(group); + group = []; + } + + if (index === actions.length - 1) { + groupedActions.push(group); + } + }); + + return groupedActions; +}; + +export default groupActions; diff --git a/client/src/utils/stepListToActions.ts b/client/src/utils/stepListToActions.ts new file mode 100644 index 000000000..5fe1bb3a7 --- /dev/null +++ b/client/src/utils/stepListToActions.ts @@ -0,0 +1,23 @@ +import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; + +const stepListToAction = (stepList: (BillStep | MemberStep)[]) => { + // (@todari) test용이라 임시로 any 사용할게용... + // Action을 사용하려고 하는데 serviceType의 기존 Action이랑 겹쳐서요~~~ + const actions: ConvertedAction[] = []; + + stepList.forEach(step => { + step.actions.forEach(action => { + actions.push({ + actionId: action.actionId, + name: action.name, + price: action.price ? action.price.toLocaleString() : null, + sequence: action.sequence, + type: step.type, + }); + }); + }); + + return actions; +}; + +export default stepListToAction; diff --git a/client/tsconfig.json b/client/tsconfig.json index 8b7b30d14..84c7c054a 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -39,6 +39,7 @@ "@assets/*": ["assets/*"], "@components/*": ["components/*"], "@constants/*": ["constants/*"], + "@store/*": ["store/*"], "@hooks/*": ["hooks/*"], "@mocks/*": ["mocks/*"], "@pages/*": ["pages/*"], diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs index 252a5b0ca..0312afe36 100644 --- a/client/webpack.common.mjs +++ b/client/webpack.common.mjs @@ -17,6 +17,7 @@ export default { '@components': path.resolve(__dirname, 'src/components/'), '@constants': path.resolve(__dirname, 'src/constants/'), '@hooks': path.resolve(__dirname, 'src/hooks/'), + '@store': path.resolve(__dirname, 'src/store/'), '@mocks': path.resolve(__dirname, 'src/mocks/'), '@pages': path.resolve(__dirname, 'src/pages/'), '@utils': path.resolve(__dirname, 'src/utils/'), From 7f01ba50ad9533a21b0eb8c6e812d2302af9ab94 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Mon, 19 Aug 2024 17:15:36 +0900 Subject: [PATCH 172/273] =?UTF-8?q?fix:=20valideMemberName=EC=9D=98=20?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=EB=AC=B8=20name=EC=9D=80=201=20=EC=9D=B4?= =?UTF-8?q?=ED=95=98=EC=9D=BC=20=EC=88=98=20=EC=97=86=EB=8B=A4=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20(#396)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> --- client/src/hooks/useDynamicInput.tsx | 2 +- client/src/utils/validate/validateMemberName.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index cd639d770..b19f09c80 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -44,7 +44,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return const handleInputChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; - + console.log(value); makeNewInputWhenFirstCharacterInput(index, value); handleChange(index, value); }; diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts index e73f42271..bb87122a2 100644 --- a/client/src/utils/validate/validateMemberName.ts +++ b/client/src/utils/validate/validateMemberName.ts @@ -12,7 +12,7 @@ const validateMemberName = (name: string): ValidateResult => { }; const validateLength = () => { - if (name.length > RULE.maxMemberNameLength || name.length < 1) return false; + if (name.length > RULE.maxMemberNameLength) return false; return true; }; From a5fc0f5fb15feea60b1a8aee9d5de8ec2041f383 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:23:13 +0900 Subject: [PATCH 173/273] =?UTF-8?q?feat:=20=EC=B4=9D=EC=95=A1=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=A1=9C=EC=A7=81=EC=9D=84=20sto?= =?UTF-8?q?re=EC=95=88=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20(#401)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 --- client/src/hooks/queries/useRequestGetStepList.ts | 4 +--- client/src/store/totalExpenseAmountStore.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/client/src/hooks/queries/useRequestGetStepList.ts b/client/src/hooks/queries/useRequestGetStepList.ts index d4357974f..7dfc1799c 100644 --- a/client/src/hooks/queries/useRequestGetStepList.ts +++ b/client/src/hooks/queries/useRequestGetStepList.ts @@ -6,7 +6,6 @@ import {requestGetStepList} from '@apis/request/stepList'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; import getEventIdByUrl from '@utils/getEventIdByUrl'; -import {getTotalExpenseAmount} from '@utils/caculateExpense'; import QUERY_KEYS from '@constants/queryKeys'; @@ -21,8 +20,7 @@ const useRequestGetStepList = () => { useEffect(() => { if (queryResult.isSuccess && queryResult.data) { - const totalExpenseAmount = getTotalExpenseAmount(queryResult.data); - updateTotalExpenseAmount(totalExpenseAmount); + updateTotalExpenseAmount(queryResult.data); } }, [queryResult.data, queryResult.isSuccess, updateTotalExpenseAmount]); diff --git a/client/src/store/totalExpenseAmountStore.ts b/client/src/store/totalExpenseAmountStore.ts index 56b7587d4..e9ebcf52a 100644 --- a/client/src/store/totalExpenseAmountStore.ts +++ b/client/src/store/totalExpenseAmountStore.ts @@ -1,14 +1,18 @@ import {create} from 'zustand'; +import {BillStep, MemberStep} from 'types/serviceType'; + +import {getTotalExpenseAmount} from '@utils/caculateExpense'; + type State = { totalExpenseAmount: number; }; type Action = { - updateTotalExpenseAmount: (totalExpenseAmount: State['totalExpenseAmount']) => void; + updateTotalExpenseAmount: (stepList: (MemberStep | BillStep)[]) => void; }; export const useTotalExpenseAmountStore = create<State & Action>(set => ({ totalExpenseAmount: 0, - updateTotalExpenseAmount: totalExpenseAmount => set(() => ({totalExpenseAmount})), + updateTotalExpenseAmount: stepList => set({totalExpenseAmount: getTotalExpenseAmount(stepList)}), })); From abab410c1acf158b1eb5967bcd48cc6caf5271d5 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:23:42 +0900 Subject: [PATCH 174/273] =?UTF-8?q?fix:=20action=20log=EA=B0=80=20?= =?UTF-8?q?=EA=B8=B8=EC=96=B4=EC=A7=88=20=EB=95=8C=20heigth=20=EC=9E=98?= =?UTF-8?q?=EB=A6=AC=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#408)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/GlobalStyle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index 2df05e939..e12b5f693 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -136,7 +136,7 @@ export const GlobalStyle = css` body { max-width: 768px; - height: 100lvh; + height: 100%; margin: 0 auto; overflow-y: scroll; From 24788ae6012a1eda2b8ef056e340f8c3eeaa8315 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:24:04 +0900 Subject: [PATCH 175/273] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EC=9D=B8?= =?UTF-8?q?=EC=9B=90=20=EC=88=98=EC=A0=95=20'=EC=82=AD=EC=A0=9C'=20api=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=A1=A4=EB=B0=B1=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#409)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 --- client/src/hooks/useDynamicInput.tsx | 2 +- client/src/hooks/useInput.tsx | 4 ++ client/src/hooks/useSetAllMemberList.tsx | 84 ++++++++---------------- 3 files changed, 34 insertions(+), 56 deletions(-) diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index b19f09c80..cd639d770 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -44,7 +44,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return const handleInputChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; - console.log(value); + makeNewInputWhenFirstCharacterInput(index, value); handleChange(index, value); }; diff --git a/client/src/hooks/useInput.tsx b/client/src/hooks/useInput.tsx index 1b90805a2..a6901573b 100644 --- a/client/src/hooks/useInput.tsx +++ b/client/src/hooks/useInput.tsx @@ -35,6 +35,10 @@ const useInput = <T extends InputValue>({validateFunc, initialInputList}: UseInp changeCanSubmit(); }, [errorMessage, errorIndexList]); + useEffect(() => { + setInputList(prev => prev.map((value, index) => ({...value, index}))); + }, [inputList.length]); + const handleChange = (index: number = 0, value: string) => { const {isValid, errorMessage: validationResultMessage} = validateFunc(value); diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index 3ec5fac73..eda5a3f81 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -7,6 +7,7 @@ import isArraysEqual from '@utils/isArraysEqual'; import useDeleteAllMemberList from './queries/useRequestDeleteAllMemberList'; import usePutAllMemberList from './queries/useRequestPutAllMemberList'; +import useInput from './useInput'; interface UseSetAllMemberListProps { validateFunc: (name: string) => ValidateResult; @@ -14,72 +15,56 @@ interface UseSetAllMemberListProps { handleCloseAllMemberListModal: () => void; } +interface UseSetAllMemberListReturns { + editedAllMemberList: string[]; + canSubmit: boolean; + errorMessage: string; + errorIndexList: number[]; + handleNameChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; + handleClickDeleteButton: (index: number) => Promise<void>; + handlePutAllMemberList: () => Promise<void>; +} + const useSetAllMemberList = ({ validateFunc, allMemberList, handleCloseAllMemberListModal, -}: UseSetAllMemberListProps) => { - const [editedAllMemberList, setEditedAllMemberList] = useState<string[]>(allMemberList); - const [errorMessage, setErrorMessage] = useState(''); - const [errorIndexList, setErrorIndexList] = useState<number[]>([]); - const [canSubmit, setCanSubmit] = useState(false); +}: UseSetAllMemberListProps): UseSetAllMemberListReturns => { + const initialInputList = allMemberList.map((name, index) => ({index, value: name})); + const { + inputList, + errorMessage, + errorIndexList, + canSubmit, + handleChange, + setInputList: setEditedAllMemberList, + setCanSubmit, + } = useInput({validateFunc, initialInputList}); + const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); const {mutate: deleteAllMemberList} = useDeleteAllMemberList(); const {mutate: putAllMemberList} = usePutAllMemberList(); + const editedAllMemberList = inputList.map(input => input.value); + useEffect(() => { setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); }, [editedAllMemberList]); const handleNameChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; - const {isValid, errorMessage: validationResultMessage} = validateFunc(value); - - if (isValid && value.length !== 0) { - setErrorMessage(''); - - setEditedAllMemberList(prev => { - const newList = [...prev]; - newList[index] = value; - return newList; - }); - - setErrorIndexList(prev => prev.filter(i => i !== index)); - setCanSubmit(true); - } else if (value.length === 0) { - setErrorMessage(''); - - setEditedAllMemberList(prev => { - const newList = [...prev]; - newList[index] = value; - return newList; - }); - - changeErrorIndex(index); - } else { - setErrorMessage(validationResultMessage ?? ''); - - changeErrorIndex(index); - } + handleChange(index, value); }; const handleClickDeleteButton = async (index: number) => { const memberToDelete = editedAllMemberList[index]; - deleteAllMemberList( - {memberName: memberToDelete}, - { - onSuccess: () => { - setDeleteMemberList(prev => [...prev, memberToDelete]); - setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - }, - }, - ); - handleCloseAllMemberListModal(); + setDeleteMemberList(prev => [...prev, memberToDelete]); + setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); }; const handlePutAllMemberList = async () => { @@ -98,20 +83,10 @@ const useSetAllMemberList = ({ return null; // 조건에 맞지 않으면 null을 반환 }) .filter(item => item !== null); // null인 항목을 필터링하여 제거 - putAllMemberList({members: editedMemberName}); handleCloseAllMemberListModal(); }; - const changeErrorIndex = (index: number) => { - setErrorIndexList(prev => { - if (!prev.includes(index)) { - return [...prev, index]; - } - return prev; - }); - }; - return { editedAllMemberList, canSubmit, @@ -122,5 +97,4 @@ const useSetAllMemberList = ({ handlePutAllMemberList, }; }; - export default useSetAllMemberList; From 17b331431ac6a9730544875778ef8e86c773fb23 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:25:33 +0900 Subject: [PATCH 176/273] =?UTF-8?q?feat:=20EditableItem.Input=EC=9D=B4=20?= =?UTF-8?q?=EB=8F=99=EC=A0=81=EC=9D=B8=20width=EB=A5=BC=20=EA=B0=96?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#411)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- HDesign/package-lock.json | 5 +- HDesign/package.json | 2 +- .../EditableItem/EditableItem.Input.style.ts | 85 ++++--- .../EditableItem/EditableItem.Input.tsx | 46 +++- .../EditableItem/EditableItem.Input.type.ts | 6 +- .../EditableItem.input.stories.tsx | 1 + .../EditableItem/EditableItem.stories.tsx | 236 +++++++++++++++++- .../EditableItem/EditableItem.style.ts | 7 + .../components/EditableItem/EditableItem.tsx | 24 +- .../EditableItem/EditableItem.type.ts | 4 +- HDesign/src/type/withTheme.ts | 5 + client/src/components/StepList/StepList.tsx | 3 - 12 files changed, 366 insertions(+), 58 deletions(-) create mode 100644 HDesign/src/type/withTheme.ts diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 274804d74..14b7563a3 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,13 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.74", + "version": "0.1.76", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.74", - + "version": "0.1.76", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index e01107490..e26c96ddd 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.74", + "version": "0.1.76", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts index fc346d77b..1dbe0ca71 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts +++ b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts @@ -1,49 +1,29 @@ import {css} from '@emotion/react'; import {TextSize} from '@components/Text/Text.type'; - -import {Theme} from '@theme/theme.type'; +import {WithTheme} from '@type/withTheme'; import TYPOGRAPHY from '@token/typography'; -interface InputWrapperStyleProps { - theme: Theme; +type UnderlineProps = { hasFocus: boolean; hasError: boolean; -} - -interface InputStyleProps { - theme: Theme; - textSize: TextSize; -} +}; -interface InputSizeStyleProps { +type InputSizeStyleProps = { textSize: TextSize; -} +}; -interface InputBaseStyleProps { - theme: Theme; -} +type InputStyleProps = InputSizeStyleProps; -export const inputWrapperStyle = ({theme, hasFocus, hasError}: InputWrapperStyleProps) => - css({ - position: 'relative', - display: 'inline-block', - - '&::after': { - content: '""', - position: 'absolute', - left: 0, - right: 0, - bottom: 0, - height: '0.125rem', - backgroundColor: hasFocus ? theme.colors.primary : hasError ? theme.colors.error : 'transparent', - transition: 'background-color 0.2s', - transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - }, - }); +export const inputWrapperStyle = css({ + display: 'inline-block', +}); -export const inputStyle = ({theme, textSize}: InputStyleProps) => [inputSizeStyle({textSize}), inputBaseStyle({theme})]; +export const inputStyle = ({theme, textSize}: WithTheme<InputStyleProps>) => [ + inputSizeStyle({textSize}), + inputBaseStyle({theme}), +]; const inputSizeStyle = ({textSize}: InputSizeStyleProps) => { const style = { @@ -62,14 +42,49 @@ const inputSizeStyle = ({textSize}: InputSizeStyleProps) => { return [style[textSize]]; }; -const inputBaseStyle = ({theme}: InputBaseStyleProps) => +const inputBaseStyle = ({theme}: WithTheme) => css({ border: 'none', outline: 'none', paddingBottom: '0.125rem', color: theme.colors.black, + '&:placeholder': { - color: theme.colors.gray, + color: theme.colors.darkGray, + }, + }); + +export const editingContainerStyle = css({ + opacity: 0, + whiteSpace: 'pre', + position: 'absolute', + pointerEvents: 'none', + padding: 0, + margin: 0, +}); + +export const isFixedIconStyle = ({theme}: WithTheme) => + css({ + color: theme.colors.error, + paddingRight: '0.25rem', + }); + +export const underlineStyle = ({theme, hasFocus, hasError}: WithTheme<UnderlineProps>) => + css({ + position: 'relative', + display: 'inline-block', + + '&::after': { + content: '""', + position: 'absolute', + + left: 0, + right: 0, + bottom: 0, + height: '0.125rem', + backgroundColor: hasFocus ? theme.colors.primary : hasError ? theme.colors.error : 'transparent', + transition: 'background-color 0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', }, }); diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/HDesign/src/components/EditableItem/EditableItem.Input.tsx index b6af0c144..10381fbed 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.tsx +++ b/HDesign/src/components/EditableItem/EditableItem.Input.tsx @@ -1,25 +1,57 @@ /** @jsxImportSource @emotion/react */ -import React, {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; +import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; -import {InputProps} from '@components/EditableItem/EditableItem.Input.type'; +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; import {useTheme} from '@theme/HDesignProvider'; -import {inputStyle, inputWrapperStyle} from './EditableItem.Input.style'; +import { + editingContainerStyle, + inputStyle, + inputWrapperStyle, + isFixedIconStyle, + underlineStyle, +} from './EditableItem.Input.style'; +import {InputProps} from './EditableItem.Input.type'; import useEditableItemInput from './useEditableItemInput'; -export const EditableItemInput: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( - {textSize = 'body', hasError = false, ...htmlProps}, +export const EditableItemInput = forwardRef<HTMLInputElement, InputProps>(function Input( + {isFixed = false, textSize = 'body', hasError = false, readOnly = false, ...htmlProps}, ref, ) { const {theme} = useTheme(); const inputRef = useRef<HTMLInputElement>(null); + const shadowRef = useRef<HTMLDivElement>(null); const {hasFocus} = useEditableItemInput({inputRef}); useImperativeHandle(ref, () => inputRef.current!); + useEffect(() => { + if (shadowRef.current && inputRef.current) { + inputRef.current.style.width = `${shadowRef.current.offsetWidth}px`; + } + }, [htmlProps.value]); + return ( - <div css={inputWrapperStyle({theme, hasFocus, hasError})}> - <input css={inputStyle({theme, textSize})} ref={inputRef} {...htmlProps} /> + <div css={inputWrapperStyle}> + <Flex flexDirection="row"> + <div ref={shadowRef} css={editingContainerStyle}> + <Text size={textSize}>{htmlProps.value || htmlProps.placeholder}</Text> + </div> + {isFixed && <div css={isFixedIconStyle({theme})}>*</div>} + <div css={underlineStyle({theme, hasError, hasFocus})}> + <input + css={inputStyle({ + theme, + textSize, + })} + ref={inputRef} + readOnly={readOnly} + {...htmlProps} + placeholder={htmlProps.placeholder} + /> + </div> + </Flex> </div> ); }); diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.type.ts b/HDesign/src/components/EditableItem/EditableItem.Input.type.ts index 5d58238e8..8fdd3d64a 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.type.ts +++ b/HDesign/src/components/EditableItem/EditableItem.Input.type.ts @@ -7,7 +7,11 @@ export interface InputStyleProps { textSize?: TextSize; } -export interface InputCustomProps {} +export interface InputCustomProps { + isFixed?: boolean; + value: string | number; + readOnly?: boolean; +} export interface InputStylePropsWithTheme extends InputStyleProps { theme: Theme; diff --git a/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx index a23483b78..370d07c89 100644 --- a/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx +++ b/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx @@ -26,6 +26,7 @@ const meta = { textSize: 'body', hasError: false, autoFocus: true, + value: '값', }, } satisfies Meta<typeof EditableItemInput>; diff --git a/HDesign/src/components/EditableItem/EditableItem.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.stories.tsx index 976a4aa90..38406727e 100644 --- a/HDesign/src/components/EditableItem/EditableItem.stories.tsx +++ b/HDesign/src/components/EditableItem/EditableItem.stories.tsx @@ -1,6 +1,8 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; +import {useState} from 'react'; + import EditableItem from '@components/EditableItem/EditableItem'; import Flex from '@components/Flex/Flex'; import Text from '@components/Text/Text'; @@ -26,19 +28,249 @@ export default meta; type Story = StoryObj<typeof meta>; export const Playground: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + <EditableItem + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={value} + onChange={e => setValue(e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={value2} + onChange={e => setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const WithLabel: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + <EditableItem + prefixLabelText="라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={value} + onChange={e => setValue(e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={value2} + onChange={e => setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const WithLabelAndIsFixedIcon: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + <EditableItem + prefixLabelText="라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={value} + onChange={e => setValue(e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={value2} + onChange={e => setValue2(e.target.value)} + isFixed={true} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const WithLabels: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + <EditableItem + prefixLabelText="왼쪽 라벨" + suffixLabelText="오른쪽 라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={value} + onChange={e => setValue(e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={value2} + onChange={e => setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const ReadOnly: Story = { + render: ({...args}) => { + return ( + <EditableItem + prefixLabelText="왼쪽 라벨" + suffixLabelText="오른쪽 라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={'훠궈무한리필'} + readOnly + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={'10000'} + readOnly + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const ReadOnlyWithIsFixedIcon: Story = { render: ({...args}) => { return ( <EditableItem + prefixLabelText="왼쪽 라벨" + suffixLabelText="오른쪽 라벨" backgroundColor={args.backgroundColor} onFocus={() => console.log('focus')} onBlur={() => console.log('blur')} > - <EditableItem.Input placeholder="지출 내역" textSize="bodyBold"></EditableItem.Input> + <EditableItem.Input + value={'훠궈무한리필'} + readOnly + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> <Flex gap="0.25rem" alignItems="center"> - <EditableItem.Input placeholder="0" type="number" style={{textAlign: 'right'}}></EditableItem.Input> + <EditableItem.Input + isFixed + value={'10000'} + readOnly + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> <Text size="caption">원</Text> </Flex> </EditableItem> ); }, }; + +export const ListView: Story = { + render: ({...args}) => { + const LENGTH = 5; + const [valueList, setValueList] = useState(new Array(LENGTH).fill('')); + const [valueList2, setValueList2] = useState(new Array(LENGTH).fill('')); + + const handleValueListChange = (index: number, newValue: string) => { + const updatedList = [...valueList]; + updatedList[index] = newValue; + setValueList(updatedList); + }; + + const handleValueList2Change = (index: number, newValue: string) => { + const updatedList = [...valueList2]; + updatedList[index] = newValue; + setValueList2(updatedList); + }; + + return ( + <EditableItem + prefixLabelText="라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <Flex flexDirection="column" width="100%" gap="1rem"> + {valueList.map((value, index) => ( + <Flex key={index} justifyContent="spaceBetween"> + <EditableItem.Input + value={value} + onChange={e => handleValueListChange(index, e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={valueList2[index]} + onChange={e => handleValueList2Change(index, e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </Flex> + ))} + </Flex> + </EditableItem> + ); + }, +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.style.ts b/HDesign/src/components/EditableItem/EditableItem.style.ts index c817e5f7d..a0fe3ca2a 100644 --- a/HDesign/src/components/EditableItem/EditableItem.style.ts +++ b/HDesign/src/components/EditableItem/EditableItem.style.ts @@ -12,3 +12,10 @@ export const editableItemStyle = (theme: Theme, backgroundColor: ColorKeys) => borderRadius: '0.5rem', backgroundColor: theme.colors[backgroundColor], }); + +export const labelTextStyle = (theme: Theme, side: 'prefix' | 'suffix') => + css({ + color: theme.colors.gray, + paddingLeft: side === 'prefix' ? '0.375rem' : 0, + paddingRight: side === 'suffix' ? '0.375rem' : 0, + }); diff --git a/HDesign/src/components/EditableItem/EditableItem.tsx b/HDesign/src/components/EditableItem/EditableItem.tsx index cc1892370..f8b9ca434 100644 --- a/HDesign/src/components/EditableItem/EditableItem.tsx +++ b/HDesign/src/components/EditableItem/EditableItem.tsx @@ -1,9 +1,10 @@ /** @jsxImportSource @emotion/react */ -import React, {useEffect} from 'react'; +import Text from '@components/Text/Text'; +import Flex from '@components/Flex/Flex'; import {useTheme} from '@theme/HDesignProvider'; -import {editableItemStyle} from './EditableItem.style'; +import {editableItemStyle, labelTextStyle} from './EditableItem.style'; import EditableItemInput from './EditableItem.Input'; import {EditableItemProps} from './EditableItem.type'; import {EditableItemProvider} from './EditableItem.context'; @@ -12,6 +13,8 @@ import useEditableItem from './useEditableItem'; const EditableItemBase = ({ onInputFocus, onInputBlur, + prefixLabelText, + suffixLabelText, backgroundColor = 'white', children, ...htmlProps @@ -21,9 +24,20 @@ const EditableItemBase = ({ useEditableItem({onInputFocus, onInputBlur}); return ( - <div css={editableItemStyle(theme, backgroundColor)} {...htmlProps}> - {children} - </div> + <Flex flexDirection="column"> + <Flex justifyContent="spaceBetween" width="100%"> + <Text size="caption" css={labelTextStyle(theme, 'prefix')}> + {prefixLabelText} + </Text> + <Text size="caption" css={labelTextStyle(theme, 'suffix')}> + {suffixLabelText} + </Text> + </Flex> + + <div css={editableItemStyle(theme, backgroundColor)} {...htmlProps}> + {children} + </div> + </Flex> ); }; diff --git a/HDesign/src/components/EditableItem/EditableItem.type.ts b/HDesign/src/components/EditableItem/EditableItem.type.ts index b19a76427..a56835855 100644 --- a/HDesign/src/components/EditableItem/EditableItem.type.ts +++ b/HDesign/src/components/EditableItem/EditableItem.type.ts @@ -3,12 +3,14 @@ import {Theme} from '@theme/theme.type'; import {ColorKeys} from '@token/colors'; export interface EditableItemStyleProps { - backgroundColor: ColorKeys; + backgroundColor?: ColorKeys; } export interface EditableItemCustomProps { onInputFocus?: () => void; onInputBlur?: () => void; + prefixLabelText?: string; + suffixLabelText?: string; } export interface EditableItemStylePropsWithTheme extends EditableItemStyleProps { diff --git a/HDesign/src/type/withTheme.ts b/HDesign/src/type/withTheme.ts new file mode 100644 index 000000000..bae8dc318 --- /dev/null +++ b/HDesign/src/type/withTheme.ts @@ -0,0 +1,5 @@ +import {Theme} from '@theme/theme.type'; + +export type WithTheme<P = unknown> = P & { + theme: Theme; +}; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 3d37788cf..be9f40998 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -6,12 +6,9 @@ import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; import Step from './Step'; const StepList = () => { - // const {stepList} = useStepList(); - const {data: stepListData} = useRequestGetStepList(); const stepList = stepListData ?? ([] as (MemberStep | BillStep)[]); - // TODO: (@weadie) if else 구문이 지저분하므로 리펙터링이 필요합니다. return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> {stepList.map((step, index) => ( From 3dbbc6590c4156d209132fdb03af12ec588b58cf Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:56:35 +0900 Subject: [PATCH 177/273] =?UTF-8?q?feat:=20=EC=B0=A8=EB=93=B1=20=EC=A0=95?= =?UTF-8?q?=EC=82=B0=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EB=B0=8F?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1=20(#406)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 --- client/src/apis/request/bill.ts | 37 ++- client/src/constants/queryKeys.ts | 1 + .../useRequestGetMemberReportListInAction.ts | 24 ++ .../useRequestPutMemberReportListInAction.ts | 29 ++ .../useDeleteMemberAction.test.tsx | 1 + .../useMemberReportInput.tsx | 57 ++++ .../useMemberReportListInAction.test.tsx | 302 ++++++++++++++++++ .../useMemberReportListInAction.ts | 100 ++++++ client/src/mocks/handlers.ts | 10 +- .../handlers/memberReportInActionHandlers.ts | 35 ++ client/src/mocks/handlers/stepListHandler.ts | 2 + client/src/mocks/invalidMemberStepList.json | 27 +- client/src/mocks/memberActionStepList.json | 6 +- .../src/mocks/memberReportListInAction.json | 6 + client/src/mocks/stepList.json | 27 +- client/src/types/serviceType.ts | 5 + .../validate/validateMemberReportInAction.ts | 41 +++ 17 files changed, 682 insertions(+), 28 deletions(-) create mode 100644 client/src/hooks/queries/useRequestGetMemberReportListInAction.ts create mode 100644 client/src/hooks/queries/useRequestPutMemberReportListInAction.ts create mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx create mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx create mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts create mode 100644 client/src/mocks/handlers/memberReportInActionHandlers.ts create mode 100644 client/src/mocks/memberReportListInAction.json create mode 100644 client/src/utils/validate/validateMemberReportInAction.ts diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index dbf2fdd45..418429d33 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -1,8 +1,8 @@ -import type {Bill} from 'types/serviceType'; +import type {Bill, MemberReportInAction} from 'types/serviceType'; import {BASE_URL} from '@apis/baseUrl'; import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestDelete, requestPostWithoutResponse, requestPut} from '@apis/fetcher'; +import {requestDelete, requestGet, requestPostWithoutResponse, requestPut} from '@apis/fetcher'; import {WithEventId} from '@apis/withEventId.type'; type RequestPostBillList = { @@ -19,20 +19,18 @@ export const requestPostBillList = async ({eventId, billList}: WithEventId<Reque }); }; -type RequestDeleteBillAction = { +type RequestBillAction = { actionId: number; }; -export const requestDeleteBillAction = async ({eventId, actionId}: WithEventId<RequestDeleteBillAction>) => { +export const requestDeleteBillAction = async ({eventId, actionId}: WithEventId<RequestBillAction>) => { await requestDelete({ baseUrl: BASE_URL.HD, endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, }); }; -type RequestPutBillAction = Bill & { - actionId: number; -}; +type RequestPutBillAction = Bill & RequestBillAction; export const requestPutBillAction = async ({eventId, actionId, title, price}: WithEventId<RequestPutBillAction>) => { await requestPut({ @@ -44,3 +42,28 @@ export const requestPutBillAction = async ({eventId, actionId, title, price}: Wi }, }); }; + +type MemberReportList = {members: MemberReportInAction[]}; + +export const requestGetMemberReportListInAction = async ({eventId, actionId}: WithEventId<RequestBillAction>) => { + return requestGet<MemberReportList>({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, + }); +}; + +type RequestPutMemberReportList = RequestBillAction & MemberReportList; + +export const requestPutMemberReportListInAction = async ({ + eventId, + actionId, + members, +}: WithEventId<RequestPutMemberReportList>) => { + return requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, + body: { + members, + }, + }); +}; diff --git a/client/src/constants/queryKeys.ts b/client/src/constants/queryKeys.ts index 23ae4b90e..17f3f4586 100644 --- a/client/src/constants/queryKeys.ts +++ b/client/src/constants/queryKeys.ts @@ -4,6 +4,7 @@ const QUERY_KEYS = { allMemberList: 'allMemberList', currentInMember: 'currentInMember', memberReport: 'memberReport', + memberReportInAction: 'memberReportInAction', }; export default QUERY_KEYS; diff --git a/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts b/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts new file mode 100644 index 000000000..85b458228 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts @@ -0,0 +1,24 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetMemberReportListInAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetMemberReportListInAction = (actionId: number) => { + const eventId = getEventIdByUrl(); + + const {data, ...queryResult} = useQuery({ + queryKey: [QUERY_KEYS.memberReportInAction, actionId], + queryFn: () => requestGetMemberReportListInAction({eventId, actionId}), + select: data => data.members, + }); + + return { + memberReportListInActionFromServer: data ?? [], + queryResult, + }; +}; + +export default useRequestGetMemberReportListInAction; diff --git a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts new file mode 100644 index 000000000..2765e278e --- /dev/null +++ b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts @@ -0,0 +1,29 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPutMemberReportListInAction} from '@apis/request/bill'; +import {MemberReportInAction} from 'types/serviceType'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutMemberReportListInAction = (actionId: number) => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...mutationProps} = useMutation({ + mutationFn: (members: MemberReportInAction[]) => requestPutMemberReportListInAction({eventId, actionId, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + }, + }); + + return { + putMemberReportListInAction: mutate, + mutationProps, + }; +}; + +export default useRequestPutMemberReportListInAction; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx index 00436cafa..20b49b096 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -68,6 +68,7 @@ describe('useDeleteMemberAction', () => { name: '망쵸', price: null, sequence: 1, + isFixed: false, }; result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx new file mode 100644 index 000000000..638cff2e5 --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx @@ -0,0 +1,57 @@ +import type {MemberReportInAction} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import validateMemberReportInAction from '@utils/validate/validateMemberReportInAction'; + +type MemberReportInput = MemberReportInAction & { + index: number; +}; + +type UseMemberReportProps = { + data: MemberReportInAction[]; + addAdjustedMember: (memberReport: MemberReportInAction) => void; + totalPrice: number; +}; + +const useMemberReportInput = ({data, addAdjustedMember, totalPrice}: UseMemberReportProps) => { + const [inputList, setInputList] = useState<MemberReportInput[]>(data.map((item, index) => ({...item, index}))); + const [canSubmit, setCanSubmit] = useState<boolean>(false); + + const onChange = (event: React.ChangeEvent<HTMLInputElement>, index: number) => { + const {value} = event.target; + + validateAndAddAdjustedMember(value, index); + }; + + const validateAndAddAdjustedMember = (price: string, index: number) => { + const {isValid, errorMessage} = validateMemberReportInAction(price, totalPrice); + setCanSubmit(errorMessage === null); + + if (isValid) { + const newInputList = [...inputList]; + newInputList[index].price = Number(price); + setInputList(newInputList); + + const memberReportData: MemberReportInAction = { + name: newInputList[index].name, + price: newInputList[index].price, + isFixed: newInputList[index].isFixed, + }; + addAdjustedMember(memberReportData); + } + }; + + // addAdjustedMember로 인해 data가 변했을 때 input list의 값을 맞춰주기 위함 + useEffect(() => { + setInputList(data.map((item, index) => ({...item, index}))); + }, [data]); + + return { + inputList, + onChange, + canSubmit, + }; +}; + +export default useMemberReportInput; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx new file mode 100644 index 000000000..e40e1694f --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx @@ -0,0 +1,302 @@ +import type {MemberReport, MemberReportInAction} from 'types/serviceType'; + +import {renderHook, waitFor, act} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; + +import memberReportListInActionJson from '../../mocks/memberReportListInAction.json'; +import {ErrorProvider} from '../useError/ErrorProvider'; + +import useMemberReportListInAction from './useMemberReportListInAction'; + +describe('useMemberReportListInActionTest', () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: 0, + }, + }, + }); + + const initializeProvider = (actionId: number, totalPrice: number) => + renderHook(() => useMemberReportListInAction(actionId, totalPrice), { + wrapper: ({children}) => ( + <QueryClientProvider client={queryClient}> + <MemoryRouter> + <ErrorProvider>{children}</ErrorProvider> + </MemoryRouter> + </QueryClientProvider> + ), + }); + + const actionId = 123; + const totalPrice = 100000; + + describe('Flow: 유저가 정상적으로 값을 불러왔을 때의 test', () => { + it('초기값을 정상적으로 불러온다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + expect(result.current.memberReportListInAction).toStrictEqual(memberReportListInActionJson); + }); + + it('망쵸의 가격을 100원으로 바꾸면 망쵸의 가격은 100원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMember: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMember); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + + expect(targetMember?.price).toBe(100); + }); + + it('망쵸의 가격을 100원으로 바꾸면 망쵸의 가격은 100원으로 설정되고 나머지 인원의 가격이 33,300원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMember: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMember); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMember?.price).toBe(100); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(33300); + }); + }); + + it('망쵸의 가격을 100원 쿠키의 가격을 100원으로 바꾸면 나머지 인원의 가격이 49,900원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => !(member.name === '망쵸' || member.name === '쿠키'), + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(49900); + }); + }); + + it('망쵸의 가격을 100원 쿠키의 가격을 100원으로 바꾸면 나머지 인원의 가격이 49,900원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => !(member.name === '망쵸' || member.name === '쿠키'), + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(49900); + }); + }); + + it('망쵸의 가격을 100원으로 바꾸고 다시 망쵸의 가격을 10,000원으로 바꾸면 나머지 인원의 가격이 30,000원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberMangchoAfter: MemberReportInAction = {name: '망쵸', price: 10000, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoAfter); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(30000); + }); + }); + }); + + describe('예외 & 엣지케이스', () => { + it('동일한 인원의 가격을 동일하게 바꾸면 변함없다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember({...adjustedMemberMangcho, isFixed: true}); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); + + expect(anotherMemberList[0].price).toBe(33300); + }); + + it('참여인원의 가격을 모두 바꾸려고 하면, 마지막 사람의 조정치는 반영되지 않는다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; + const adjustedMemberSoha: MemberReportInAction = {name: '소하', price: 100, isFixed: false}; + + // 마지막 사람 + const adjustedMemberLeeSang: MemberReportInAction = {name: '이상', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberSoha); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberLeeSang); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); + + expect(targetMember?.price).not.toBe(100); + }); + + it('망쵸에게 300원을 주면 나머지 사람들은 33233원이고 마지막 사람은 33234원이 된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 300, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + console.log(result.current.memberReportListInAction); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMember?.price).toBe(300); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => member.name === '이상' || member.name === '소하', + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(33233); + }); + + const lastMember = result.current.memberReportListInAction.find(member => member.name === '쿠키'); + + expect(lastMember?.price).toBe(33234); + }); + + it('망쵸, 쿠키의 가격을 100원으로 바꾼 후 다시 쿠키의 가격을 33000원으로 바꾸면 쿠키의 isFixed는 false가 된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; + const adjustedMemberCookieReset: MemberReportInAction = {name: '쿠키', price: 33300, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '쿠키'); + + expect(targetMember?.isFixed).toBe(true); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookieReset); + }); + + const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '쿠키'); + + expect(targetMemberReset?.isFixed).toBe(false); + }); + + it('망쵸의 가격을 100원으로 바꾼 후 다시 망쵸의 가격을 25000원으로 바꾸면 망쵸의 isFixed는 false가 된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberMangchoAfter: MemberReportInAction = {name: '망쵸', price: 25000, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMember?.isFixed).toBe(true); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoAfter); + }); + + const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMemberReset?.isFixed).toBe(false); + }); + }); + + // last + describe('onSubmit 실행 시 반영 테스트', () => { + it('망쵸의 가격을 100원으로 바꾸고 저장하면 망쵸 100원이 반영된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + await waitFor(() => { + result.current.onSubmit(); + }); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMember?.price).toBe(100); + }); + }); +}); diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts new file mode 100644 index 000000000..9549c7e91 --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts @@ -0,0 +1,100 @@ +import type {MemberReportInAction} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import useRequestGetMemberReportListInAction from '@hooks/queries/useRequestGetMemberReportListInAction'; +import useRequestPutMemberReportListInAction from '@hooks/queries/useRequestPutMemberReportListInAction'; + +const useMemberReportListInAction = (actionId: number, totalPrice: number) => { + const {memberReportListInActionFromServer, queryResult} = useRequestGetMemberReportListInAction(actionId); + const {putMemberReportListInAction} = useRequestPutMemberReportListInAction(actionId); + + const [memberReportListInAction, setMemberReportListInAction] = useState<MemberReportInAction[]>( + memberReportListInActionFromServer, + ); + + useEffect(() => { + if (queryResult.isSuccess) { + setMemberReportListInAction(memberReportListInActionFromServer); + } + }, [memberReportListInActionFromServer, queryResult.isSuccess]); + + // 조정값 멤버의 수를 구하는 함수 + const getAdjustedMemberCount = (memberReportListInAction: MemberReportInAction[]) => { + return memberReportListInAction.filter(member => member.isFixed === true).length; + }; + + const addAdjustedMember = (memberReport: MemberReportInAction) => { + if (getAdjustedMemberCount(memberReportListInAction) + 1 >= memberReportListInAction.length) { + return; + } + + const newMemberReportListInAction = memberReportListInAction.map(member => + member.name === memberReport.name ? {...member, price: memberReport.price, isFixed: true} : member, + ); + + calculateAnotherMemberPrice(newMemberReportListInAction); + }; + + const calculateDividedPrice = (remainMemberCount: number, totalAdjustedPrice: number) => { + return { + divided: Math.floor((totalPrice - totalAdjustedPrice) / remainMemberCount), + remainder: (totalPrice - totalAdjustedPrice) % remainMemberCount, + }; + }; + + // 계산값으로 값을 변경했을 때 isFixed를 푸는 함수 + // 100 true 33300 true 33300 false 33300 false + const setIsFixedFalseAtResetToDividedPrice = (memberReportListInAction: MemberReportInAction[], divided: number) => { + return memberReportListInAction.map(memberReport => { + if (memberReport.isFixed === true && memberReport.price === divided) { + return {...memberReport, isFixed: false}; + } + + return memberReport; + }); + }; + + const calculateAnotherMemberPrice = (memberReportListInAction: MemberReportInAction[]) => { + // 총 조정치 금액 + const totalAdjustedPrice = memberReportListInAction + .filter(memberReport => memberReport.isFixed === true) + .reduce((acc, cur) => acc + cur.price, 0); + + const remainMemberCount = memberReportListInAction.length - getAdjustedMemberCount(memberReportListInAction); + const {divided, remainder} = calculateDividedPrice(remainMemberCount, totalAdjustedPrice); + + const updatedList = memberReportListInAction.map(member => + member.isFixed === true ? member : {...member, price: divided}, + ); + + // 나머지를 조정되지 않은 멤버 중 마지막 멤버에게 추가 + if (remainder !== 0) { + const nonAdjustedMembers = updatedList.filter(member => member.isFixed === false); + const lastNonAdjustedMemberIndex = updatedList.findIndex( + member => member.name === nonAdjustedMembers[nonAdjustedMembers.length - 1].name, + ); + + if (lastNonAdjustedMemberIndex !== -1) { + updatedList[lastNonAdjustedMemberIndex].price += remainder; + } + } + + // 조정됐지만 계산값으로 가격이 변한 경우 fixed 상태를 풀어야한다. + const result = setIsFixedFalseAtResetToDividedPrice(updatedList, divided); + setMemberReportListInAction(result); + }; + + const onSubmit = () => { + putMemberReportListInAction(memberReportListInAction); + }; + + return { + memberReportListInAction, + addAdjustedMember, + onSubmit, + queryResult, + }; +}; + +export default useMemberReportListInAction; diff --git a/client/src/mocks/handlers.ts b/client/src/mocks/handlers.ts index f20429263..4189b2d66 100644 --- a/client/src/mocks/handlers.ts +++ b/client/src/mocks/handlers.ts @@ -3,5 +3,13 @@ import {eventHandler} from './handlers/eventHandlers'; import {reportHandlers} from './handlers/reportHandlers'; import {stepListHandler} from './handlers/stepListHandler'; import {testHandler} from './handlers/testHandlers'; +import {memberReportInActionHandler} from './handlers/memberReportInActionHandlers'; -export const handlers = [...authHandler, ...eventHandler, ...testHandler, ...stepListHandler, ...reportHandlers]; +export const handlers = [ + ...authHandler, + ...eventHandler, + ...testHandler, + ...stepListHandler, + ...reportHandlers, + ...memberReportInActionHandler, +]; diff --git a/client/src/mocks/handlers/memberReportInActionHandlers.ts b/client/src/mocks/handlers/memberReportInActionHandlers.ts new file mode 100644 index 000000000..7c9b5b1b1 --- /dev/null +++ b/client/src/mocks/handlers/memberReportInActionHandlers.ts @@ -0,0 +1,35 @@ +import {http, HttpResponse} from 'msw'; + +import {MemberReport} from 'types/serviceType'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import memberReportInActionJson from '../memberReportListInAction.json'; + +let memberReportInActionMockData = memberReportInActionJson as MemberReport[]; + +type MemberReportListBody = {members: MemberReport[]}; + +export const memberReportInActionHandler = [ + http.get<any, MemberReportListBody, any, `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`>( + `${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, + () => { + return HttpResponse.json({ + members: memberReportInActionMockData, + }); + }, + ), + + http.put<any, MemberReportListBody, any, `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`>( + `${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, + async ({request}) => { + const {members} = await request.json(); + + memberReportInActionMockData = members; + + return HttpResponse.json({ + status: 200, + }); + }, + ), +]; diff --git a/client/src/mocks/handlers/stepListHandler.ts b/client/src/mocks/handlers/stepListHandler.ts index e771d71c0..d79b7b0b4 100644 --- a/client/src/mocks/handlers/stepListHandler.ts +++ b/client/src/mocks/handlers/stepListHandler.ts @@ -73,6 +73,7 @@ export const stepListHandler = [ name, price: 0, sequence: 999, + isFixed: false, })), }, ]; @@ -99,6 +100,7 @@ export const stepListHandler = [ name: title, price, sequence: 999, + isFixed: false, })), }, ]; diff --git a/client/src/mocks/invalidMemberStepList.json b/client/src/mocks/invalidMemberStepList.json index 5c4d7fee1..33ca77e4c 100644 --- a/client/src/mocks/invalidMemberStepList.json +++ b/client/src/mocks/invalidMemberStepList.json @@ -8,13 +8,15 @@ "actionId": 999, "name": "망쵸", "price": null, - "sequence": 1 + "sequence": 1, + "isFixed": false }, { "actionId": 2, "name": "백호", "price": null, - "sequence": 2 + "sequence": 2, + "isFixed": false } ] }, @@ -27,13 +29,15 @@ "actionId": 3, "name": "감자탕", "price": 10000, - "sequence": 3 + "sequence": 3, + "isFixed": false }, { "actionId": 4, "name": "인생네컷", "price": 10000, - "sequence": 4 + "sequence": 4, + "isFixed": false } ] }, @@ -46,13 +50,15 @@ "actionId": 5, "name": "소하", "price": null, - "sequence": 5 + "sequence": 5, + "isFixed": false }, { "actionId": 6, "name": "웨디", "price": null, - "sequence": 6 + "sequence": 6, + "isFixed": false } ] }, @@ -65,7 +71,8 @@ "actionId": 9, "name": "노래방", "price": 20000, - "sequence": 10 + "sequence": 10, + "isFixed": false } ] }, @@ -78,13 +85,15 @@ "actionId": 7, "name": "망쵸", "price": null, - "sequence": 7 + "sequence": 7, + "isFixed": false }, { "actionId": 8, "name": "백호", "price": null, - "sequence": 8 + "sequence": 8, + "isFixed": false } ] } diff --git a/client/src/mocks/memberActionStepList.json b/client/src/mocks/memberActionStepList.json index 578dfdd11..734db4a75 100644 --- a/client/src/mocks/memberActionStepList.json +++ b/client/src/mocks/memberActionStepList.json @@ -8,13 +8,15 @@ "actionId": 1, "name": "망쵸", "price": null, - "sequence": 1 + "sequence": 1, + "isFixed": false }, { "actionId": 2, "name": "백호", "price": null, - "sequence": 2 + "sequence": 2, + "isFixed": false } ] } diff --git a/client/src/mocks/memberReportListInAction.json b/client/src/mocks/memberReportListInAction.json new file mode 100644 index 000000000..2e24670cb --- /dev/null +++ b/client/src/mocks/memberReportListInAction.json @@ -0,0 +1,6 @@ +[ + {"name": "망쵸", "price": 25000, "isFixed": false}, + {"name": "이상", "price": 25000, "isFixed": false}, + {"name": "소하", "price": 25000, "isFixed": false}, + {"name": "쿠키", "price": 25000, "isFixed": false} +] diff --git a/client/src/mocks/stepList.json b/client/src/mocks/stepList.json index e4221ffd3..355692d58 100644 --- a/client/src/mocks/stepList.json +++ b/client/src/mocks/stepList.json @@ -8,13 +8,15 @@ "actionId": 1, "name": "망쵸", "price": null, - "sequence": 1 + "sequence": 1, + "isFixed": false }, { "actionId": 2, "name": "백호", "price": null, - "sequence": 2 + "sequence": 2, + "isFixed": false } ] }, @@ -27,13 +29,15 @@ "actionId": 3, "name": "감자탕", "price": 10000, - "sequence": 3 + "sequence": 3, + "isFixed": false }, { "actionId": 4, "name": "인생네컷", "price": 10000, - "sequence": 4 + "sequence": 4, + "isFixed": false } ] }, @@ -46,13 +50,15 @@ "actionId": 5, "name": "소하", "price": null, - "sequence": 5 + "sequence": 5, + "isFixed": false }, { "actionId": 6, "name": "웨디", "price": null, - "sequence": 6 + "sequence": 6, + "isFixed": false } ] }, @@ -65,7 +71,8 @@ "actionId": 9, "name": "노래방", "price": 20000, - "sequence": 10 + "sequence": 10, + "isFixed": false } ] }, @@ -78,13 +85,15 @@ "actionId": 7, "name": "망쵸", "price": null, - "sequence": 7 + "sequence": 7, + "isFixed": false }, { "actionId": 8, "name": "백호", "price": null, - "sequence": 8 + "sequence": 8, + "isFixed": false } ] } diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts index bddb36329..1dd69dcfb 100644 --- a/client/src/types/serviceType.ts +++ b/client/src/types/serviceType.ts @@ -7,6 +7,10 @@ export type MemberReport = { price: number; }; +export type MemberReportInAction = MemberReport & { + isFixed: boolean; +}; + export type Bill = { title: string; price: number; @@ -38,6 +42,7 @@ export type Action = { name: string; price: number | null; sequence: number; + isFixed: boolean; }; export type BillAction = Omit<Action, 'price'> & { diff --git a/client/src/utils/validate/validateMemberReportInAction.ts b/client/src/utils/validate/validateMemberReportInAction.ts new file mode 100644 index 000000000..8e02c3dde --- /dev/null +++ b/client/src/utils/validate/validateMemberReportInAction.ts @@ -0,0 +1,41 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateMemberReportInAction = (price: string, totalPrice: number): ValidateResult => { + let errorMessage = null; + const numberTypePrice = Number(price); + + const validateOnlyNaturalNumber = () => { + if (!(Number.isInteger(numberTypePrice) && numberTypePrice >= 0)) return false; + return true; + }; + + const validatePrice = () => { + if (numberTypePrice > RULE.maxPrice) return false; + return true; + }; + + const validateEmpty = () => { + if (!price.trim().length) { + errorMessage = ERROR_MESSAGE.preventEmpty; + return false; + } + return true; + }; + + const validateUnderTotalPrice = () => { + if (numberTypePrice > totalPrice) return false; + + return true; + }; + + if (validateOnlyNaturalNumber() && validatePrice() && validateEmpty() && validateUnderTotalPrice()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage: errorMessage || ERROR_MESSAGE.invalidInput}; +}; + +export default validateMemberReportInAction; From 78d20a398b459eccc1ced55b4dfb61df23ef7e61 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:08:46 +0900 Subject: [PATCH 178/273] =?UTF-8?q?feat:=20=EC=B0=A8=EB=93=B1=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EC=A0=81=EC=9A=A9=20=EC=A4=91=20=EC=A7=80=EC=9B=90?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#423)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 --- .../useMemberReportInput.tsx | 26 ++++++++- .../useMemberReportListInAction.test.tsx | 21 +++++++ .../useMemberReportListInAction.ts | 58 +++++++++++++++++++ .../validate/validateMemberReportInAction.ts | 10 +--- 4 files changed, 103 insertions(+), 12 deletions(-) diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx index 638cff2e5..9f0cb4449 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx @@ -11,13 +11,23 @@ type MemberReportInput = MemberReportInAction & { type UseMemberReportProps = { data: MemberReportInAction[]; addAdjustedMember: (memberReport: MemberReportInAction) => void; + getOnlyOneNotAdjustedRemainMemberIndex: () => number | null; + getIsSamePriceStateAndServerState: () => boolean; totalPrice: number; }; -const useMemberReportInput = ({data, addAdjustedMember, totalPrice}: UseMemberReportProps) => { +const useMemberReportInput = ({ + data, + addAdjustedMember, + totalPrice, + getOnlyOneNotAdjustedRemainMemberIndex, + getIsSamePriceStateAndServerState, +}: UseMemberReportProps) => { const [inputList, setInputList] = useState<MemberReportInput[]>(data.map((item, index) => ({...item, index}))); const [canSubmit, setCanSubmit] = useState<boolean>(false); + const [canEditList, setCanEditList] = useState<boolean[]>(new Array(data.length).fill(true)); + const onChange = (event: React.ChangeEvent<HTMLInputElement>, index: number) => { const {value} = event.target; @@ -25,8 +35,8 @@ const useMemberReportInput = ({data, addAdjustedMember, totalPrice}: UseMemberRe }; const validateAndAddAdjustedMember = (price: string, index: number) => { - const {isValid, errorMessage} = validateMemberReportInAction(price, totalPrice); - setCanSubmit(errorMessage === null); + const {isValid} = validateMemberReportInAction(price, totalPrice); + setCanSubmit(isValid); if (isValid) { const newInputList = [...inputList]; @@ -44,12 +54,22 @@ const useMemberReportInput = ({data, addAdjustedMember, totalPrice}: UseMemberRe // addAdjustedMember로 인해 data가 변했을 때 input list의 값을 맞춰주기 위함 useEffect(() => { + setCanSubmit(!getIsSamePriceStateAndServerState()); setInputList(data.map((item, index) => ({...item, index}))); + + // 남은 인원이 1명일 때 수정을 불가능하도록 설정 + const onlyOneIndex = getOnlyOneNotAdjustedRemainMemberIndex(); + if (onlyOneIndex !== null) { + const newCanEditList = new Array(data.length).fill(true); + newCanEditList[onlyOneIndex] = false; + setCanEditList(newCanEditList); + } }, [data]); return { inputList, onChange, + canEditList, canSubmit, }; }; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx index e40e1694f..99d3b1814 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx @@ -275,6 +275,27 @@ describe('useMemberReportListInActionTest', () => { const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '망쵸'); expect(targetMemberReset?.isFixed).toBe(false); }); + + it('아무도 조정된 값이 없다면 조정값이 있는지 확인 결과 false다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + expect(result.current.isExistAdjustedPrice()).toBe(false); + }); + + it('망쵸의 가격을 100원으로 바꾼 후 리스트 중 조정값이 있는지 확인 결과 true다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + expect(result.current.isExistAdjustedPrice()).toBe(true); + }); }); // last diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts index 9549c7e91..3d332ea25 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts @@ -13,12 +13,51 @@ const useMemberReportListInAction = (actionId: number, totalPrice: number) => { memberReportListInActionFromServer, ); + // isFixed를 모두 풀고 계산값으로 모두 처리하는 기능 + const reCalculatePriceByTotalPriceChange = () => { + const {divided, remainder} = calculateDividedPrice(memberReportListInAction.length, 0); + + const resetMemberReportList = [...memberReportListInAction]; + resetMemberReportList.forEach((member, index) => { + if (index !== resetMemberReportList.length - 1) { + member.price = divided; + } else { + member.price = divided + remainder; + } + member.isFixed = false; + }); + + setMemberReportListInAction(resetMemberReportList); + }; + + // 총 금액이 변동됐을 때 (서버에서 온 값과 다를 때) 재계산 실행 + useEffect(() => { + const totalPriceFromServer = memberReportListInActionFromServer.reduce((acc, cur) => acc + cur.price, 0); + + if (totalPriceFromServer !== totalPrice) { + reCalculatePriceByTotalPriceChange(); + } + }, [totalPrice]); + useEffect(() => { if (queryResult.isSuccess) { setMemberReportListInAction(memberReportListInActionFromServer); } }, [memberReportListInActionFromServer, queryResult.isSuccess]); + const isExistAdjustedPrice = () => { + return memberReportListInAction.some(member => member.isFixed === true); + }; + + // 조정되지 않은 인원이 단 1명인 경우의 index + const getOnlyOneNotAdjustedRemainMemberIndex = (): number | null => { + const adjustedPriceCount = getAdjustedMemberCount(memberReportListInAction); + + if (adjustedPriceCount < memberReportListInAction.length - 1) return null; + + return memberReportListInAction.findIndex(member => member.isFixed === false); + }; + // 조정값 멤버의 수를 구하는 함수 const getAdjustedMemberCount = (memberReportListInAction: MemberReportInAction[]) => { return memberReportListInAction.filter(member => member.isFixed === true).length; @@ -89,10 +128,29 @@ const useMemberReportListInAction = (actionId: number, totalPrice: number) => { putMemberReportListInAction(memberReportListInAction); }; + const getIsSamePriceStateAndServerState = () => { + const serverStatePriceList = memberReportListInActionFromServer.map(({price}) => price); + const clientStatePriceList = memberReportListInAction.map(({price}) => price); + + let isSame = true; + + // isArrayEqual을 사용하지 않은 이유는 정렬이 영향을 받으면 안 되기 때문입니다 + for (let i = 0; i < serverStatePriceList.length; i++) { + if (serverStatePriceList[i] !== clientStatePriceList[i]) { + isSame = false; + } + } + + return isSame; + }; + return { memberReportListInAction, addAdjustedMember, + isExistAdjustedPrice, onSubmit, + getOnlyOneNotAdjustedRemainMemberIndex, + getIsSamePriceStateAndServerState, queryResult, }; }; diff --git a/client/src/utils/validate/validateMemberReportInAction.ts b/client/src/utils/validate/validateMemberReportInAction.ts index 8e02c3dde..b4e6c2a9a 100644 --- a/client/src/utils/validate/validateMemberReportInAction.ts +++ b/client/src/utils/validate/validateMemberReportInAction.ts @@ -17,21 +17,13 @@ const validateMemberReportInAction = (price: string, totalPrice: number): Valida return true; }; - const validateEmpty = () => { - if (!price.trim().length) { - errorMessage = ERROR_MESSAGE.preventEmpty; - return false; - } - return true; - }; - const validateUnderTotalPrice = () => { if (numberTypePrice > totalPrice) return false; return true; }; - if (validateOnlyNaturalNumber() && validatePrice() && validateEmpty() && validateUnderTotalPrice()) { + if (validateOnlyNaturalNumber() && validatePrice() && validateUnderTotalPrice()) { return {isValid: true, errorMessage: null}; } From 9ab0a964836b29dfec43d5485d7ab723b99249d9 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:14:18 +0900 Subject: [PATCH 179/273] =?UTF-8?q?fix:=20=EC=B0=A8=EB=93=B1=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20can=20submit=EC=9D=B4=20valid=20=ED=95=98=EC=A7=80?= =?UTF-8?q?=EB=A7=8C=20false=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20(#42?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 --- .../useMemberReportInput.tsx | 16 ++++++++++++++-- .../useMemberReportListInAction.ts | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx index 9f0cb4449..9c9cd80d9 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx @@ -26,7 +26,7 @@ const useMemberReportInput = ({ const [inputList, setInputList] = useState<MemberReportInput[]>(data.map((item, index) => ({...item, index}))); const [canSubmit, setCanSubmit] = useState<boolean>(false); - const [canEditList, setCanEditList] = useState<boolean[]>(new Array(data.length).fill(true)); + const [canEditList, setCanEditList] = useState<boolean[]>([]); const onChange = (event: React.ChangeEvent<HTMLInputElement>, index: number) => { const {value} = event.target; @@ -36,7 +36,6 @@ const useMemberReportInput = ({ const validateAndAddAdjustedMember = (price: string, index: number) => { const {isValid} = validateMemberReportInAction(price, totalPrice); - setCanSubmit(isValid); if (isValid) { const newInputList = [...inputList]; @@ -52,6 +51,14 @@ const useMemberReportInput = ({ } }; + // 서버와 값이 같지 않고 input price의 상태가 모두 valid하다면 can submit true + useEffect(() => { + const isSamePriceState = getIsSamePriceStateAndServerState(); + const isAllValid = inputList.every(input => validateMemberReportInAction(String(input.price), totalPrice)); + + setCanSubmit(!isSamePriceState && isAllValid); + }, [inputList]); + // addAdjustedMember로 인해 data가 변했을 때 input list의 값을 맞춰주기 위함 useEffect(() => { setCanSubmit(!getIsSamePriceStateAndServerState()); @@ -59,6 +66,11 @@ const useMemberReportInput = ({ // 남은 인원이 1명일 때 수정을 불가능하도록 설정 const onlyOneIndex = getOnlyOneNotAdjustedRemainMemberIndex(); + + if (data.length !== 0) { + setCanEditList(new Array(data.length).fill(true)); + } + if (onlyOneIndex !== null) { const newCanEditList = new Array(data.length).fill(true); newCanEditList[onlyOneIndex] = false; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts index 3d332ea25..c9e16ff3b 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts @@ -34,10 +34,10 @@ const useMemberReportListInAction = (actionId: number, totalPrice: number) => { useEffect(() => { const totalPriceFromServer = memberReportListInActionFromServer.reduce((acc, cur) => acc + cur.price, 0); - if (totalPriceFromServer !== totalPrice) { + if (totalPriceFromServer !== totalPrice && totalPriceFromServer !== 0) { reCalculatePriceByTotalPriceChange(); } - }, [totalPrice]); + }, [totalPrice, memberReportListInActionFromServer]); useEffect(() => { if (queryResult.isSuccess) { From 4463eec30cfdc95dd110fad92d4264e2fb1b3f42 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:29:16 +0900 Subject: [PATCH 180/273] =?UTF-8?q?feat:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=B6=94=EA=B0=80=20=EB=B3=80=EA=B2=BD=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=A0=81=EC=9A=A9=20(#414)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- client/package-lock.json | 8 +- client/package.json | 4 +- .../src/components/StepList/BillStepItem.tsx | 84 ++++++++++++++----- client/src/components/StepList/Step.tsx | 33 ++++++-- client/src/components/StepList/StepList.tsx | 57 ++++++++++++- client/src/hooks/useSetBillInput.ts | 66 +++++++++++++++ .../EventPage/AdminPage/AdminPage.style.ts | 11 ++- .../pages/EventPage/AdminPage/AdminPage.tsx | 28 +++++-- 8 files changed, 246 insertions(+), 45 deletions(-) create mode 100644 client/src/hooks/useSetBillInput.ts diff --git a/client/package-lock.json b/client/package-lock.json index d01bee964..d9f21f883 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.74", + "haengdong-design": "^0.1.76", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -10137,9 +10137,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.74", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.74.tgz", - "integrity": "sha512-K75LDIR4wqR+Z8YDTMsYXm9sWQ60Qw4DLPSOSnsb5mzncX1u3/z+zLOb1gs/zS8YZznUwzu6HzavWh6Sl8guNQ==", + "version": "0.1.76", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.76.tgz", + "integrity": "sha512-wTZv/3XK9I8N5NAyCAoYyykWu76MzWQlQ+jDZDuTFuzyV2c+MoYI2Ouvyu+9rl+HDYRuBVIaQ6ysfM6hQcwVYg==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index 5de424ec7..ff2abe9d8 100644 --- a/client/package.json +++ b/client/package.json @@ -68,7 +68,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.74", + "haengdong-design": "^0.1.76", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -80,4 +80,4 @@ "npm": ">=10.7.0", "node": ">=20.15.1" } -} \ No newline at end of file +} diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 7c49d8efa..89fbe7e2e 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -1,26 +1,41 @@ -import type {BillStep, MemberReport} from 'types/serviceType'; - -import {DragHandleItem, DragHandleItemContainer} from 'haengdong-design'; +import {DragHandleItem, DragHandleItemContainer, EditableItem, Flex, Text} from 'haengdong-design'; import {Fragment, useState} from 'react'; import {useOutletContext} from 'react-router-dom'; +import {BillStep, MemberReport} from 'types/serviceType'; import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; import {MemberListInBillStep} from '@components/Modal/MemberListInBillStep'; import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; +import useSetBillInput from '@hooks/useSetBillInput'; + interface BillStepItemProps { step: BillStep; isOpenBottomSheet: boolean; setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; + isAddEditableItem: boolean; + setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; + isLastBillItem: boolean; + index: number; } -const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { +const BillStepItem: React.FC<BillStepItemProps> = ({ + step, + isOpenBottomSheet, + setIsOpenBottomSheet, + isAddEditableItem, + setIsAddEditableItem, + isLastBillItem, + index, +}) => { const {isAdmin} = useOutletContext<EventPageContextProps>(); + const {handleBlurBillRequest, handleChangeBillInput, billInput} = useSetBillInput({setIsAddEditableItem}); + const [clickedIndex, setClickedIndex] = useState(-1); const [isOpenMemberListInBillStep, setIsOpenMemberListInBillStep] = useState(false); const stepName = `차`; - const totalPrice = step.actions.reduce((acc, cur) => acc + cur.price, 0); + const totalPrice = step.actions && step.type === 'BILL' ? step.actions.reduce((acc, cur) => acc + cur.price, 0) : 0; const handleDragHandleItemClick = (index: number) => { setClickedIndex(index); @@ -39,6 +54,7 @@ const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, set return ( <> <DragHandleItemContainer + id={`${index}`} topLeftText={stepName} topRightText={`${step.members.length}명`} bottomLeftText="총액" @@ -46,24 +62,48 @@ const BillStepItem: React.FC<BillStepItemProps> = ({step, isOpenBottomSheet, set backgroundColor="white" onTopRightTextClick={handleTopRightTextClick} > - {step.actions.map((action, index) => ( - <Fragment key={action.actionId}> - <DragHandleItem - hasDragHandler={isAdmin} - prefix={action.name} - suffix={`${action.price.toLocaleString('ko-kr')} 원`} - backgroundColor="lightGrayContainer" - onClick={() => handleDragHandleItemClick(index)} - /> - {isOpenBottomSheet && clickedIndex === index && isAdmin && ( - <PutAndDeleteBillActionModal - billAction={action} - isBottomSheetOpened={isOpenBottomSheet} - setIsBottomSheetOpened={setIsOpenBottomSheet} + {step.actions && + step.type === 'BILL' && + step.actions.map((action, index) => ( + <Fragment key={action.actionId}> + <DragHandleItem + hasDragHandler={isAdmin} + prefix={action.name} + suffix={`${action.price.toLocaleString('ko-kr')} 원`} + backgroundColor="lightGrayContainer" + onClick={() => handleDragHandleItemClick(index)} /> - )} - </Fragment> - ))} + + {isOpenBottomSheet && clickedIndex === index && isAdmin && ( + <PutAndDeleteBillActionModal + billAction={action} + isBottomSheetOpened={isOpenBottomSheet} + setIsBottomSheetOpened={setIsOpenBottomSheet} + /> + )} + </Fragment> + ))} + + {isAddEditableItem && isLastBillItem && ( + <EditableItem backgroundColor="lightGrayContainer" onBlur={handleBlurBillRequest}> + <EditableItem.Input + placeholder="지출 내역" + textSize="bodyBold" + value={billInput.title} + onChange={e => handleChangeBillInput('title', e)} + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + placeholder="0" + type="number" + value={billInput.price} + onChange={e => handleChangeBillInput('price', e)} + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + )} </DragHandleItemContainer> {isOpenMemberListInBillStep && ( <MemberListInBillStep diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index 4d0f08903..f6c89475b 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -1,22 +1,45 @@ import type {BillStep, MemberStep} from 'types/serviceType'; -import {useState} from 'react'; +import {useEffect, useState} from 'react'; import BillStepItem from './BillStepItem'; import MemberStepItem from './MemberStepItem'; interface StepProps { step: BillStep | MemberStep; + isAddEditableItem: boolean; + lastBillItemIndex: number; + lastItemIndex: number; + index: number; + setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; } -const Step = ({step}: StepProps) => { +const Step = ({step, isAddEditableItem, lastBillItemIndex, lastItemIndex, setIsAddEditableItem, index}: StepProps) => { const [isOpenBottomSheet, setIsOpenBottomSheet] = useState<boolean>(false); + const [isLastBillItem, setIsLastBillItem] = useState<boolean>(false); - if (step.type === 'BILL') { + useEffect(() => { + if (index === lastBillItemIndex && lastBillItemIndex === lastItemIndex) { + // index를 사용하여 마지막 BillStep인지 확인 + setIsLastBillItem(true); + } else { + setIsLastBillItem(false); + } + }, [index, lastBillItemIndex]); + + if (step.actions && step.type === 'BILL') { return ( - <BillStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setIsOpenBottomSheet={setIsOpenBottomSheet} /> + <BillStepItem + index={index} + step={step as BillStep} + isOpenBottomSheet={isOpenBottomSheet} + setIsOpenBottomSheet={setIsOpenBottomSheet} + isAddEditableItem={isAddEditableItem} + setIsAddEditableItem={setIsAddEditableItem} + isLastBillItem={isLastBillItem} + /> ); - } else if (step.type === 'IN' || step.type === 'OUT') { + } else if (step.actions && (step.type === 'IN' || step.type === 'OUT')) { return ( <MemberStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setIsOpenBottomSheet={setIsOpenBottomSheet} /> ); diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index be9f40998..755bf8ac6 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,18 +1,69 @@ import {Flex} from 'haengdong-design'; +import {useEffect, useMemo, useState} from 'react'; import {BillStep, MemberStep} from 'types/serviceType'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; import Step from './Step'; -const StepList = () => { +interface StepListProps { + isAddEditableItem: boolean; + setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; +} + +const StepList = ({isAddEditableItem, setIsAddEditableItem}: StepListProps) => { const {data: stepListData} = useRequestGetStepList(); - const stepList = stepListData ?? ([] as (MemberStep | BillStep)[]); + const [stepList, setStepList] = useState<(MemberStep | BillStep)[]>([]); + const existIndexInStepList = stepList.map((step, index) => ({...step, index})); + const [hasAddedItem, setHasAddedItem] = useState(false); + + useEffect(() => { + if (stepListData) { + setStepList(stepListData); + } + }, [stepListData]); + + const lastBillItemIndex = useMemo(() => { + const billSteps = existIndexInStepList.filter(step => step.type === 'BILL'); + + // billSteps 배열이 비어 있지 않으면 마지막 항목의 index를 반환, 그렇지 않으면 -1을 반환 + return billSteps.length > 0 ? billSteps.slice(-1)[0].index : -1; + }, [stepList]); + + const lastItemIndex = useMemo(() => { + return existIndexInStepList.length > 0 ? existIndexInStepList.slice(-1)[0].index : -1; + }, [existIndexInStepList]); + + useEffect(() => { + // 최초로 빈 stepList가 생성되고 난 후, 다시 hasAddedItem을 false로 변환하기 위한 조건문 + if (hasAddedItem) setHasAddedItem(prev => !prev); + + if (isAddEditableItem && lastBillItemIndex !== lastItemIndex && !hasAddedItem) { + setStepList(prev => [ + ...prev, + { + type: 'BILL', + stepName: '', + members: [], + actions: [], + }, + ]); + setHasAddedItem(prev => !prev); + } + }, [isAddEditableItem, lastBillItemIndex, lastItemIndex, hasAddedItem, existIndexInStepList, stepListData]); return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> {stepList.map((step, index) => ( - <Step step={step} key={`${step.stepName}${index}`} /> + <Step + index={index} + step={step} + lastBillItemIndex={lastBillItemIndex} + lastItemIndex={lastItemIndex} + key={`${step.stepName}${index}`} + isAddEditableItem={isAddEditableItem} + setIsAddEditableItem={setIsAddEditableItem} + /> ))} </Flex> ); diff --git a/client/src/hooks/useSetBillInput.ts b/client/src/hooks/useSetBillInput.ts new file mode 100644 index 000000000..c1dd4a394 --- /dev/null +++ b/client/src/hooks/useSetBillInput.ts @@ -0,0 +1,66 @@ +import {useState} from 'react'; + +import validatePurchase from '@utils/validate/validatePurchase'; +import {Bill} from 'types/serviceType'; + +import useRequestPostBillList from './queries/useRequestPostBillList'; +import {BillInputType, InputPair} from './useDynamicBillActionInput'; + +interface UseSetBillInputProps { + setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; +} + +interface UseSetBillInputReturns { + billInput: Bill; + handleChangeBillInput: (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => void; + handleBlurBillRequest: () => void; +} + +const useSetBillInput = ({setIsAddEditableItem}: UseSetBillInputProps): UseSetBillInputReturns => { + const initialInput = {title: '', price: 0}; + const [billInput, setBillInput] = useState<Bill>(initialInput); + + const {mutate: postBillList} = useRequestPostBillList(); + + const handleChangeBillInput = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { + const {value} = event.target; + const {isValid} = validatePurchase({ + ...billInput, + [field]: value, + }); + + if (isValid) { + setBillInput(prev => ({ + ...prev, + [field]: value, + })); + } + }; + + const handleBlurBillRequest = () => { + const isEmptyTitle = billInput.title.trim().length; + const isEmptyPrice = Number(billInput.price); + + // 두 input의 값이 모두 채워졌을 때 api 요청 + // api 요청을 하면 Input을 띄우지 않음 + if (isEmptyTitle && isEmptyPrice) { + postBillList( + {billList: [billInput]}, + { + onSuccess: () => { + setBillInput(initialInput); + setIsAddEditableItem(false); + }, + }, + ); + } + }; + + return { + billInput, + handleBlurBillRequest, + handleChangeBillInput, + }; +}; + +export default useSetBillInput; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts index 6fea4be3b..1a711bbbd 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts +++ b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts @@ -4,8 +4,7 @@ export const receiptStyle = () => css({ display: 'flex', flexDirection: 'column', - gap: '8px', - padding: '0 8px', + gap: '1rem', paddingBottom: '8.75rem', }); @@ -14,3 +13,11 @@ export const titleAndListButtonContainerStyle = () => display: 'flex', flexDirection: 'column', }); + +export const buttonGroupStyle = () => + css({ + display: 'flex', + width: '100%', + padding: '0 0.5rem', + gap: '0.5rem', + }); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 9fd10f8ef..65e6f42cc 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,5 +1,5 @@ import {useEffect, useState} from 'react'; -import {Title, FixedButton, ListButton} from 'haengdong-design'; +import {Title, FixedButton, ListButton, Button} from 'haengdong-design'; import {useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; @@ -11,11 +11,12 @@ import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; import {EventPageContextProps} from '../EventPageLayout'; -import {receiptStyle, titleAndListButtonContainerStyle} from './AdminPage.style'; +import {receiptStyle, titleAndListButtonContainerStyle, buttonGroupStyle} from './AdminPage.style'; const AdminPage = () => { const [isOpenFixedButtonBottomSheet, setIsOpenFixedButtonBottomSheet] = useState(false); const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); + const [isAddEditableItem, setIsAddEditableItem] = useState(false); const {eventName} = useOutletContext<EventPageContextProps>(); const {data: allMemberListData} = useRequestGetAllMemberList(); @@ -54,11 +55,24 @@ const AdminPage = () => { )} </div> <section css={receiptStyle}> - <StepList /> - <FixedButton - children={allMemberList.length === 0 ? '시작인원 추가하기' : '행동 추가하기'} - onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} - /> + <StepList isAddEditableItem={isAddEditableItem} setIsAddEditableItem={setIsAddEditableItem} /> + {allMemberList.length === 0 ? ( + <FixedButton children={'시작인원 추가하기'} onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} /> + ) : ( + <div css={buttonGroupStyle}> + <Button + size="medium" + variants="tertiary" + style={{width: '100%'}} + onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} + > + 인원 변동 추가 + </Button> + <Button size="medium" onClick={() => setIsAddEditableItem(true)} style={{width: '100%'}}> + 지출 내역 추가 + </Button> + </div> + )} {isOpenFixedButtonBottomSheet && ( <ModalBasedOnMemberCount allMemberList={allMemberList} From c01c412640a6df8fa71cab51a158963a66533ba6 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:45:06 +0900 Subject: [PATCH 181/273] =?UTF-8?q?feat:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=95=84=EC=9D=B4=ED=85=9C=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=EC=8B=9C=20=EB=9C=A8=EB=8A=94=20=EC=B0=A8=EB=93=B1=20=EC=A0=95?= =?UTF-8?q?=EC=82=B0=20=EB=AA=A8=EB=8B=AC=20=ED=8D=BC=EB=B8=94=EB=A6=AC?= =?UTF-8?q?=EC=8B=B1=20(#431)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 --- .../components/BottomSheet/BottomSheet.tsx | 2 - .../DragHandleItem/DragHandleItem.stories.tsx | 10 ++ .../DragHandleItem/DragHandleItem.tsx | 9 +- .../DragHandleItem/DragHandleItem.type.ts | 1 + .../EditableItem/EditableItem.Input.style.ts | 6 - .../EditableItem/EditableItem.Input.tsx | 13 +- .../IsFixedIcon/IsFixedIcon.style.ts | 9 ++ .../components/IsFixedIcon/IsFixedIcon.tsx | 13 ++ client/package-lock.json | 86 +++++------ .../PutAndDeleteBillActionModal.tsx | 133 ++++++++++++++---- client/src/hooks/usePutAndDeleteBillAction.ts | 29 ++-- 11 files changed, 207 insertions(+), 104 deletions(-) create mode 100644 HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts create mode 100644 HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx diff --git a/HDesign/src/components/BottomSheet/BottomSheet.tsx b/HDesign/src/components/BottomSheet/BottomSheet.tsx index a1d3590c2..3ffadc323 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.tsx +++ b/HDesign/src/components/BottomSheet/BottomSheet.tsx @@ -1,9 +1,7 @@ /** @jsxImportSource @emotion/react */ import {createPortal} from 'react-dom'; -import {useEffect, useRef, useState} from 'react'; import {BottomSheetProps} from '@components/BottomSheet/BottomSheet.type'; -import FixedButton from '@components/FixedButton/FixedButton'; import {useTheme} from '@theme/HDesignProvider'; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx index 534bbacf9..c7125d4d8 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx @@ -25,6 +25,10 @@ const meta = { description: '', control: {type: 'text'}, }, + isFixed: { + description: '컴포넌트가 고정되어 있는지 여부를 나타냅니다.', + control: {type: 'boolean'}, + }, }, args: { backgroundColor: 'white', @@ -39,3 +43,9 @@ export default meta; type Story = StoryObj<typeof meta>; export const Playground: Story = {}; + +export const FixedItem: Story = { + args: { + isFixed: true, + }, +}; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx index df6ac2b27..9acf38084 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx @@ -1,9 +1,8 @@ /** @jsxImportSource @emotion/react */ -import React from 'react'; - import Icon from '@components/Icon/Icon'; import Flex from '@components/Flex/Flex'; import Text from '@components/Text/Text'; +import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; import {useTheme} from '@theme/HDesignProvider'; @@ -15,6 +14,7 @@ import {DragHandleItemProps} from './DragHandleItem.type'; export const DragHandleItem = ({ hasDragHandler = false, backgroundColor = 'white', + isFixed = false, prefix, suffix, ...htmlProps @@ -32,7 +32,10 @@ export const DragHandleItem = ({ )} <Flex justifyContent="spaceBetween" width="100%"> <Text size="bodyBold">{prefix}</Text> - <Text>{suffix}</Text> + <Flex flexDirection="row"> + {isFixed && <IsFixedIcon />} + <Text>{suffix}</Text> + </Flex> </Flex> </div> </div> diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts index 29b8ebfd4..fc0a1f520 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts @@ -11,6 +11,7 @@ export interface DragHandleItemCustomProps { hasDragHandler?: boolean; prefix?: string; suffix?: string; + isFixed?: boolean; } export type DragHandleItemOptionProps = DragHandleItemStyleProps & DragHandleItemCustomProps; diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts index 1dbe0ca71..eadff482e 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts +++ b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts @@ -64,12 +64,6 @@ export const editingContainerStyle = css({ margin: 0, }); -export const isFixedIconStyle = ({theme}: WithTheme) => - css({ - color: theme.colors.error, - paddingRight: '0.25rem', - }); - export const underlineStyle = ({theme, hasFocus, hasError}: WithTheme<UnderlineProps>) => css({ position: 'relative', diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/HDesign/src/components/EditableItem/EditableItem.Input.tsx index 10381fbed..c0a08bc0e 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.tsx +++ b/HDesign/src/components/EditableItem/EditableItem.Input.tsx @@ -1,18 +1,13 @@ /** @jsxImportSource @emotion/react */ -import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; +import {forwardRef, useEffect, useImperativeHandle, useRef} from 'react'; import Flex from '@components/Flex/Flex'; import Text from '@components/Text/Text'; +import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; import {useTheme} from '@theme/HDesignProvider'; -import { - editingContainerStyle, - inputStyle, - inputWrapperStyle, - isFixedIconStyle, - underlineStyle, -} from './EditableItem.Input.style'; +import {editingContainerStyle, inputStyle, inputWrapperStyle, underlineStyle} from './EditableItem.Input.style'; import {InputProps} from './EditableItem.Input.type'; import useEditableItemInput from './useEditableItemInput'; @@ -38,7 +33,7 @@ export const EditableItemInput = forwardRef<HTMLInputElement, InputProps>(functi <div ref={shadowRef} css={editingContainerStyle}> <Text size={textSize}>{htmlProps.value || htmlProps.placeholder}</Text> </div> - {isFixed && <div css={isFixedIconStyle({theme})}>*</div>} + {isFixed && <IsFixedIcon />} <div css={underlineStyle({theme, hasError, hasFocus})}> <input css={inputStyle({ diff --git a/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts b/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts new file mode 100644 index 000000000..6ba001e05 --- /dev/null +++ b/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +import {WithTheme} from '@type/withTheme'; + +export const isFixedIconStyle = ({theme}: WithTheme) => + css({ + color: theme.colors.error, + paddingRight: '0.25rem', + }); diff --git a/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx b/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx new file mode 100644 index 000000000..a7b62d959 --- /dev/null +++ b/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx @@ -0,0 +1,13 @@ +/** @jsxImportSource @emotion/react */ + +import {useTheme} from '@theme/HDesignProvider'; + +import {isFixedIconStyle} from './IsFixedIcon.style'; + +const IsFixedIcon = () => { + const {theme} = useTheme(); + + return <div css={isFixedIconStyle({theme})}>*</div>; +}; + +export default IsFixedIcon; diff --git a/client/package-lock.json b/client/package-lock.json index d9f21f883..b7df876e4 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -4127,9 +4127,9 @@ } }, "node_modules/@swc/core": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.11.tgz", - "integrity": "sha512-AB+qc45UrJrDfbhPKcUXk+9z/NmFfYYwJT6G7/iur0fCse9kXjx45gi40+u/O2zgarG/30/zV6E3ps8fUvjh7g==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.14.tgz", + "integrity": "sha512-9aeXeifnyuvc2pcuuhPQgVUwdpGEzZ+9nJu0W8/hNl/aESFsJGR5i9uQJRGu0atoNr01gK092fvmqMmQAPcKow==", "hasInstallScript": true, "dependencies": { "@swc/counter": "^0.1.3", @@ -4143,16 +4143,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.11", - "@swc/core-darwin-x64": "1.7.11", - "@swc/core-linux-arm-gnueabihf": "1.7.11", - "@swc/core-linux-arm64-gnu": "1.7.11", - "@swc/core-linux-arm64-musl": "1.7.11", - "@swc/core-linux-x64-gnu": "1.7.11", - "@swc/core-linux-x64-musl": "1.7.11", - "@swc/core-win32-arm64-msvc": "1.7.11", - "@swc/core-win32-ia32-msvc": "1.7.11", - "@swc/core-win32-x64-msvc": "1.7.11" + "@swc/core-darwin-arm64": "1.7.14", + "@swc/core-darwin-x64": "1.7.14", + "@swc/core-linux-arm-gnueabihf": "1.7.14", + "@swc/core-linux-arm64-gnu": "1.7.14", + "@swc/core-linux-arm64-musl": "1.7.14", + "@swc/core-linux-x64-gnu": "1.7.14", + "@swc/core-linux-x64-musl": "1.7.14", + "@swc/core-win32-arm64-msvc": "1.7.14", + "@swc/core-win32-ia32-msvc": "1.7.14", + "@swc/core-win32-x64-msvc": "1.7.14" }, "peerDependencies": { "@swc/helpers": "*" @@ -4164,9 +4164,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.11.tgz", - "integrity": "sha512-HRQv4qIeMBPThZ6Y/4yYW52rGsS6yrpusvuxLGyoFo45Y0y12/V2yXkOIA/0HIQyrqoUAxn1k4zQXpPaPNCmnw==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.14.tgz", + "integrity": "sha512-V0OUXjOH+hdGxDYG8NkQzy25mKOpcNKFpqtZEzLe5V/CpLJPnpg1+pMz70m14s9ZFda9OxsjlvPbg1FLUwhgIQ==", "cpu": [ "arm64" ], @@ -4179,9 +4179,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.11.tgz", - "integrity": "sha512-vtMQj0F3oYwDu5yhO7SKDRg1XekRSi6/TbzHAbBXv+dBhlGGvcZZynT1H90EVFTv+7w7Sh+lOFvRv5Z4ZTcxow==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.14.tgz", + "integrity": "sha512-9iFvUnxG6FC3An5ogp5jbBfQuUmTTwy8KMB+ZddUoPB3NR1eV+Y9vOh/tfWcenSJbgOKDLgYC5D/b1mHAprsrQ==", "cpu": [ "x64" ], @@ -4194,9 +4194,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.11.tgz", - "integrity": "sha512-mHtzWKxhtyreI4CSxs+3+ENv8t/Qo35WFoYG66qHEgJz/Z2Lh6jv1E+MYgHdYwnpQHgHbdvAco7HsBu/Dt6xXw==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.14.tgz", + "integrity": "sha512-zGJsef9qPivKSH8Vv4F/HiBXBTHZ5Hs3ZjVGo/UIdWPJF8fTL9OVADiRrl34Q7zOZEtGXRwEKLUW1SCQcbDvZA==", "cpu": [ "arm" ], @@ -4209,9 +4209,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.11.tgz", - "integrity": "sha512-FRwe/x0GfXSQjGP2lIk+NO0pUFS/lI/RorCLBPiK808EVE9JTbh9DKCc/4Bbb4jgScAjNkrFCUVObQYl3YKmpA==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.14.tgz", + "integrity": "sha512-AxV3MPsoI7i4B8FXOew3dx3N8y00YoJYvIPfxelw07RegeCEH3aHp2U2DtgbP/NV1ugZMx0TL2Z2DEvocmA51g==", "cpu": [ "arm64" ], @@ -4224,9 +4224,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.11.tgz", - "integrity": "sha512-GY/rs0+GUq14Gbnza90KOrQd/9yHd5qQMii5jcSWcUCT5A8QTa8kiicsM2NxZeTJ69xlKmT7sLod5l99lki/2A==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.14.tgz", + "integrity": "sha512-JDLdNjUj3zPehd4+DrQD8Ltb3B5lD8D05IwePyDWw+uR/YPc7w/TX1FUVci5h3giJnlMCJRvi1IQYV7K1n7KtQ==", "cpu": [ "arm64" ], @@ -4239,9 +4239,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.11.tgz", - "integrity": "sha512-QDkGRwSPmp2RBOlSs503IUXlWYlny8DyznTT0QuK0ML2RpDFlXWU94K/EZhS0RBEUkMY/W51OacM8P8aS/dkCg==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.14.tgz", + "integrity": "sha512-Siy5OvPCLLWmMdx4msnEs8HvEVUEigSn0+3pbLjv78iwzXd0qSBNHUPZyC1xeurVaUbpNDxZTpPRIwpqNE2+Og==", "cpu": [ "x64" ], @@ -4254,9 +4254,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.11.tgz", - "integrity": "sha512-SBEfKrXy6zQ6ksnyxw1FaCftrIH4fLfA81xNnKb7x/6iblv7Ko6H0aK3P5C86jyqF/82+ONl9C7ImGkUFQADig==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.14.tgz", + "integrity": "sha512-FtEGm9mwtRYQNK43WMtUIadxHs/ja2rnDurB99os0ZoFTGG2IHuht2zD97W0wB8JbqEabT1XwSG9Y5wmN+ciEQ==", "cpu": [ "x64" ], @@ -4269,9 +4269,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.11.tgz", - "integrity": "sha512-a2Y4xxEsLLYHJN7sMnw9+YQJDi3M1BxEr9hklfopPuGGnYLFNnx5CypH1l9ReijEfWjIAHNi7pq3m023lzW1Hg==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.14.tgz", + "integrity": "sha512-Jp8KDlfq7Ntt2/BXr0y344cYgB1zf0DaLzDZ1ZJR6rYlAzWYSccLYcxHa97VGnsYhhPspMpmCvHid97oe2hl4A==", "cpu": [ "arm64" ], @@ -4284,9 +4284,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.11.tgz", - "integrity": "sha512-ZbZFMwZO+j8ulhegJ7EhJ/QVZPoQ5qc30ylJQSxizizTJaen71Q7/13lXWc6ksuCKvg6dUKrp/TPgoxOOtSrFA==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.14.tgz", + "integrity": "sha512-I+cFsXF0OU0J9J4zdWiQKKLURO5dvCujH9Jr8N0cErdy54l9d4gfIxdctfTF+7FyXtWKLTCkp+oby9BQhkFGWA==", "cpu": [ "ia32" ], @@ -4299,9 +4299,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.11.tgz", - "integrity": "sha512-IUohZedSJyDu/ReEBG/mqX6uG29uA7zZ9z6dIAF+p6eFxjXmh9MuHryyM+H8ebUyoq/Ad3rL+rUCksnuYNnI0w==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.14.tgz", + "integrity": "sha512-NNrprQCK6d28mG436jVo2TD+vACHseUECacEBGZ9Ef0qfOIWS1XIt2MisQKG0Oea2VvLFl6tF/V4Lnx/H0Sn3Q==", "cpu": [ "x64" ], diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index d60e7fc61..182f40bda 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -1,8 +1,11 @@ import type {BillAction} from 'types/serviceType'; -import {BottomSheet, FixedButton, LabelGroupInput, Text} from 'haengdong-design'; +import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; import validatePurchase from '@utils/validate/validatePurchase'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; +import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; @@ -19,47 +22,119 @@ const PutAndDeleteBillActionModal = ({ isBottomSheetOpened, setIsBottomSheetOpened, }: PutAndDeleteBillActionModalProps) => { - const {inputPair, handleInputChange, handleOnBlur, errorMessage, errorInfo, canSubmit, onSubmit, onDelete} = - usePutAndDeleteBillAction( - {title: billAction.name, price: String(billAction.price), index: 0}, - validatePurchase, - () => setIsBottomSheetOpened(false), - ); + const { + inputPair, + handleInputChange, + // handleOnBlur, + // errorMessage, + // errorInfo, + canSubmit, + onDelete, + onSubmit: putBillAction, + } = usePutAndDeleteBillAction( + {title: billAction.name, price: String(billAction.price), index: 0}, + validatePurchase, + () => setIsBottomSheetOpened(false), + ); + + const { + memberReportListInAction, + addAdjustedMember, + onSubmit: putMemberReportListInAction, + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + isExistAdjustedPrice, + } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price)); + const { + inputList, + onChange, + canEditList, + canSubmit: isChangedMemberReportInput, + } = useMemberReportInput({ + data: memberReportListInAction, + addAdjustedMember, + totalPrice: billAction.price, + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + }); + + const {data: stepListData = []} = useRequestGetStepList(); + + const actionMemberList = stepListData.filter(({actions}) => + actions.find(({actionId}) => actionId === billAction.actionId), + )[0].members; return ( <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> - <form css={bottomSheetStyle} onSubmit={event => onSubmit(event, inputPair, billAction.actionId)}> + <form + css={bottomSheetStyle} + onSubmit={event => { + putBillAction(event, inputPair, billAction.actionId); + putMemberReportListInAction(); + }} + > <h2 css={bottomSheetHeaderStyle}> <Text size="bodyBold">지출 내역 수정하기</Text> </h2> <fieldset css={inputContainerStyle}> - <LabelGroupInput labelText="지출내역 / 금액" errorText={errorMessage ?? ''}> - <LabelGroupInput.Element - aria-label="지출 내역" - elementKey={'title'} - type="text" - value={inputPair.title} - onChange={event => handleInputChange('title', event)} - onBlur={handleOnBlur} - isError={errorInfo.title} + <EditableItem backgroundColor="lightGrayContainer" prefixLabelText="지출 내역 / 금액"> + <EditableItem.Input placeholder="지출 내역" + textSize="bodyBold" + value={inputPair.title} + onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('title', event)} /> - <LabelGroupInput.Element - aria-label="금액" - elementKey={'price'} - type="number" - value={inputPair.price} - onChange={event => handleInputChange('price', event)} - onBlur={handleOnBlur} - isError={errorInfo.price} - placeholder="금액" - /> - </LabelGroupInput> + <Flex alignItems="center" gap="0.25rem"> + <EditableItem.Input + placeholder="0" + style={{ + textAlign: 'right', + }} + type="number" + value={inputPair.price} + onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('price', event)} + isFixed={isExistAdjustedPrice()} + /> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + + <EditableItem + backgroundColor="lightGrayContainer" + prefixLabelText="참여자" + suffixLabelText={`총 ${actionMemberList.length}명`} + > + <Flex flexDirection="column" width="100%" gap="1rem"> + {inputList.map(({name, price, isFixed}, index) => ( + <Flex key={name} justifyContent="spaceBetween"> + <EditableItem.Input + value={name} + placeholder="참여자 명" + textSize="smallBodyBold" + disabled + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + onChange={event => onChange(event, index)} + isFixed={isFixed} + textSize="smallBody" + value={price} + placeholder="0" + type="number" + readOnly={!canEditList[index]} + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </Flex> + ))} + </Flex> + </EditableItem> </fieldset> <FixedButton type="submit" variants="primary" - disabled={!canSubmit} + disabled={!(canSubmit || isChangedMemberReportInput)} onDeleteClick={() => onDelete(billAction.actionId)} > 수정 완료 diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 02f738904..69e364c8a 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -1,6 +1,6 @@ import type {Bill} from 'types/serviceType'; -import {useState} from 'react'; +import {useEffect, useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; @@ -24,19 +24,21 @@ const usePutAndDeleteBillAction = ( const {mutate: putBillAction} = usePutBillAction(); const {mutate: deleteBillAction} = useDeleteBillAction(); + // 현재 타겟의 event.target.value를 넣어주기 위해서 + const getFieldValue = (field: BillInputType, value: string) => { + if (field === 'title') { + return {title: value, price: Number(inputPair.price)}; + } else { + return {title: inputPair.title, price: Number(value)}; + } + }; + + // TODO: (@weadie) getFieldValue 를 리펙토링해야한다. + const handleInputChange = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; - // 현재 타겟의 event.target.value를 넣어주기 위해서 - const getFieldValue = (): Bill => { - if (field === 'title') { - return {title: value, price: Number(inputPair.price)}; - } else { - return {title: inputPair.title, price: Number(value)}; - } - }; - - const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue()); + const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue(field, value)); setErrorMessage(errorMessage); @@ -50,9 +52,12 @@ const usePutAndDeleteBillAction = ( }); setCanSubmit(value.length !== 0); } else { + const {isValid: isValidName} = validateFunc(getFieldValue('title', inputPair.title)); + const {isValid: isValidPrice} = validateFunc(getFieldValue('price', inputPair.price)); + + setCanSubmit(isValidName && isValidPrice); // valid하지 않으면 event.target.value 덮어쓰기 event.target.value = inputPair[field]; - setCanSubmit(false); } if (field === 'title') { From 8ceb42fa7311e8261355ec24705434526e0d7799 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:25:21 +0900 Subject: [PATCH 182/273] =?UTF-8?q?feat:=20BottomSheet=20=EC=A7=80?= =?UTF-8?q?=EC=B6=9C=20=EB=B6=80=EB=B6=84=20=EC=82=AD=EC=A0=9C=20&=20input?= =?UTF-8?q?=20autoFocus=20(#433)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe <pigkill40@naver.com> * design: 기본 css style 초기화 작업 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * design: 전역 스타일링 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우터 셋팅 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 앱의 진입점 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우트 경로 설정 Co-authored-by: pakxe <pigkill40@naver.com> * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 인원 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Input component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Title component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: BottomSheet component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 메서드 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 코드 컨벤션 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: 메서드 순서 변경 Co-authored-by: Arachne <jhg2819@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> authored-by: khabh <khabh@naver.com> * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 <rhymint@gmail.com> * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * refactor: global style app과 index에 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> --------- Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * style: lint 적용 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers<HTMLElement>' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * fix: 사용하지 않는 지출 Modal Input 삭제 * remove: 지출 추가 로직 변경으로 인해 사용하지 않는 파일 제거 * feat: 첫번째 Input에 focus 적용 * feat: 첫번째 DynamicInput에 autoFocus 적용 * fix: StepListProps 속성이 없어서 발생하는 에러 해결 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: juha <khabh@naver.com> Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> --- .../AddBillActionListModalContent.style.ts | 31 ---- .../AddBillActionListModalContent.tsx | 74 --------- .../AddBillActionListModalContent/index.ts | 1 - .../InMember.tsx | 1 + .../OutMember.tsx | 1 + .../SetActionModal/SetActionListModal.tsx | 27 ++-- .../SetInitialMemberListModal.tsx | 1 + client/src/components/StepList/StepList.tsx | 6 +- .../src/hooks/useDynamicBillActionInput.tsx | 140 ------------------ client/src/hooks/usePutAndDeleteBillAction.ts | 4 +- client/src/hooks/useSetBillInput.ts | 3 +- client/src/types/serviceType.ts | 7 + 12 files changed, 24 insertions(+), 272 deletions(-) delete mode 100644 client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.style.ts delete mode 100644 client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddBillActionListModalContent/index.ts delete mode 100644 client/src/hooks/useDynamicBillActionInput.tsx diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.style.ts b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.style.ts deleted file mode 100644 index 80c770362..000000000 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.style.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {css} from '@emotion/react'; - -const container = () => - css({ - height: '100%', - }); - -const inputContainer = () => - css({ - display: 'flex', - height: '100%', - flexDirection: 'column', - gap: '1.5rem', - overflow: 'auto', - paddingBottom: '14rem', - }); - -export const input = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '0.5rem', - }); - -const addBillActionListStyle = { - container, - inputContainer, - input, -}; - -export default addBillActionListStyle; diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx deleted file mode 100644 index 553a7ae15..000000000 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/AddBillActionListModalContent.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import {FixedButton, LabelGroupInput} from 'haengdong-design'; - -import validatePurchase from '@utils/validate/validatePurchase'; -import useRequestPostBillList from '@hooks/queries/useRequestPostBillList'; - -import useDynamicBillActionInput from '@hooks/useDynamicBillActionInput'; - -import style from './AddBillActionListModalContent.style'; - -interface AddBillActionListModalContentProps { - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -} - -const AddBillActionListModalContent = ({setIsOpenBottomSheet}: AddBillActionListModalContentProps) => { - // useDynamicBillActionInput에서 errorIndexList 반환하지 않음 - const { - inputPairList, - inputRefList, - errorMessage, - handleInputChange, - getFilledInputPairList, - deleteEmptyInputPairElementOnBlur, - focusNextInputOnEnter, - } = useDynamicBillActionInput(validatePurchase); - - const {mutate: postBillList} = useRequestPostBillList(); - - const handleSetPurchaseSubmit = () => { - // TODO: (@weadie) 요청 실패시 오류 핸들 필요 - postBillList({billList: getFilledInputPairList().map(({title, price}) => ({title, price: Number(price)}))}); - setIsOpenBottomSheet(false); - }; - - return ( - <div css={style.container}> - <div css={style.inputContainer}> - <LabelGroupInput labelText="지출내역 / 금액" errorText={errorMessage}> - {inputPairList.map(({index, title, price}) => ( - <div key={index} css={style.input}> - <LabelGroupInput.Element - elementKey={`${index}`} - type="text" - value={title} - onChange={e => handleInputChange(index, 'title', e)} - onKeyDown={e => focusNextInputOnEnter(e, index, 'title')} - onBlur={() => deleteEmptyInputPairElementOnBlur()} // TODO: (@weadie) 이 블러프롭이 내부적으로 index를 넘기고 있기 때문에 화살표 함수로 써야만하내요.. - placeholder="지출 내역" - ref={el => (inputRefList.current[index * 2] = el)} - /> - <LabelGroupInput.Element - elementKey={`${index}`} - type="number" - value={price} - onChange={e => handleInputChange(index, 'price', e)} - onKeyDown={e => focusNextInputOnEnter(e, index, 'price')} - onBlur={() => deleteEmptyInputPairElementOnBlur()} - placeholder="금액" - ref={el => (inputRefList.current[index * 2 + 1] = el)} - /> - </div> - ))} - </LabelGroupInput> - </div> - <FixedButton - disabled={!(inputPairList.length - 1)} - variants={'primary'} - children={'추가하기'} - onClick={handleSetPurchaseSubmit} - /> - </div> - ); -}; - -export default AddBillActionListModalContent; diff --git a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/index.ts b/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/index.ts deleted file mode 100644 index ed3e43886..000000000 --- a/client/src/components/Modal/SetActionModal/AddBillActionListModalContent/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as AddBillActionListModalContent} from './AddBillActionListModalContent'; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx index 54949fc04..5f9f9a2e0 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx @@ -27,6 +27,7 @@ const InMember = ({dynamicProps}: InMemberProps) => { onBlur={() => deleteEmptyInputElementOnBlur()} onKeyDown={e => focusNextInputOnEnter(e, index)} placeholder="이름" + autoFocus={inputList.length === 1 && index === 0} /> )); }; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx index 949d47fa9..9294b18ae 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -43,6 +43,7 @@ const OutMember = ({dynamicProps}: OutMemberProps) => { onBlur={() => deleteEmptyInputElementOnBlur()} onKeyDown={e => focusNextInputOnEnter(e, index)} placeholder="이름" + autoFocus={inputList.length === 1 && index === 0} /> </Search> )); diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx index 4a6ea10a6..862bd91e3 100644 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -1,9 +1,8 @@ import type {InOutType} from 'types/serviceType'; import {useState} from 'react'; -import {BottomSheet, Switch} from 'haengdong-design'; +import {BottomSheet, Switch, Text} from 'haengdong-design'; -import {AddBillActionListModalContent} from './AddBillActionListModalContent'; import {AddMemberActionListModalContent} from './AddMemberActionListModalContent'; import style from './SetActionListModal.style'; @@ -15,13 +14,8 @@ interface SetActionModalContentProps { } const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetActionModalContentProps) => { - const [action, setAction] = useState<ActionType>('지출'); const [inOutAction, setInOutAction] = useState<InOutType>('탈주'); - const handleActionTypeChange = (value: string) => { - setAction(value as ActionType); - }; - const handleParticipantTypeChange = (value: string) => { setInOutAction(value as InOutType); }; @@ -30,19 +24,16 @@ const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetAction <BottomSheet isOpened={isOpenBottomSheet} onClose={() => setIsOpenBottomSheet(false)}> <div css={style.container}> <div css={style.switchContainer}> - <Switch value={action} onChange={handleActionTypeChange} values={['지출', '인원']} /> - {action === '인원' && ( - <Switch values={['늦참', '탈주']} value={inOutAction} onChange={handleParticipantTypeChange} /> - )} + <Text size="bodyBold" color="onTertiary"> + 인원 변동 + </Text> + <Switch values={['늦참', '탈주']} value={inOutAction} onChange={handleParticipantTypeChange} /> </div> - {action === '지출' && <AddBillActionListModalContent setIsOpenBottomSheet={setIsOpenBottomSheet} />} - {action === '인원' && ( - <AddMemberActionListModalContent - inOutAction={inOutAction === '탈주' ? 'OUT' : 'IN'} - setIsOpenBottomSheet={setIsOpenBottomSheet} - /> - )} + <AddMemberActionListModalContent + inOutAction={inOutAction === '탈주' ? 'OUT' : 'IN'} + setIsOpenBottomSheet={setIsOpenBottomSheet} + /> </div> </BottomSheet> ); diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index 223f725e8..8c9ef26e0 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -51,6 +51,7 @@ const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: Se onChange={e => handleInputChange(index, e)} onBlur={() => deleteEmptyInputElementOnBlur()} onKeyDown={e => focusNextInputOnEnter(e, index)} + autoFocus={inputList.length === 1 && index === 0} /> ))} </LabelGroupInput> diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 755bf8ac6..88a1ee425 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -7,11 +7,11 @@ import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; import Step from './Step'; interface StepListProps { - isAddEditableItem: boolean; - setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; + isAddEditableItem?: boolean; + setIsAddEditableItem?: React.Dispatch<React.SetStateAction<boolean>>; } -const StepList = ({isAddEditableItem, setIsAddEditableItem}: StepListProps) => { +const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: StepListProps) => { const {data: stepListData} = useRequestGetStepList(); const [stepList, setStepList] = useState<(MemberStep | BillStep)[]>([]); const existIndexInStepList = stepList.map((step, index) => ({...step, index})); diff --git a/client/src/hooks/useDynamicBillActionInput.tsx b/client/src/hooks/useDynamicBillActionInput.tsx deleted file mode 100644 index d07794751..000000000 --- a/client/src/hooks/useDynamicBillActionInput.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import {useEffect, useRef, useState} from 'react'; - -import {ValidateResult} from '@utils/validate/type'; -import {Bill} from 'types/serviceType'; - -export type InputPair = Omit<Bill, 'price'> & { - price: string; - index: number; -}; - -export type BillInputType = 'title' | 'price'; - -// TODO: (@weadie) 지나치게 도메인에 묶여있는 인풋. 절대 다른 페어인풋으로 재사용할 수 없다. -const useDynamicBillActionInput = (validateFunc: (inputPair: Bill) => ValidateResult) => { - const [inputPairList, setInputPairList] = useState<InputPair[]>([{title: '', price: '', index: 0}]); - const inputRefList = useRef<(HTMLInputElement | null)[]>([]); - const [errorMessage, setErrorMessage] = useState(''); - const [canSubmit, setCanSubmit] = useState(false); - - useEffect(() => { - if (inputRefList.current.length > 0) { - const lastInputPair = inputRefList.current.slice(-2); - lastInputPair.forEach(ref => ref?.scrollIntoView({behavior: 'smooth', block: 'center'})); - } - }, [inputPairList]); - - const handleInputChange = (index: number, field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { - const {value} = event.target; - const targetInputPair = findInputPairByIndex(index); - const {isValid: isValidInput, errorMessage: validationResultMessage} = validateFunc({ - ...targetInputPair, - price: 0, // price가 input에서 0을 초기값으로 갖지않도록 타입을 수정했기 때문에 0을 명시적으로 넘겨줍니다. - [field]: value, - }); - - // TODO: (@weadie) 가독성이 안좋다는 리뷰. 함수로 분리 - if (isLastInputPairFilled({index, field, value})) { - setErrorMessage(''); - setInputPairList(prevInputPairList => { - const updatedInputPairList = [...prevInputPairList]; - const targetInputPair = findInputPairByIndex(index, updatedInputPairList); - - targetInputPair[field] = value; - - // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 - const newIndex = updatedInputPairList[updatedInputPairList.length - 1].index + 1; - const finalInputs = [...updatedInputPairList, {index: newIndex, title: '', price: ''}]; - - return finalInputs; - }); - } else if (isValidInput || value.length === 0) { - setErrorMessage(''); - setInputPairList(prevInputPairList => { - const updatedInputPairList = [...prevInputPairList]; - const targetInputPair = findInputPairByIndex(index, updatedInputPairList); - - targetInputPair[field] = value; - - return updatedInputPairList; - }); - } else { - const targetInput = findInputPairByIndex(index); - - event.target.value = targetInput[field]; - - setErrorMessage(validationResultMessage ?? ''); - } - - handleCanSubmit(); - }; - - const deleteEmptyInputPairElementOnBlur = () => { - // 이름, 금액 2개중 최소 하나 이상 값을 가지고 있는 inputPair 배열 - const filledMinInputPairList = inputPairList.filter(({title, price}) => title !== '' || price !== ''); - - // 0쌍, 1쌍 input이 값이 있는 상태에서 두 쌍의 값을 모두 x버튼으로 제거해도 입력 쌍이 2개 남아있는 문제를 위해 조건문을 추가했습니다. - if (filledMinInputPairList.length === 0 && inputPairList.length > 1) { - setInputPairList([{index: 0, title: '', price: ''}]); - return; - } - - if (filledMinInputPairList.length === 0) return; - - if (filledMinInputPairList.length !== inputPairList.length) { - // 이름, 금액 2개중 하나라도 값이 있다면 지우지 않습니다. - setInputPairList(prevInputPairList => { - const filledInputPairList = prevInputPairList.filter(({title, price}) => title !== '' || price !== ''); - - const newIndex = filledInputPairList[filledInputPairList.length - 1].index + 1; - return [...filledInputPairList, {index: newIndex, title: '', price: ''}]; - }); - } - }; - - const handleCanSubmit = () => { - setCanSubmit(inputPairList.length > 0 && getFilledInputPairList().length > 0); - }; - - const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number, field: BillInputType) => { - if (e.nativeEvent.isComposing) return; - - if (e.key === 'Enter') { - // 2개(제목, 가격)를 쌍으로 index를 관리하고 있으므로 input element 정확히 특정하기 위한 개별 input element key 값을 계산합니다. - const exactInputIndex = index * 2 + (field === 'title' ? 0 : 1); - - inputRefList.current[exactInputIndex + 1]?.focus(); - } - }; - - // 아래부터는 이 훅에서 재사용되는 함수입니다. - - // list 인자를 넘겨주면 그 인자로 찾고, 없다면 InputPairList state를 사용합니다. - const findInputPairByIndex = (index: number, list?: InputPair[]) => { - return (list ?? inputPairList).filter(input => input.index === index)[0]; - }; - - // list 인자를 넘겨주면 그 인자로 찾고, 없다면 InputPairList state를 사용합니다. - const getFilledInputPairList = (list?: InputPair[]) => { - return (list ?? inputPairList).filter(({title, price}) => title !== '' && price !== ''); - }; - - const isLastInputPairFilled = ({index, value}: {index: number; field: BillInputType; value: string}) => { - const lastInputIndex = inputPairList[inputPairList.length - 1].index; - - return value !== '' && index === lastInputIndex; - }; - - return { - inputPairList, - getFilledInputPairList, - inputRefList, - handleInputChange, - deleteEmptyInputPairElementOnBlur, - errorMessage, - canSubmit, - focusNextInputOnEnter, - }; -}; - -export default useDynamicBillActionInput; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 69e364c8a..b1ae2b78f 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -1,11 +1,9 @@ -import type {Bill} from 'types/serviceType'; +import type {Bill, BillInputType, InputPair} from 'types/serviceType'; import {useEffect, useState} from 'react'; import {ValidateResult} from '@utils/validate/type'; -import {BillInputType, InputPair} from '@hooks/useDynamicBillActionInput'; - import {ERROR_MESSAGE} from '@constants/errorMessage'; import usePutBillAction from './queries/useRequestPutBillAction'; diff --git a/client/src/hooks/useSetBillInput.ts b/client/src/hooks/useSetBillInput.ts index c1dd4a394..4f839602a 100644 --- a/client/src/hooks/useSetBillInput.ts +++ b/client/src/hooks/useSetBillInput.ts @@ -1,10 +1,9 @@ import {useState} from 'react'; import validatePurchase from '@utils/validate/validatePurchase'; -import {Bill} from 'types/serviceType'; +import {Bill, BillInputType} from 'types/serviceType'; import useRequestPostBillList from './queries/useRequestPostBillList'; -import {BillInputType, InputPair} from './useDynamicBillActionInput'; interface UseSetBillInputProps { setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts index 1dd69dcfb..0467995f1 100644 --- a/client/src/types/serviceType.ts +++ b/client/src/types/serviceType.ts @@ -71,3 +71,10 @@ export type ConvertedAction = { sequence: number; type: ActionType; }; + +export type InputPair = Omit<Bill, 'price'> & { + price: string; + index: number; +}; + +export type BillInputType = 'title' | 'price'; From bd3f3e248b789d0bd1c49b0d9c4caee44eabb5cc Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:32:17 +0900 Subject: [PATCH 183/273] =?UTF-8?q?fix:=20height=EA=B0=80=20=EC=A7=A4?= =?UTF-8?q?=EB=A6=AC=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?(#434)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/GlobalStyle.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index e12b5f693..a37f2ac13 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -134,6 +134,10 @@ export const GlobalStyle = css` box-sizing: border-box; } + html { + height: 100%; + } + body { max-width: 768px; height: 100%; From 1c0161697a746c9caaaca0d419601df806d46bc1 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:41:53 +0900 Subject: [PATCH 184/273] =?UTF-8?q?fix:=20=EC=B0=A8=EB=93=B1=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EC=9D=B8=EC=9B=90=EC=9D=B4=202=EB=AA=85=EC=9D=BC?= =?UTF-8?q?=20=EB=95=8C=20=EA=B3=84=EC=82=B0=EB=90=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EB=B2=84=EA=B7=B8=20(#435)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 나머지 1명만 조정치가 아닐 때 계산이 되지 않았던 버그 수정 * test: 2명일 때의 테스트 진행 * fix: 마지막 사람이 값이 변경될 수 없으므로 (input = disabled 처리) 관련 로직 훅에서 제거 * test: 발생할 수 없는 테스트 제거 --- .../useMemberReportListInAction.test.tsx | 75 +++++++++++-------- .../useMemberReportListInAction.ts | 4 - .../handlers/memberReportInActionHandlers.ts | 24 ++++-- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx index 99d3b1814..e499157c2 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx @@ -1,4 +1,4 @@ -import type {MemberReport, MemberReportInAction} from 'types/serviceType'; +import type {MemberReportInAction} from 'types/serviceType'; import {renderHook, waitFor, act} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; @@ -165,38 +165,6 @@ describe('useMemberReportListInActionTest', () => { expect(anotherMemberList[0].price).toBe(33300); }); - it('참여인원의 가격을 모두 바꾸려고 하면, 마지막 사람의 조정치는 반영되지 않는다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; - const adjustedMemberSoha: MemberReportInAction = {name: '소하', price: 100, isFixed: false}; - - // 마지막 사람 - const adjustedMemberLeeSang: MemberReportInAction = {name: '이상', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookie); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberSoha); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberLeeSang); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); - - expect(targetMember?.price).not.toBe(100); - }); - it('망쵸에게 300원을 주면 나머지 사람들은 33233원이고 마지막 사람은 33234원이 된다.', async () => { const {result} = initializeProvider(actionId, totalPrice); const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 300, isFixed: false}; @@ -298,6 +266,47 @@ describe('useMemberReportListInActionTest', () => { }); }); + describe('지출 인원이 2명인 상황', () => { + const actionId = 1; + const totalPrice = 50000; + + // 망쵸 이상 + it('망쵸의 가격을 100원으로 수정한 경우, 이상의 가격이 49900원으로 수정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); + + expect(targetMember?.price).toBe(49900); + }); + + it('망쵸의 가격을 100원으로 수정하고 다시 200원으로 수정한 경우, 이상의 가격이 49800원으로 수정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberMangchoOther: MemberReportInAction = {name: '망쵸', price: 200, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoOther); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); + + expect(targetMember?.price).toBe(49800); + }); + }); + // last describe('onSubmit 실행 시 반영 테스트', () => { it('망쵸의 가격을 100원으로 바꾸고 저장하면 망쵸 100원이 반영된다.', async () => { diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts index c9e16ff3b..4ae984ae6 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts @@ -64,10 +64,6 @@ const useMemberReportListInAction = (actionId: number, totalPrice: number) => { }; const addAdjustedMember = (memberReport: MemberReportInAction) => { - if (getAdjustedMemberCount(memberReportListInAction) + 1 >= memberReportListInAction.length) { - return; - } - const newMemberReportListInAction = memberReportListInAction.map(member => member.name === memberReport.name ? {...member, price: memberReport.price, isFixed: true} : member, ); diff --git a/client/src/mocks/handlers/memberReportInActionHandlers.ts b/client/src/mocks/handlers/memberReportInActionHandlers.ts index 7c9b5b1b1..45de357f1 100644 --- a/client/src/mocks/handlers/memberReportInActionHandlers.ts +++ b/client/src/mocks/handlers/memberReportInActionHandlers.ts @@ -8,17 +8,31 @@ import memberReportInActionJson from '../memberReportListInAction.json'; let memberReportInActionMockData = memberReportInActionJson as MemberReport[]; +type MemberReportListRequestParams = { + eventId: string; + actionId: string; +}; type MemberReportListBody = {members: MemberReport[]}; export const memberReportInActionHandler = [ - http.get<any, MemberReportListBody, any, `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`>( - `${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, - () => { + http.get< + MemberReportListRequestParams, + MemberReportListBody, + any, + `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed` + >(`${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, ({params}) => { + const {actionId} = params; + + if (Number(actionId) === 123) { return HttpResponse.json({ members: memberReportInActionMockData, }); - }, - ), + } + + return HttpResponse.json({ + members: memberReportInActionMockData.slice(0, 2), + }); + }), http.put<any, MemberReportListBody, any, `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`>( `${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, From eda2e25f57bd216cc8ad466156769cb362d9bfa2 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:49:13 +0900 Subject: [PATCH 185/273] =?UTF-8?q?feat:=20=EB=9E=9C=EB=94=A9=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EA=B5=AC=ED=98=84=20(#418)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 랜딩페이지 구현 * style: lint 적용 * fix: 문구 수정 * style: lint 적용 * fix: 랜딩페이지 화면의 변화에 따른 e2e 테스트 코드 변경 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> --- client/cypress/e2e/createEvent.cy.ts | 2 +- client/src/assets/image/addBillMockup.svg | 312 +++++++++++++++++ client/src/assets/image/addMemberMockup.svg | 317 ++++++++++++++++++ client/src/assets/image/chevronDownLarge.svg | 3 + .../src/assets/image/memberReportMockup.svg | 311 +++++++++++++++++ client/src/pages/MainPage/MainPage.tsx | 24 +- client/src/pages/MainPage/Nav/Nav.style.ts | 25 ++ client/src/pages/MainPage/Nav/Nav.tsx | 25 ++ .../pages/MainPage/Section/AddBillSection.tsx | 31 ++ .../MainPage/Section/AddMemberSection.tsx | 33 ++ .../MainPage/Section/DescriptionSection.tsx | 33 ++ .../pages/MainPage/Section/MainSection.tsx | 93 +++++ .../MainPage/Section/MemberReportSection.tsx | 31 ++ 13 files changed, 1228 insertions(+), 12 deletions(-) create mode 100644 client/src/assets/image/addBillMockup.svg create mode 100644 client/src/assets/image/addMemberMockup.svg create mode 100644 client/src/assets/image/chevronDownLarge.svg create mode 100644 client/src/assets/image/memberReportMockup.svg create mode 100644 client/src/pages/MainPage/Nav/Nav.style.ts create mode 100644 client/src/pages/MainPage/Nav/Nav.tsx create mode 100644 client/src/pages/MainPage/Section/AddBillSection.tsx create mode 100644 client/src/pages/MainPage/Section/AddMemberSection.tsx create mode 100644 client/src/pages/MainPage/Section/DescriptionSection.tsx create mode 100644 client/src/pages/MainPage/Section/MainSection.tsx create mode 100644 client/src/pages/MainPage/Section/MemberReportSection.tsx diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts index dcfa04ee0..5b4a93884 100644 --- a/client/cypress/e2e/createEvent.cy.ts +++ b/client/cypress/e2e/createEvent.cy.ts @@ -6,7 +6,7 @@ beforeEach(() => { describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 flow', () => { it('랜딩페이지에서 "행사 생성하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { cy.visit('/'); - cy.get('button').should('have.text', '행사 생성하기').click(); + cy.get('header').find('button').click(); cy.url().should('include', '/event/create/name'); }); diff --git a/client/src/assets/image/addBillMockup.svg b/client/src/assets/image/addBillMockup.svg new file mode 100644 index 000000000..c7e4aa109 --- /dev/null +++ b/client/src/assets/image/addBillMockup.svg @@ -0,0 +1,312 @@ +<svg width="100%" height="100%" viewBox="0 0 430 867" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<path d="M358.532 867H71.3893C33.968 867 3.6333 836.665 3.6333 799.244V348.944V282.739V265.653V199.447V170.878V136.894V67.6347C3.6333 30.2134 33.968 -0.12131 71.3893 -0.12131H358.532C395.954 -0.12131 426.288 30.2134 426.288 67.6347V799.244C426.288 836.665 395.954 867 358.532 867ZM71.9202 1.8971C35.3203 1.8971 5.65171 31.5657 5.65171 68.1655V798.713C5.65171 835.312 35.3203 864.982 71.9202 864.982H358.001C394.601 864.982 424.27 835.312 424.27 798.713V68.1655C424.27 31.5657 394.601 1.8971 358.001 1.8971H71.9202ZM357.471 862.963H72.451C36.6727 862.963 7.67012 833.96 7.67012 798.182V68.6964C7.67012 32.9181 36.6727 3.91551 72.451 3.91551H357.471C393.247 3.91551 422.251 32.9181 422.251 68.6964V798.182C422.251 833.96 393.247 862.963 357.471 862.963ZM73.0908 6.49706C38.683 6.49706 10.7906 34.3895 10.7906 68.7973V798.081C10.7906 832.489 38.683 860.381 73.0908 860.381H356.831C391.239 860.381 419.131 832.489 419.131 798.081V68.7973C419.131 34.3895 391.239 6.49706 356.831 6.49706H73.0908Z" fill="#5E465D"/> +<path d="M358.001 864.981H71.9193C35.3195 864.981 5.65088 835.312 5.65088 798.713V68.1653C5.65088 31.5655 35.3195 1.89689 71.9193 1.89689H358.001C394.6 1.89689 424.269 31.5655 424.269 68.1653V798.713C424.269 835.312 394.6 864.981 358.001 864.981ZM72.4502 3.9153C36.6718 3.9153 7.66929 32.9179 7.66929 68.6962V798.181C7.66929 833.96 36.6718 862.963 72.4502 862.963H357.47C393.246 862.963 422.251 833.96 422.251 798.181V68.6962C422.251 32.9179 393.246 3.9153 357.47 3.9153H72.4502Z" fill="#A597A4"/> +<path d="M356.831 860.381H73.0908C38.6829 860.381 10.7905 832.489 10.7905 798.08V68.7972C10.7905 34.3893 38.6829 6.49689 73.0908 6.49689H356.831C391.239 6.49689 419.131 34.3893 419.131 68.7972V798.08C419.131 832.489 391.239 860.381 356.831 860.381ZM72.7739 20.3169C45.9593 20.3169 24.223 42.0552 24.223 68.8698V798.008C24.223 824.823 45.9593 846.561 72.7759 846.561H357.146C383.962 846.561 405.698 824.823 405.698 798.008V68.8698C405.698 42.0552 383.962 20.3169 357.146 20.3169H324.147H105.383C94.1145 20.3169 83.421 20.3169 72.7739 20.3169Z" fill="#1D1D1B"/> +<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> +<mask id="mask0_1835_8259" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> +<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> +</mask> +<g mask="url(#mask0_1835_8259)"> +<g clip-path="url(#clip0_1835_8259)"> +<mask id="mask1_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> +<path d="M406 20H24V847H406V20Z" fill="white"/> +</mask> +<g mask="url(#mask1_1835_8259)"> +<path d="M406 20H24V847H406V20Z" fill="#F1F0F5"/> +<path d="M51.8437 93.2812H41.9297V89.1094H51.8437V93.2812ZM43.8906 91.7892H49.8906V90.5937H43.8906V91.7892ZM52.7109 81.7267H41.0391V80.2345H52.7109V81.7267ZM46.9062 82.1017C48.4583 82.1017 49.6406 82.2734 50.4531 82.6172C51.2708 82.9557 51.6797 83.4583 51.6797 84.125C51.6797 84.7917 51.2708 85.297 50.4531 85.6407C49.6406 85.9845 48.4583 86.1562 46.9062 86.1562C45.3594 86.1562 44.1745 85.9845 43.3516 85.6407C42.5286 85.297 42.1172 84.7917 42.1172 84.125C42.1172 83.4583 42.5286 82.9557 43.3516 82.6172C44.1745 82.2734 45.3594 82.1017 46.9062 82.1017ZM46.9062 83.4375C46.2708 83.4375 45.7656 83.461 45.3906 83.5079C45.0156 83.5548 44.7318 83.6277 44.5391 83.7267C44.3464 83.8256 44.25 83.9583 44.25 84.125C44.25 84.2865 44.3464 84.4168 44.5391 84.5157C44.7318 84.6147 45.0208 84.6902 45.4062 84.7423C45.7917 84.7944 46.2917 84.8203 46.9062 84.8203C47.5312 84.8203 48.0339 84.7944 48.4141 84.7423C48.7995 84.6902 49.0859 84.6147 49.2734 84.5157C49.4609 84.4168 49.5547 84.2865 49.5547 84.125C49.5547 83.9583 49.4609 83.8256 49.2734 83.7267C49.0859 83.6277 48.8047 83.5548 48.4297 83.5079C48.0547 83.461 47.5469 83.4375 46.9062 83.4375ZM47.8984 81.3047H45.8984V79.0938H47.8984V81.3047ZM53.3984 88.3907H40.4297V86.8359H53.3984V88.3907ZM47.8984 87.6798H45.8984V85.6484H47.8984V87.6798Z" fill="#B2B1B6"/> +<path d="M73.2187 81.875H67.0781V80.25H73.2187V81.875ZM70.8594 87.1094H68.875V83.5312H70.8594V87.1094ZM74.3984 81.2344C74.3932 81.9687 74.3724 82.6458 74.3359 83.2656C74.2995 83.8854 74.2135 84.5651 74.0781 85.3047L72.1094 85.1328C72.25 84.388 72.3385 83.737 72.375 83.1797C72.4167 82.6224 72.4427 81.9818 72.4531 81.2578V81.1328V80.25H74.3984V81.1328V81.2344ZM77.875 89.8516H75.8281V79.2031H77.875V89.8516ZM79.6016 85.2187H77.0703V83.5547H79.6016V85.2187ZM78.3203 93.1953H68.3281V91.5859H78.3203V93.1953ZM70.3281 92.0937H68.3281V88.9062H70.3281V92.0937ZM66.2344 86.3437C67.9375 86.3437 69.513 86.3151 70.9609 86.2578C72.4141 86.2005 73.7839 86.0781 75.0703 85.8906L75.1641 87.3281C73.8464 87.5729 72.4635 87.7344 71.0156 87.8125C69.5677 87.8906 68.0312 87.9297 66.4062 87.9297L66.2344 86.3437ZM92.1719 93.4766H90.1797V79.2031H92.1719V93.4766ZM82.2891 88.5C83.6276 88.5104 84.8281 88.4818 85.8906 88.4141C86.9583 88.3411 88.0495 88.2135 89.1641 88.0312L89.3437 89.6406C88.2448 89.8333 87.1484 89.9661 86.0547 90.0391C84.9661 90.1068 83.7109 90.1406 82.2891 90.1406H81.0156V88.5H82.2891ZM87.7578 85.8828H83.0703V89.125H81.0156V84.3203H85.7266V82.0156H81V80.4062H87.7578V85.8828Z" fill="#56555A"/> +<path d="M406 114H24V270H406V114Z" fill="white"/> +<path d="M60.9609 151.188H58.1133V137.805H60.9609V151.188ZM58.875 145.551H55.3828V143.113H58.875V145.551ZM56.4141 150.496H53.625V138.215H56.4141V150.496ZM52.9922 142.34H42.5273V140.008H52.9922V142.34ZM47.7891 143.066C48.6875 143.066 49.4883 143.219 50.1914 143.523C50.9023 143.828 51.457 144.266 51.8555 144.836C52.2539 145.398 52.4531 146.051 52.4531 146.793C52.4531 147.512 52.2539 148.152 51.8555 148.715C51.457 149.27 50.9023 149.703 50.1914 150.016C49.4883 150.32 48.6875 150.473 47.7891 150.473C46.9062 150.473 46.1133 150.32 45.4102 150.016C44.7148 149.703 44.168 149.27 43.7695 148.715C43.3711 148.152 43.1719 147.512 43.1719 146.793C43.1719 146.051 43.3711 145.398 43.7695 144.836C44.168 144.266 44.7148 143.828 45.4102 143.523C46.1133 143.219 46.9062 143.066 47.7891 143.066ZM47.7891 145.211C47.4062 145.203 47.0664 145.262 46.7695 145.387C46.4805 145.512 46.2539 145.695 46.0898 145.938C45.9258 146.18 45.8438 146.465 45.8438 146.793C45.8438 147.113 45.9219 147.391 46.0781 147.625C46.2422 147.859 46.4688 148.043 46.7578 148.176C47.0547 148.301 47.3984 148.363 47.7891 148.363C48.1797 148.363 48.5234 148.301 48.8203 148.176C49.1172 148.043 49.3477 147.859 49.5117 147.625C49.6758 147.391 49.7578 147.113 49.7578 146.793C49.7578 146.465 49.6758 146.18 49.5117 145.938C49.3477 145.695 49.1172 145.512 48.8203 145.387C48.5234 145.262 48.1797 145.203 47.7891 145.211ZM49.2656 141.625H46.2773V138.016H49.2656V141.625ZM53.6719 151.41C55.2031 151.41 56.5234 151.562 57.6328 151.867C58.7422 152.164 59.5898 152.605 60.1758 153.191C60.7695 153.777 61.0664 154.477 61.0664 155.289C61.0664 156.109 60.7695 156.805 60.1758 157.375C59.5898 157.953 58.7422 158.395 57.6328 158.699C56.5234 159.004 55.2031 159.156 53.6719 159.156C52.1484 159.156 50.832 159.004 49.7227 158.699C48.6211 158.395 47.7734 157.953 47.1797 157.375C46.5859 156.805 46.2891 156.109 46.2891 155.289C46.2891 154.477 46.5859 153.777 47.1797 153.191C47.7734 152.605 48.6211 152.164 49.7227 151.867C50.832 151.562 52.1484 151.41 53.6719 151.41ZM53.6719 153.648C52.6953 153.641 51.8828 153.695 51.2344 153.812C50.5938 153.93 50.1055 154.113 49.7695 154.363C49.4414 154.613 49.2812 154.922 49.2891 155.289C49.2812 155.641 49.4414 155.938 49.7695 156.18C50.1055 156.414 50.5977 156.594 51.2461 156.719C51.8945 156.844 52.7031 156.906 53.6719 156.906C54.6406 156.906 55.4492 156.844 56.0977 156.719C56.7539 156.594 57.2422 156.414 57.5625 156.18C57.8906 155.945 58.0586 155.648 58.0664 155.289C58.0586 154.914 57.8906 154.605 57.5625 154.363C57.2422 154.113 56.7578 153.93 56.1094 153.812C55.4609 153.695 54.6484 153.641 53.6719 153.648ZM82.875 150.262H63.3867V147.895H82.875V150.262ZM74.5898 148.832H71.6602V144.684H74.5898V148.832ZM80.6484 146.066H65.7422V143.723H80.6484V146.066ZM80.5312 141.098H68.707V145.258H65.7422V138.766H80.5312V141.098ZM73.0781 151.316C74.6172 151.316 75.9414 151.473 77.0508 151.785C78.1602 152.09 79.0117 152.539 79.6055 153.133C80.1992 153.719 80.5 154.43 80.5078 155.266C80.5 156.094 80.1992 156.797 79.6055 157.375C79.0195 157.961 78.168 158.406 77.0508 158.711C75.9414 159.023 74.6172 159.184 73.0781 159.191C71.5234 159.184 70.1875 159.023 69.0703 158.711C67.9531 158.406 67.0938 157.961 66.4922 157.375C65.8984 156.789 65.6016 156.086 65.6016 155.266C65.6016 154.43 65.8984 153.719 66.4922 153.133C67.0938 152.539 67.9531 152.09 69.0703 151.785C70.1875 151.473 71.5234 151.316 73.0781 151.316ZM73.0781 153.602C72.0859 153.602 71.2617 153.664 70.6055 153.789C69.957 153.906 69.4648 154.09 69.1289 154.34C68.8008 154.59 68.6406 154.898 68.6484 155.266C68.6406 155.641 68.8008 155.949 69.1289 156.191C69.4648 156.434 69.957 156.613 70.6055 156.73C71.2617 156.848 72.0859 156.906 73.0781 156.906C74.0547 156.906 74.8672 156.848 75.5156 156.73C76.1719 156.613 76.6641 156.434 76.9922 156.191C77.3281 155.949 77.4961 155.641 77.4961 155.266C77.4961 154.906 77.3281 154.602 76.9922 154.352C76.6641 154.094 76.1719 153.906 75.5156 153.789C74.8594 153.664 74.0469 153.602 73.0781 153.602ZM102.551 159.156H99.7383V137.805H102.551V159.156ZM100.418 148.457H96.7969V146.066H100.418V148.457ZM97.6758 158.125H94.9336V138.191H97.6758V158.125ZM86.2148 151.832C87.7773 151.832 89.1172 151.797 90.2344 151.727C91.3516 151.656 92.5 151.516 93.6797 151.305L93.8906 153.73C92.7031 153.965 91.5352 154.121 90.3867 154.199C89.2461 154.27 87.8555 154.312 86.2148 154.328H84.7148V151.832H86.2148ZM92.6836 142.703H87.7148V153.039H84.7148V140.301H92.6836V142.703ZM112.16 141.59C112.152 142.98 111.926 144.277 111.481 145.48C111.035 146.676 110.352 147.719 109.43 148.609C108.516 149.5 107.391 150.16 106.055 150.59L104.555 148.234C105.695 147.867 106.652 147.34 107.426 146.652C108.199 145.957 108.77 145.176 109.137 144.309C109.512 143.441 109.703 142.535 109.711 141.59V140.195H112.16V141.59ZM112.734 141.578C112.734 142.445 112.91 143.27 113.262 144.051C113.613 144.824 114.156 145.52 114.891 146.137C115.625 146.746 116.543 147.215 117.645 147.543L116.238 149.875C114.926 149.484 113.828 148.879 112.945 148.059C112.063 147.23 111.398 146.266 110.953 145.164C110.516 144.055 110.297 142.859 110.297 141.578V140.195H112.734V141.578ZM116.988 141.637H105.363V139.246H116.988V141.637ZM121.781 150.473H118.793V137.805H121.781V150.473ZM124.664 145.211H120.938V142.773H124.664V145.211ZM114.785 150.895C116.262 150.895 117.539 151.059 118.617 151.387C119.703 151.707 120.535 152.176 121.113 152.793C121.691 153.41 121.981 154.148 121.981 155.008C121.981 155.867 121.691 156.605 121.113 157.223C120.535 157.848 119.703 158.324 118.617 158.652C117.539 158.988 116.262 159.156 114.785 159.156C113.293 159.156 111.996 158.988 110.895 158.652C109.793 158.324 108.945 157.848 108.352 157.223C107.766 156.605 107.473 155.867 107.473 155.008C107.473 154.148 107.766 153.41 108.352 152.793C108.945 152.176 109.789 151.707 110.883 151.387C111.984 151.059 113.285 150.895 114.785 150.895ZM114.785 153.215C113.856 153.215 113.066 153.281 112.418 153.414C111.777 153.547 111.293 153.75 110.965 154.023C110.637 154.289 110.477 154.617 110.484 155.008C110.477 155.414 110.637 155.754 110.965 156.027C111.293 156.293 111.777 156.496 112.418 156.637C113.059 156.77 113.848 156.836 114.785 156.836C115.715 156.836 116.492 156.77 117.117 156.637C117.75 156.496 118.227 156.293 118.547 156.027C118.875 155.754 119.039 155.414 119.039 155.008C119.039 154.609 118.875 154.277 118.547 154.012C118.227 153.746 117.75 153.547 117.117 153.414C116.492 153.281 115.715 153.215 114.785 153.215ZM136.91 139.316C137.988 139.316 138.949 139.629 139.793 140.254C140.645 140.871 141.312 141.758 141.797 142.914C142.281 144.062 142.527 145.398 142.535 146.922C142.527 148.453 142.281 149.797 141.797 150.953C141.312 152.102 140.645 152.984 139.793 153.602C138.949 154.219 137.988 154.527 136.91 154.527C135.816 154.527 134.844 154.219 133.992 153.602C133.141 152.984 132.473 152.102 131.988 150.953C131.512 149.797 131.273 148.453 131.273 146.922C131.273 145.398 131.512 144.062 131.988 142.914C132.473 141.758 133.141 140.871 133.992 140.254C134.844 139.629 135.816 139.316 136.91 139.316ZM136.91 142.023C136.363 142.016 135.883 142.203 135.469 142.586C135.055 142.969 134.73 143.527 134.496 144.262C134.27 144.996 134.156 145.883 134.156 146.922C134.156 147.961 134.27 148.848 134.496 149.582C134.73 150.316 135.055 150.875 135.469 151.258C135.883 151.633 136.363 151.82 136.91 151.82C137.465 151.82 137.949 151.633 138.363 151.258C138.777 150.875 139.094 150.316 139.312 149.582C139.539 148.848 139.652 147.961 139.652 146.922C139.652 145.883 139.539 144.996 139.312 144.262C139.094 143.52 138.777 142.961 138.363 142.586C137.949 142.203 137.465 142.016 136.91 142.023ZM150.996 145.281H147.176V142.785H150.996V145.281ZM150.996 151.504H147.176V149.078H150.996V151.504ZM147.984 159.156H144.984V137.805H147.984V159.156ZM159.41 159.156H156.34V151.27H159.41V159.156ZM166.816 159.156H163.781V151.27H166.816V159.156ZM171.387 152.102H151.887V149.688H171.387V152.102ZM161.578 138.531C163.094 138.531 164.441 138.73 165.621 139.129C166.801 139.527 167.715 140.09 168.363 140.816C169.02 141.543 169.348 142.387 169.348 143.348C169.348 144.293 169.02 145.121 168.363 145.832C167.715 146.535 166.801 147.082 165.621 147.473C164.441 147.863 163.094 148.059 161.578 148.059C160.062 148.059 158.719 147.863 157.547 147.473C156.375 147.082 155.461 146.535 154.805 145.832C154.156 145.121 153.832 144.293 153.832 143.348C153.832 142.387 154.156 141.543 154.805 140.816C155.461 140.09 156.375 139.527 157.547 139.129C158.719 138.73 160.062 138.531 161.578 138.531ZM161.578 140.922C160.617 140.93 159.785 141.027 159.082 141.215C158.387 141.395 157.852 141.668 157.477 142.035C157.102 142.395 156.918 142.832 156.926 143.348C156.918 143.84 157.102 144.262 157.477 144.613C157.852 144.965 158.387 145.234 159.082 145.422C159.785 145.602 160.617 145.691 161.578 145.691C162.539 145.691 163.371 145.602 164.074 145.422C164.777 145.234 165.316 144.969 165.691 144.625C166.074 144.273 166.266 143.848 166.266 143.348C166.266 142.832 166.074 142.395 165.691 142.035C165.316 141.668 164.777 141.395 164.074 141.215C163.379 141.027 162.547 140.93 161.578 140.922ZM181.137 154.258H178.16V150.777H181.137V154.258ZM190.559 159.156H187.594V137.805H190.559V159.156ZM173.578 153.133C176.234 153.117 178.57 153.074 180.586 153.004C182.609 152.926 184.555 152.762 186.422 152.512L186.609 154.727C184.547 155.086 182.426 155.32 180.246 155.43C178.066 155.531 175.695 155.582 173.133 155.582L172.734 153.133H173.578ZM186.117 142.551H173.156V140.207H186.117V142.551ZM179.625 143.395C180.672 143.395 181.602 143.562 182.414 143.898C183.234 144.227 183.867 144.695 184.312 145.305C184.766 145.914 184.992 146.613 184.992 147.402C184.992 148.184 184.766 148.879 184.312 149.488C183.867 150.09 183.234 150.559 182.414 150.895C181.602 151.23 180.672 151.398 179.625 151.398C178.594 151.398 177.676 151.23 176.871 150.895C176.066 150.559 175.438 150.09 174.984 149.488C174.539 148.879 174.316 148.184 174.316 147.402C174.316 146.613 174.539 145.914 174.984 145.305C175.438 144.695 176.066 144.227 176.871 143.898C177.676 143.562 178.594 143.395 179.625 143.395ZM179.625 145.656C179.141 145.656 178.711 145.727 178.336 145.867C177.969 146 177.68 146.199 177.469 146.465C177.258 146.73 177.152 147.043 177.152 147.402C177.152 147.77 177.254 148.082 177.457 148.34C177.668 148.59 177.961 148.785 178.336 148.926C178.711 149.059 179.141 149.125 179.625 149.125C180.125 149.125 180.566 149.059 180.949 148.926C181.332 148.785 181.625 148.59 181.828 148.34C182.031 148.082 182.133 147.77 182.133 147.402C182.133 147.043 182.031 146.73 181.828 146.465C181.625 146.199 181.332 146 180.949 145.867C180.566 145.727 180.125 145.656 179.625 145.656ZM181.16 141.543H178.16V137.91H181.16V141.543Z" fill="#56555A"/> +<path d="M47.3125 183.641C47.3125 184.599 47.1302 185.544 46.7656 186.477C46.401 187.409 45.9115 188.237 45.2969 188.961C44.6875 189.685 44.0208 190.229 43.2969 190.594L42.5625 189.625C43.224 189.307 43.8385 188.828 44.4062 188.188C44.9792 187.542 45.4375 186.818 45.7812 186.016C46.125 185.214 46.2969 184.422 46.2969 183.641V181.344H47.3125V183.641ZM47.5312 183.641C47.5312 184.406 47.7031 185.169 48.0469 185.93C48.3906 186.685 48.849 187.359 49.4219 187.953C49.9948 188.547 50.6198 188.99 51.2969 189.281L50.6094 190.25C49.8542 189.906 49.1667 189.396 48.5469 188.719C47.9323 188.042 47.4427 187.263 47.0781 186.383C46.7188 185.497 46.5417 184.583 46.5469 183.641V181.344H47.5312V183.641ZM50.8438 181.828H43.0156V180.812H50.8438V181.828ZM54.0156 193.266H52.7812V179.375H54.0156V193.266ZM63.3125 188.391H62.1094V186.281H63.3125V188.391ZM69.0469 186.516H56.4062V185.562H69.0469V186.516ZM63.3125 180.984H62.1094V179.297H63.3125V180.984ZM63.125 181.312C63.125 182.016 62.8698 182.625 62.3594 183.141C61.849 183.651 61.1641 184.055 60.3047 184.352C59.4505 184.643 58.4948 184.833 57.4375 184.922L57.0781 183.984C57.9948 183.927 58.8307 183.784 59.5859 183.555C60.3411 183.32 60.9401 183.013 61.3828 182.633C61.8255 182.247 62.0469 181.807 62.0469 181.312V181.109H63.125V181.312ZM63.3906 181.312C63.3854 181.807 63.6042 182.247 64.0469 182.633C64.4948 183.013 65.0938 183.32 65.8438 183.555C66.599 183.784 67.4375 183.927 68.3594 183.984L67.9844 184.922C66.9323 184.833 65.9792 184.643 65.125 184.352C64.2708 184.055 63.5885 183.651 63.0781 183.141C62.5677 182.625 62.3125 182.016 62.3125 181.312V181.109H63.3906V181.312ZM67.7656 181.562H57.7031V180.594H67.7656V181.562ZM67.4219 190.812H59.1719V192.516H57.9531V189.938H66.2188V188.734H57.9219V187.812H67.4219V190.812ZM67.8438 193.109H57.9531V192.172H67.8438V193.109ZM86.0938 193.266H84.8906V179.375H86.0938V193.266ZM85.25 186.078H82.5312V185.031H85.25V186.078ZM82.8906 192.547H81.7344V179.688H82.8906V192.547ZM76.1562 189.078H74.9375V181.078H76.1562V189.078ZM75.7969 188.578C76.625 188.583 77.4349 188.555 78.2266 188.492C79.0234 188.424 79.849 188.302 80.7031 188.125L80.8594 189.219C79.9427 189.385 79.0755 189.503 78.2578 189.57C77.4453 189.638 76.625 189.672 75.7969 189.672H74.9375V188.578H75.7969ZM98.7188 182.438H94.4688V181.422H98.7188V182.438ZM98.7188 185.562H94.4688V184.547H98.7188V185.562ZM99.5781 193.266H98.3438V189.312H90.2344V188.328H99.5781V193.266ZM99.5781 187.562H98.3438V179.375H99.5781V187.562ZM91.8906 180.172C92.5677 180.172 93.1797 180.312 93.7266 180.594C94.2734 180.875 94.7005 181.268 95.0078 181.773C95.3203 182.279 95.4792 182.849 95.4844 183.484C95.4792 184.135 95.3203 184.714 95.0078 185.219C94.7005 185.719 94.2734 186.112 93.7266 186.398C93.1797 186.68 92.5677 186.818 91.8906 186.812C91.2031 186.818 90.5859 186.68 90.0391 186.398C89.4922 186.112 89.0625 185.716 88.75 185.211C88.4375 184.706 88.2812 184.13 88.2812 183.484C88.2812 182.849 88.4375 182.279 88.75 181.773C89.0625 181.268 89.4922 180.875 90.0391 180.594C90.5859 180.312 91.2031 180.172 91.8906 180.172ZM91.8906 181.219C91.4219 181.219 91.0026 181.315 90.6328 181.508C90.263 181.701 89.974 181.971 89.7656 182.32C89.5573 182.664 89.4531 183.052 89.4531 183.484C89.4531 183.927 89.5573 184.323 89.7656 184.672C89.974 185.016 90.263 185.286 90.6328 185.484C91.0026 185.682 91.4219 185.781 91.8906 185.781C92.3438 185.781 92.7526 185.682 93.1172 185.484C93.487 185.286 93.776 185.016 93.9844 184.672C94.1927 184.323 94.2969 183.927 94.2969 183.484C94.2969 183.057 94.1927 182.669 93.9844 182.32C93.776 181.971 93.487 181.701 93.1172 181.508C92.7474 181.315 92.3385 181.219 91.8906 181.219ZM113.156 185.938H106.641V180.281H113.156V185.938ZM107.844 184.969H111.953V181.281H107.844V184.969ZM117.359 187.359H116.156V179.375H117.359V187.359ZM113.391 189.266C113.391 189.911 113.146 190.513 112.656 191.07C112.167 191.628 111.516 192.091 110.703 192.461C109.891 192.836 109.016 193.089 108.078 193.219L107.641 192.266C108.432 192.177 109.19 191.982 109.914 191.68C110.638 191.372 111.221 191.005 111.664 190.578C112.107 190.151 112.328 189.714 112.328 189.266V188.984H113.391V189.266ZM113.594 189.266C113.594 189.703 113.81 190.135 114.242 190.562C114.675 190.99 115.245 191.357 115.953 191.664C116.667 191.966 117.417 192.167 118.203 192.266L117.781 193.219C116.849 193.089 115.979 192.831 115.172 192.445C114.37 192.065 113.727 191.596 113.242 191.039C112.763 190.482 112.526 189.891 112.531 189.266V188.984H113.594V189.266ZM117.719 189.266H108.219V188.312H117.719V189.266ZM113.562 188.75H112.344V186.953H113.562V188.75ZM135.219 189.547H134V179.391H135.219V189.547ZM135.656 192.969H126.25V191.938H135.656V192.969ZM127.469 192.281H126.25V188.516H127.469V192.281ZM127.719 180.359C128.406 180.359 129.026 180.505 129.578 180.797C130.13 181.089 130.565 181.492 130.883 182.008C131.201 182.523 131.359 183.109 131.359 183.766C131.359 184.427 131.201 185.018 130.883 185.539C130.565 186.055 130.13 186.458 129.578 186.75C129.026 187.042 128.406 187.188 127.719 187.188C127.031 187.188 126.411 187.042 125.859 186.75C125.307 186.458 124.872 186.055 124.555 185.539C124.237 185.018 124.078 184.427 124.078 183.766C124.078 183.109 124.237 182.523 124.555 182.008C124.872 181.492 125.307 181.089 125.859 180.797C126.411 180.505 127.031 180.359 127.719 180.359ZM127.719 181.438C127.255 181.438 126.836 181.536 126.461 181.734C126.091 181.932 125.799 182.208 125.586 182.562C125.378 182.917 125.276 183.318 125.281 183.766C125.276 184.219 125.378 184.625 125.586 184.984C125.799 185.339 126.091 185.615 126.461 185.812C126.836 186.01 127.255 186.109 127.719 186.109C128.177 186.109 128.591 186.01 128.961 185.812C129.331 185.615 129.622 185.339 129.836 184.984C130.049 184.625 130.156 184.219 130.156 183.766C130.156 183.318 130.049 182.917 129.836 182.562C129.622 182.208 129.331 181.932 128.961 181.734C128.591 181.536 128.177 181.438 127.719 181.438ZM142.812 189.453H141.578V186.359H142.812V189.453ZM149.031 189.938H147.797V179.391H149.031V189.938ZM149.375 192.969H139.5V191.938H149.375V192.969ZM140.734 192.234H139.5V188.906H140.734V192.234ZM137.5 185.828C139.359 185.818 141.005 185.789 142.438 185.742C143.87 185.69 145.24 185.583 146.547 185.422L146.625 186.312C145.276 186.526 143.862 186.667 142.383 186.734C140.904 186.802 139.333 186.833 137.672 186.828L137.5 185.828ZM148.125 188.5H144.922V187.609H148.125V188.5ZM142.062 179.953C142.734 179.953 143.331 180.052 143.852 180.25C144.378 180.448 144.784 180.732 145.07 181.102C145.357 181.471 145.5 181.896 145.5 182.375C145.5 182.865 145.357 183.289 145.07 183.648C144.784 184.008 144.38 184.286 143.859 184.484C143.339 184.682 142.74 184.781 142.062 184.781C141.38 184.781 140.779 184.682 140.258 184.484C139.742 184.286 139.341 184.008 139.055 183.648C138.768 183.289 138.625 182.865 138.625 182.375C138.625 181.896 138.768 181.471 139.055 181.102C139.341 180.732 139.745 180.448 140.266 180.25C140.786 180.052 141.385 179.953 142.062 179.953ZM142.062 180.891C141.615 180.885 141.219 180.945 140.875 181.07C140.531 181.19 140.263 181.365 140.07 181.594C139.883 181.823 139.792 182.083 139.797 182.375C139.792 182.672 139.883 182.935 140.07 183.164C140.263 183.388 140.531 183.562 140.875 183.688C141.219 183.812 141.615 183.875 142.062 183.875C142.5 183.875 142.891 183.812 143.234 183.688C143.578 183.562 143.846 183.388 144.039 183.164C144.232 182.935 144.328 182.672 144.328 182.375C144.328 182.083 144.232 181.823 144.039 181.594C143.846 181.365 143.578 181.19 143.234 181.07C142.891 180.945 142.5 180.885 142.062 180.891ZM166.156 182.969H162.109V181.938H166.156V182.969ZM166.203 185.938H162.109V184.922H166.203V185.938ZM166.938 189.672H165.703V179.391H166.938V189.672ZM167.25 192.969H157.953V191.938H167.25V192.969ZM159.188 192.438H157.953V188.656H159.188V192.438ZM157.344 182.781H161.219V180.312H162.422V187.297H156.125V180.312H157.344V182.781ZM161.219 186.281V183.75H157.344V186.281H161.219ZM181.922 187.234H169.25V186.25H181.922V187.234ZM176.172 186.672H174.984V184.016H176.172V186.672ZM180.438 184.625H170.859V183.625H180.438V184.625ZM180.344 181.016H172.062V184.234H170.859V180.031H180.344V181.016ZM175.578 188.25C176.568 188.25 177.419 188.349 178.133 188.547C178.846 188.745 179.393 189.031 179.773 189.406C180.159 189.776 180.354 190.224 180.359 190.75C180.354 191.281 180.161 191.732 179.781 192.102C179.406 192.471 178.859 192.755 178.141 192.953C177.422 193.156 176.568 193.26 175.578 193.266C174.578 193.26 173.719 193.156 173 192.953C172.281 192.755 171.732 192.469 171.352 192.094C170.971 191.724 170.781 191.276 170.781 190.75C170.781 190.224 170.971 189.776 171.352 189.406C171.732 189.031 172.281 188.745 173 188.547C173.719 188.349 174.578 188.25 175.578 188.25ZM175.578 189.219C174.839 189.219 174.203 189.279 173.672 189.398C173.141 189.518 172.732 189.695 172.445 189.93C172.164 190.159 172.026 190.432 172.031 190.75C172.026 191.073 172.164 191.349 172.445 191.578C172.732 191.807 173.141 191.982 173.672 192.102C174.203 192.221 174.839 192.281 175.578 192.281C176.307 192.281 176.938 192.221 177.469 192.102C178 191.982 178.409 191.807 178.695 191.578C178.982 191.349 179.125 191.073 179.125 190.75C179.125 190.432 178.982 190.159 178.695 189.93C178.409 189.695 178 189.518 177.469 189.398C176.938 189.279 176.307 189.219 175.578 189.219ZM189.406 179.625C190.432 179.625 191.312 179.716 192.047 179.898C192.786 180.081 193.349 180.352 193.734 180.711C194.12 181.07 194.312 181.505 194.312 182.016C194.312 182.536 194.12 182.979 193.734 183.344C193.349 183.708 192.789 183.984 192.055 184.172C191.32 184.354 190.438 184.448 189.406 184.453C188.37 184.448 187.484 184.354 186.75 184.172C186.021 183.984 185.461 183.708 185.07 183.344C184.68 182.979 184.484 182.536 184.484 182.016C184.484 181.505 184.68 181.07 185.07 180.711C185.461 180.352 186.023 180.081 186.758 179.898C187.492 179.716 188.375 179.625 189.406 179.625ZM189.406 180.547C188.641 180.547 187.984 180.607 187.438 180.727C186.896 180.846 186.479 181.016 186.188 181.234C185.901 181.453 185.76 181.714 185.766 182.016C185.76 182.333 185.901 182.607 186.188 182.836C186.479 183.06 186.896 183.229 187.438 183.344C187.984 183.458 188.641 183.516 189.406 183.516C190.172 183.516 190.828 183.458 191.375 183.344C191.927 183.229 192.346 183.06 192.633 182.836C192.919 182.612 193.062 182.339 193.062 182.016C193.062 181.714 192.919 181.453 192.633 181.234C192.346 181.016 191.927 180.846 191.375 180.727C190.823 180.607 190.167 180.547 189.406 180.547ZM195.734 186.391H183.078V185.391H195.734V186.391ZM194.109 190.703H185.859V192.391H184.641V189.797H192.906V188.531H184.609V187.594H194.109V190.703ZM194.531 193.109H184.641V192.141H194.531V193.109ZM207.844 193.297H206.641V188.188H207.844V193.297ZM213.578 188.812H200.922V187.781H213.578V188.812ZM207.719 182.125C207.719 182.896 207.461 183.602 206.945 184.242C206.43 184.883 205.747 185.417 204.898 185.844C204.055 186.266 203.146 186.552 202.172 186.703L201.719 185.719C202.552 185.604 203.346 185.37 204.102 185.016C204.857 184.661 205.469 184.232 205.938 183.727C206.406 183.221 206.641 182.688 206.641 182.125V181.75H207.719V182.125ZM207.859 182.125C207.859 182.682 208.091 183.216 208.555 183.727C209.018 184.232 209.628 184.661 210.383 185.016C211.138 185.37 211.932 185.604 212.766 185.719L212.312 186.703C211.339 186.557 210.43 186.268 209.586 185.836C208.747 185.404 208.073 184.867 207.562 184.227C207.052 183.581 206.797 182.88 206.797 182.125V181.75H207.859V182.125ZM212.359 182.109H202.156V181.109H212.359V182.109ZM207.844 181.453H206.641V179.375H207.844V181.453ZM225.5 193.266H224.281V179.375H225.5V193.266ZM227.75 186.062H225.188V185.031H227.75V186.062ZM221.906 180.875C221.901 182.224 221.677 183.5 221.234 184.703C220.797 185.901 220.104 187.008 219.156 188.023C218.208 189.034 217 189.901 215.531 190.625L214.844 189.656C216.13 189.016 217.208 188.263 218.078 187.398C218.953 186.529 219.607 185.565 220.039 184.508C220.477 183.451 220.698 182.307 220.703 181.078V180.875H221.906ZM221.328 181.906H215.484V180.875H221.328V181.906ZM235.516 182.781H228.547V181.781H235.516V182.781ZM232.031 183.719C232.609 183.719 233.125 183.854 233.578 184.125C234.036 184.396 234.393 184.771 234.648 185.25C234.909 185.724 235.042 186.266 235.047 186.875C235.042 187.49 234.909 188.036 234.648 188.516C234.393 188.995 234.036 189.372 233.578 189.648C233.125 189.924 232.609 190.062 232.031 190.062C231.464 190.062 230.951 189.924 230.492 189.648C230.039 189.372 229.685 188.995 229.43 188.516C229.174 188.036 229.047 187.49 229.047 186.875C229.047 186.271 229.177 185.729 229.438 185.25C229.698 184.771 230.052 184.396 230.5 184.125C230.953 183.854 231.464 183.719 232.031 183.719ZM232.031 184.75C231.667 184.755 231.341 184.852 231.055 185.039C230.768 185.221 230.544 185.474 230.383 185.797C230.221 186.115 230.141 186.474 230.141 186.875C230.141 187.281 230.221 187.643 230.383 187.961C230.544 188.279 230.768 188.529 231.055 188.711C231.341 188.893 231.667 188.984 232.031 188.984C232.396 188.984 232.724 188.893 233.016 188.711C233.307 188.529 233.536 188.279 233.703 187.961C233.87 187.643 233.953 187.281 233.953 186.875C233.953 186.474 233.87 186.115 233.703 185.797C233.536 185.474 233.307 185.221 233.016 185.039C232.724 184.852 232.396 184.755 232.031 184.75ZM240.406 193.266H239.234V179.375H240.406V193.266ZM239.625 186.25H236.969V185.234H239.625V186.25ZM237.391 192.578H236.234V179.719H237.391V192.578ZM232.656 182.391H231.438V179.797H232.656V182.391ZM253.141 181.344C253.141 182.141 252.883 182.872 252.367 183.539C251.852 184.201 251.174 184.755 250.336 185.203C249.497 185.646 248.604 185.948 247.656 186.109L247.172 185.141C247.99 185.021 248.773 184.776 249.523 184.406C250.279 184.031 250.891 183.576 251.359 183.039C251.828 182.503 252.062 181.938 252.062 181.344V180.75H253.141V181.344ZM253.438 181.344C253.438 181.938 253.672 182.503 254.141 183.039C254.609 183.576 255.219 184.031 255.969 184.406C256.724 184.776 257.51 185.021 258.328 185.141L257.875 186.109C256.917 185.948 256.018 185.646 255.18 185.203C254.341 184.755 253.664 184.201 253.148 183.539C252.633 182.872 252.375 182.141 252.375 181.344V180.75H253.438V181.344ZM253.328 193.266H252.125V187.953H253.328V193.266ZM259.078 188.312H246.422V187.297H259.078V188.312ZM257.875 181.25H247.609V180.25H257.875V181.25ZM268.5 185.406H265.766V184.359H268.5V185.406ZM264.156 183.375C264.156 184.328 264.023 185.258 263.758 186.164C263.492 187.065 263.109 187.875 262.609 188.594C262.115 189.307 261.536 189.865 260.875 190.266L260.094 189.344C260.719 188.979 261.266 188.479 261.734 187.844C262.203 187.208 262.562 186.505 262.812 185.734C263.062 184.958 263.188 184.172 263.188 183.375V180.688H264.156V183.375ZM264.375 183.328C264.375 184.073 264.492 184.815 264.727 185.555C264.961 186.289 265.297 186.961 265.734 187.57C266.177 188.18 266.698 188.661 267.297 189.016L266.594 189.969C265.938 189.573 265.37 189.023 264.891 188.32C264.411 187.617 264.047 186.833 263.797 185.969C263.552 185.104 263.432 184.224 263.438 183.328V180.688H264.375V183.328ZM272.156 193.266H270.969V179.375H272.156V193.266ZM269.281 192.562H268.125V179.672H269.281V192.562ZM278.438 190.703H277.234V186.547H278.438V190.703ZM283.641 190.703H282.406V186.547H283.641V190.703ZM286.797 191.484H274.078V190.453H286.797V191.484ZM280.406 180.25C281.391 180.255 282.266 180.406 283.031 180.703C283.802 180.995 284.404 181.414 284.836 181.961C285.268 182.503 285.484 183.125 285.484 183.828C285.484 184.536 285.268 185.159 284.836 185.695C284.404 186.232 283.802 186.648 283.031 186.945C282.266 187.242 281.391 187.391 280.406 187.391C279.422 187.391 278.544 187.242 277.773 186.945C277.008 186.648 276.409 186.232 275.977 185.695C275.544 185.159 275.328 184.536 275.328 183.828C275.328 183.125 275.544 182.503 275.977 181.961C276.409 181.414 277.008 180.995 277.773 180.703C278.544 180.406 279.422 180.255 280.406 180.25ZM280.406 181.266C279.651 181.26 278.977 181.365 278.383 181.578C277.794 181.786 277.336 182.086 277.008 182.477C276.68 182.867 276.516 183.318 276.516 183.828C276.516 184.339 276.68 184.789 277.008 185.18C277.336 185.57 277.794 185.875 278.383 186.094C278.977 186.312 279.651 186.422 280.406 186.422C281.156 186.422 281.826 186.312 282.414 186.094C283.003 185.875 283.464 185.57 283.797 185.18C284.13 184.789 284.297 184.339 284.297 183.828C284.297 183.318 284.13 182.867 283.797 182.477C283.464 182.086 283.003 181.786 282.414 181.578C281.826 181.365 281.156 181.26 280.406 181.266ZM54.0312 213.547H52.8125V203.391H54.0312V213.547ZM54.4688 216.969H45.0625V215.938H54.4688V216.969ZM46.2812 216.281H45.0625V212.516H46.2812V216.281ZM46.5312 204.359C47.2188 204.359 47.8385 204.505 48.3906 204.797C48.9427 205.089 49.3776 205.492 49.6953 206.008C50.013 206.523 50.1719 207.109 50.1719 207.766C50.1719 208.427 50.013 209.018 49.6953 209.539C49.3776 210.055 48.9427 210.458 48.3906 210.75C47.8385 211.042 47.2188 211.188 46.5312 211.188C45.8438 211.188 45.224 211.042 44.6719 210.75C44.1198 210.458 43.6849 210.055 43.3672 209.539C43.0495 209.018 42.8906 208.427 42.8906 207.766C42.8906 207.109 43.0495 206.523 43.3672 206.008C43.6849 205.492 44.1198 205.089 44.6719 204.797C45.224 204.505 45.8438 204.359 46.5312 204.359ZM46.5312 205.438C46.0677 205.438 45.6484 205.536 45.2734 205.734C44.9036 205.932 44.612 206.208 44.3984 206.562C44.1901 206.917 44.0885 207.318 44.0938 207.766C44.0885 208.219 44.1901 208.625 44.3984 208.984C44.612 209.339 44.9036 209.615 45.2734 209.812C45.6484 210.01 46.0677 210.109 46.5312 210.109C46.9896 210.109 47.4036 210.01 47.7734 209.812C48.1432 209.615 48.4349 209.339 48.6484 208.984C48.862 208.625 48.9688 208.219 48.9688 207.766C48.9688 207.318 48.862 206.917 48.6484 206.562C48.4349 206.208 48.1432 205.932 47.7734 205.734C47.4036 205.536 46.9896 205.438 46.5312 205.438ZM61.625 213.453H60.3906V210.359H61.625V213.453ZM67.8438 213.938H66.6094V203.391H67.8438V213.938ZM68.1875 216.969H58.3125V215.938H68.1875V216.969ZM59.5469 216.234H58.3125V212.906H59.5469V216.234ZM56.3125 209.828C58.1719 209.818 59.8177 209.789 61.25 209.742C62.6823 209.69 64.0521 209.583 65.3594 209.422L65.4375 210.312C64.0885 210.526 62.6745 210.667 61.1953 210.734C59.7161 210.802 58.1458 210.833 56.4844 210.828L56.3125 209.828ZM66.9375 212.5H63.7344V211.609H66.9375V212.5ZM60.875 203.953C61.5469 203.953 62.1432 204.052 62.6641 204.25C63.1901 204.448 63.5964 204.732 63.8828 205.102C64.1693 205.471 64.3125 205.896 64.3125 206.375C64.3125 206.865 64.1693 207.289 63.8828 207.648C63.5964 208.008 63.1927 208.286 62.6719 208.484C62.151 208.682 61.5521 208.781 60.875 208.781C60.1927 208.781 59.5911 208.682 59.0703 208.484C58.5547 208.286 58.1536 208.008 57.8672 207.648C57.5807 207.289 57.4375 206.865 57.4375 206.375C57.4375 205.896 57.5807 205.471 57.8672 205.102C58.1536 204.732 58.5573 204.448 59.0781 204.25C59.599 204.052 60.1979 203.953 60.875 203.953ZM60.875 204.891C60.4271 204.885 60.0312 204.945 59.6875 205.07C59.3438 205.19 59.0755 205.365 58.8828 205.594C58.6953 205.823 58.6042 206.083 58.6094 206.375C58.6042 206.672 58.6953 206.935 58.8828 207.164C59.0755 207.388 59.3438 207.562 59.6875 207.688C60.0312 207.812 60.4271 207.875 60.875 207.875C61.3125 207.875 61.7031 207.812 62.0469 207.688C62.3906 207.562 62.6589 207.388 62.8516 207.164C63.0443 206.935 63.1406 206.672 63.1406 206.375C63.1406 206.083 63.0443 205.823 62.8516 205.594C62.6589 205.365 62.3906 205.19 62.0469 205.07C61.7031 204.945 61.3125 204.885 60.875 204.891ZM84.9688 206.969H80.9219V205.938H84.9688V206.969ZM85.0156 209.938H80.9219V208.922H85.0156V209.938ZM85.75 213.672H84.5156V203.391H85.75V213.672ZM86.0625 216.969H76.7656V215.938H86.0625V216.969ZM78 216.438H76.7656V212.656H78V216.438ZM76.1562 206.781H80.0312V204.312H81.2344V211.297H74.9375V204.312H76.1562V206.781ZM80.0312 210.281V207.75H76.1562V210.281H80.0312ZM100.734 211.234H88.0625V210.25H100.734V211.234ZM94.9844 210.672H93.7969V208.016H94.9844V210.672ZM99.25 208.625H89.6719V207.625H99.25V208.625ZM99.1562 205.016H90.875V208.234H89.6719V204.031H99.1562V205.016ZM94.3906 212.25C95.3802 212.25 96.2318 212.349 96.9453 212.547C97.6589 212.745 98.2057 213.031 98.5859 213.406C98.9714 213.776 99.1667 214.224 99.1719 214.75C99.1667 215.281 98.974 215.732 98.5938 216.102C98.2188 216.471 97.6719 216.755 96.9531 216.953C96.2344 217.156 95.3802 217.26 94.3906 217.266C93.3906 217.26 92.5312 217.156 91.8125 216.953C91.0938 216.755 90.5443 216.469 90.1641 216.094C89.7839 215.724 89.5938 215.276 89.5938 214.75C89.5938 214.224 89.7839 213.776 90.1641 213.406C90.5443 213.031 91.0938 212.745 91.8125 212.547C92.5312 212.349 93.3906 212.25 94.3906 212.25ZM94.3906 213.219C93.651 213.219 93.0156 213.279 92.4844 213.398C91.9531 213.518 91.5443 213.695 91.2578 213.93C90.9766 214.159 90.8385 214.432 90.8438 214.75C90.8385 215.073 90.9766 215.349 91.2578 215.578C91.5443 215.807 91.9531 215.982 92.4844 216.102C93.0156 216.221 93.651 216.281 94.3906 216.281C95.1198 216.281 95.75 216.221 96.2812 216.102C96.8125 215.982 97.2214 215.807 97.5078 215.578C97.7943 215.349 97.9375 215.073 97.9375 214.75C97.9375 214.432 97.7943 214.159 97.5078 213.93C97.2214 213.695 96.8125 213.518 96.2812 213.398C95.75 213.279 95.1198 213.219 94.3906 213.219ZM108.219 203.625C109.245 203.625 110.125 203.716 110.859 203.898C111.599 204.081 112.161 204.352 112.547 204.711C112.932 205.07 113.125 205.505 113.125 206.016C113.125 206.536 112.932 206.979 112.547 207.344C112.161 207.708 111.602 207.984 110.867 208.172C110.133 208.354 109.25 208.448 108.219 208.453C107.182 208.448 106.297 208.354 105.562 208.172C104.833 207.984 104.273 207.708 103.883 207.344C103.492 206.979 103.297 206.536 103.297 206.016C103.297 205.505 103.492 205.07 103.883 204.711C104.273 204.352 104.836 204.081 105.57 203.898C106.305 203.716 107.188 203.625 108.219 203.625ZM108.219 204.547C107.453 204.547 106.797 204.607 106.25 204.727C105.708 204.846 105.292 205.016 105 205.234C104.713 205.453 104.573 205.714 104.578 206.016C104.573 206.333 104.713 206.607 105 206.836C105.292 207.06 105.708 207.229 106.25 207.344C106.797 207.458 107.453 207.516 108.219 207.516C108.984 207.516 109.641 207.458 110.188 207.344C110.74 207.229 111.159 207.06 111.445 206.836C111.732 206.612 111.875 206.339 111.875 206.016C111.875 205.714 111.732 205.453 111.445 205.234C111.159 205.016 110.74 204.846 110.188 204.727C109.635 204.607 108.979 204.547 108.219 204.547ZM114.547 210.391H101.891V209.391H114.547V210.391ZM112.922 214.703H104.672V216.391H103.453V213.797H111.719V212.531H103.422V211.594H112.922V214.703ZM113.344 217.109H103.453V216.141H113.344V217.109ZM131.219 217.266H129.984V203.375H131.219V217.266ZM127.109 204.891C127.104 206.266 126.875 207.552 126.422 208.75C125.974 209.948 125.266 211.052 124.297 212.062C123.328 213.068 122.089 213.932 120.578 214.656L119.906 213.656C121.245 213.021 122.357 212.271 123.242 211.406C124.133 210.542 124.794 209.583 125.227 208.531C125.664 207.474 125.885 206.323 125.891 205.078V204.891H127.109ZM126.391 205.891H120.547V204.891H126.391V205.891ZM140.188 205.109C140.188 205.865 139.94 206.552 139.445 207.172C138.951 207.786 138.292 208.297 137.469 208.703C136.651 209.104 135.76 209.375 134.797 209.516L134.344 208.547C135.167 208.432 135.943 208.208 136.672 207.875C137.401 207.542 137.987 207.135 138.43 206.656C138.872 206.177 139.094 205.661 139.094 205.109V204.688H140.188V205.109ZM140.688 205.109C140.688 205.661 140.911 206.177 141.359 206.656C141.807 207.135 142.396 207.542 143.125 207.875C143.859 208.208 144.641 208.432 145.469 208.547L144.984 209.516C144.026 209.375 143.135 209.104 142.312 208.703C141.49 208.297 140.831 207.786 140.336 207.172C139.841 206.552 139.594 205.865 139.594 205.109V204.688H140.688V205.109ZM145.094 205.078H134.719V204.078H145.094V205.078ZM146.266 211.547H133.547V210.531H146.266V211.547ZM140.609 214.391H139.391V211.156H140.609V214.391ZM144.844 216.969H135.172V215.938H144.844V216.969ZM136.406 216.328H135.172V213H136.406V216.328ZM153.719 204.281C154.682 204.281 155.549 204.44 156.32 204.758C157.096 205.076 157.703 205.523 158.141 206.102C158.578 206.68 158.797 207.344 158.797 208.094C158.797 208.849 158.578 209.518 158.141 210.102C157.703 210.68 157.096 211.128 156.32 211.445C155.549 211.758 154.682 211.911 153.719 211.906C152.755 211.911 151.888 211.758 151.117 211.445C150.352 211.128 149.747 210.68 149.305 210.102C148.862 209.518 148.641 208.849 148.641 208.094C148.641 207.344 148.862 206.68 149.305 206.102C149.747 205.523 150.352 205.076 151.117 204.758C151.888 204.44 152.755 204.281 153.719 204.281ZM153.719 205.281C152.979 205.281 152.312 205.398 151.719 205.633C151.125 205.867 150.656 206.201 150.312 206.633C149.974 207.06 149.807 207.547 149.812 208.094C149.807 208.646 149.974 209.135 150.312 209.562C150.656 209.99 151.122 210.32 151.711 210.555C152.305 210.789 152.974 210.906 153.719 210.906C154.458 210.906 155.125 210.789 155.719 210.555C156.312 210.32 156.776 209.99 157.109 209.562C157.443 209.135 157.609 208.646 157.609 208.094C157.609 207.547 157.44 207.06 157.102 206.633C156.763 206.201 156.297 205.867 155.703 205.633C155.115 205.398 154.453 205.281 153.719 205.281ZM160.109 215.422H147.391V214.391H160.109V215.422ZM173.938 215.547H161.219V214.516H173.938V215.547ZM168.141 214.969H166.938V211.531H168.141V214.969ZM172.328 208.609H164.031V211.422H162.812V207.609H171.125V205.422H162.781V204.406H172.328V208.609ZM172.656 211.891H162.812V210.875H172.656V211.891ZM189.719 206.344H185.734V205.359H189.719V206.344ZM189.75 208.953H185.734V207.984H189.75V208.953ZM186.172 210.125H179.719V204.234H186.172V210.125ZM180.938 209.156H184.969V205.219H180.938V209.156ZM190.562 211.375H189.344V203.375H190.562V211.375ZM186.562 213.266C186.562 213.911 186.318 214.51 185.828 215.062C185.339 215.615 184.688 216.078 183.875 216.453C183.068 216.828 182.198 217.078 181.266 217.203L180.844 216.266C181.635 216.177 182.393 215.984 183.117 215.688C183.841 215.385 184.424 215.021 184.867 214.594C185.31 214.161 185.531 213.719 185.531 213.266V212.984H186.562V213.266ZM186.781 213.266C186.776 213.703 186.99 214.135 187.422 214.562C187.859 214.99 188.432 215.357 189.141 215.664C189.854 215.966 190.604 216.167 191.391 216.266L190.969 217.203C190.036 217.073 189.169 216.815 188.367 216.43C187.57 216.049 186.93 215.583 186.445 215.031C185.961 214.479 185.719 213.891 185.719 213.266V212.984H186.781V213.266ZM190.891 213.266H181.406V212.297H190.891V213.266ZM186.781 212.844H185.531V210.953H186.781V212.844ZM201.328 207.906C201.323 208.859 201.154 209.781 200.82 210.672C200.492 211.557 200.036 212.341 199.453 213.023C198.87 213.706 198.214 214.224 197.484 214.578L196.781 213.625C197.453 213.312 198.06 212.857 198.602 212.258C199.148 211.659 199.576 210.982 199.883 210.227C200.19 209.466 200.344 208.693 200.344 207.906V206.656H201.328V207.906ZM201.531 207.906C201.531 208.641 201.682 209.367 201.984 210.086C202.286 210.799 202.698 211.448 203.219 212.031C203.745 212.609 204.339 213.057 205 213.375L204.281 214.328C203.562 213.974 202.924 213.466 202.367 212.805C201.81 212.143 201.372 211.388 201.055 210.539C200.737 209.685 200.578 208.807 200.578 207.906V206.656H201.531V207.906ZM204.688 206.797H197.156V205.797H204.688V206.797ZM201.562 206.359H200.328V203.641H201.562V206.359ZM207.656 217.266H206.438V203.375H207.656V217.266ZM209.984 210.125H207.375V209.078H209.984V210.125ZM222.203 213.547H220.984V203.391H222.203V213.547ZM222.641 216.969H213.234V215.938H222.641V216.969ZM214.453 216.281H213.234V212.516H214.453V216.281ZM214.703 204.359C215.391 204.359 216.01 204.505 216.562 204.797C217.115 205.089 217.549 205.492 217.867 206.008C218.185 206.523 218.344 207.109 218.344 207.766C218.344 208.427 218.185 209.018 217.867 209.539C217.549 210.055 217.115 210.458 216.562 210.75C216.01 211.042 215.391 211.188 214.703 211.188C214.016 211.188 213.396 211.042 212.844 210.75C212.292 210.458 211.857 210.055 211.539 209.539C211.221 209.018 211.062 208.427 211.062 207.766C211.062 207.109 211.221 206.523 211.539 206.008C211.857 205.492 212.292 205.089 212.844 204.797C213.396 204.505 214.016 204.359 214.703 204.359ZM214.703 205.438C214.24 205.438 213.82 205.536 213.445 205.734C213.076 205.932 212.784 206.208 212.57 206.562C212.362 206.917 212.26 207.318 212.266 207.766C212.26 208.219 212.362 208.625 212.57 208.984C212.784 209.339 213.076 209.615 213.445 209.812C213.82 210.01 214.24 210.109 214.703 210.109C215.161 210.109 215.576 210.01 215.945 209.812C216.315 209.615 216.607 209.339 216.82 208.984C217.034 208.625 217.141 208.219 217.141 207.766C217.141 207.318 217.034 206.917 216.82 206.562C216.607 206.208 216.315 205.932 215.945 205.734C215.576 205.536 215.161 205.438 214.703 205.438ZM229.312 207.641C229.312 208.599 229.13 209.544 228.766 210.477C228.401 211.409 227.911 212.237 227.297 212.961C226.688 213.685 226.021 214.229 225.297 214.594L224.562 213.625C225.224 213.307 225.839 212.828 226.406 212.188C226.979 211.542 227.438 210.818 227.781 210.016C228.125 209.214 228.297 208.422 228.297 207.641V205.344H229.312V207.641ZM229.531 207.641C229.531 208.406 229.703 209.169 230.047 209.93C230.391 210.685 230.849 211.359 231.422 211.953C231.995 212.547 232.62 212.99 233.297 213.281L232.609 214.25C231.854 213.906 231.167 213.396 230.547 212.719C229.932 212.042 229.443 211.263 229.078 210.383C228.719 209.497 228.542 208.583 228.547 207.641V205.344H229.531V207.641ZM232.844 205.828H225.016V204.812H232.844V205.828ZM236.016 217.266H234.781V203.375H236.016V217.266ZM255.406 209.953H252.844V208.922H255.406V209.953ZM253.156 217.266H251.938V203.375H253.156V217.266ZM244.203 213.344H242.984V204.75H244.203V213.344ZM244.094 212.703C245.193 212.708 246.273 212.661 247.336 212.562C248.398 212.464 249.484 212.297 250.594 212.062L250.75 213.109C249.62 213.339 248.513 213.5 247.43 213.594C246.346 213.688 245.234 213.734 244.094 213.734H242.984V212.703H244.094ZM261.453 216.844H260.219V211.219H261.453V216.844ZM267.734 217.281H266.516V203.391H267.734V217.281ZM256.484 210.828C258.167 210.823 259.755 210.794 261.25 210.742C262.745 210.685 264.156 210.583 265.484 210.438L265.547 211.359C264.177 211.557 262.755 211.69 261.281 211.758C259.807 211.826 258.214 211.865 256.5 211.875H256.328L256.172 210.828H256.484ZM264.312 208.859H257.547V207.828H264.312V208.859ZM258.766 208.125H257.547V204.328H258.766V208.125ZM273.797 204.453C274.469 204.453 275.068 204.651 275.594 205.047C276.125 205.443 276.536 206.008 276.828 206.742C277.12 207.477 277.266 208.328 277.266 209.297C277.266 210.271 277.12 211.122 276.828 211.852C276.536 212.576 276.125 213.135 275.594 213.531C275.068 213.927 274.469 214.125 273.797 214.125C273.115 214.125 272.508 213.927 271.977 213.531C271.451 213.135 271.042 212.576 270.75 211.852C270.458 211.122 270.312 210.271 270.312 209.297C270.312 208.328 270.458 207.477 270.75 206.742C271.042 206.008 271.451 205.443 271.977 205.047C272.508 204.651 273.115 204.453 273.797 204.453ZM273.797 205.547C273.344 205.547 272.943 205.703 272.594 206.016C272.25 206.328 271.979 206.768 271.781 207.336C271.583 207.898 271.484 208.552 271.484 209.297C271.484 210.042 271.583 210.698 271.781 211.266C271.979 211.828 272.25 212.263 272.594 212.57C272.943 212.878 273.344 213.031 273.797 213.031C274.245 213.031 274.646 212.878 275 212.57C275.354 212.263 275.628 211.826 275.82 211.258C276.013 210.69 276.109 210.036 276.109 209.297C276.109 208.557 276.013 207.904 275.82 207.336C275.628 206.768 275.354 206.328 275 206.016C274.646 205.703 274.245 205.547 273.797 205.547ZM281.578 217.297H280.359V203.375H281.578V217.297ZM280.906 209.703H276.859V208.688H280.906V209.703ZM295.406 217.266H294.172V203.375H295.406V217.266ZM288.469 207.5C288.464 208.469 288.286 209.424 287.938 210.367C287.594 211.31 287.125 212.151 286.531 212.891C285.943 213.625 285.302 214.188 284.609 214.578L283.797 213.641C284.453 213.312 285.062 212.82 285.625 212.164C286.188 211.503 286.635 210.763 286.969 209.945C287.302 209.122 287.469 208.307 287.469 207.5V205.344H288.469V207.5ZM288.703 207.5C288.703 208.214 288.87 208.958 289.203 209.734C289.536 210.505 289.979 211.211 290.531 211.852C291.089 212.487 291.693 212.969 292.344 213.297L291.609 214.234C290.906 213.87 290.258 213.328 289.664 212.609C289.076 211.891 288.604 211.081 288.25 210.18C287.896 209.279 287.719 208.385 287.719 207.5V205.344H288.703V207.5ZM291.875 205.828H284.297V204.812H291.875V205.828ZM294.969 208.328H291.328V207.297H294.969V208.328ZM294.969 211.281H291.328V210.25H294.969V211.281ZM302.078 214.703H300.875V210.547H302.078V214.703ZM307.281 214.703H306.047V210.547H307.281V214.703ZM310.438 215.484H297.719V214.453H310.438V215.484ZM304.047 204.25C305.031 204.255 305.906 204.406 306.672 204.703C307.443 204.995 308.044 205.414 308.477 205.961C308.909 206.503 309.125 207.125 309.125 207.828C309.125 208.536 308.909 209.159 308.477 209.695C308.044 210.232 307.443 210.648 306.672 210.945C305.906 211.242 305.031 211.391 304.047 211.391C303.062 211.391 302.185 211.242 301.414 210.945C300.648 210.648 300.049 210.232 299.617 209.695C299.185 209.159 298.969 208.536 298.969 207.828C298.969 207.125 299.185 206.503 299.617 205.961C300.049 205.414 300.648 204.995 301.414 204.703C302.185 204.406 303.062 204.255 304.047 204.25ZM304.047 205.266C303.292 205.26 302.617 205.365 302.023 205.578C301.435 205.786 300.977 206.086 300.648 206.477C300.32 206.867 300.156 207.318 300.156 207.828C300.156 208.339 300.32 208.789 300.648 209.18C300.977 209.57 301.435 209.875 302.023 210.094C302.617 210.312 303.292 210.422 304.047 210.422C304.797 210.422 305.466 210.312 306.055 210.094C306.643 209.875 307.104 209.57 307.438 209.18C307.771 208.789 307.938 208.339 307.938 207.828C307.938 207.318 307.771 206.867 307.438 206.477C307.104 206.086 306.643 205.786 306.055 205.578C305.466 205.365 304.797 205.26 304.047 205.266Z" fill="#929195"/> +<path d="M380 230H50C45.5817 230 42 233.582 42 238V246C42 250.418 45.5817 254 50 254H380C384.418 254 388 250.418 388 246V238C388 233.582 384.418 230 380 230Z" fill="white"/> +<path d="M50.6602 243.188H47.9883V242.426H50.6602V243.188ZM51.0585 247.184H50.1327V239.543H51.0585V247.184ZM51.3516 249.727H44.3672V248.953H51.3516V249.727ZM45.2929 249.328H44.3672V246.492H45.2929V249.328ZM45.8789 241.688C45.8789 242.309 45.7559 242.896 45.5098 243.451C45.2637 244.002 44.918 244.486 44.4727 244.904C44.0312 245.318 43.5234 245.633 42.9492 245.848L42.4688 245.098C42.9765 244.918 43.4316 244.654 43.834 244.307C44.2363 243.959 44.5508 243.559 44.7773 243.105C45.0039 242.648 45.1172 242.176 45.1172 241.688V240.832H45.8789V241.688ZM46.0429 241.688C46.0429 242.133 46.1522 242.566 46.371 242.988C46.5897 243.41 46.8926 243.785 47.2793 244.113C47.666 244.441 48.1094 244.691 48.6094 244.863L48.1289 245.602C47.5703 245.398 47.0762 245.1 46.6465 244.705C46.2207 244.311 45.8887 243.854 45.6504 243.334C45.4121 242.814 45.2929 242.266 45.2929 241.688V240.832H46.0429V241.688ZM48.375 241.148H42.7617V240.387H48.375V241.148ZM59.0858 244.43H57.082V243.645H59.0858V244.43ZM55.6875 242.742C55.6836 243.438 55.584 244.117 55.3887 244.781C55.1973 245.445 54.918 246.043 54.5508 246.574C54.1875 247.102 53.7578 247.516 53.2617 247.816L52.7108 247.113C53.1718 246.848 53.5723 246.482 53.9121 246.018C54.252 245.553 54.5117 245.035 54.6914 244.465C54.875 243.895 54.9688 243.32 54.9727 242.742V242.191H55.6875V242.742ZM55.8398 242.742C55.8438 243.305 55.9355 243.855 56.1152 244.395C56.2988 244.934 56.5625 245.424 56.9062 245.865C57.25 246.303 57.6523 246.645 58.1133 246.891L57.5858 247.582C57.0819 247.309 56.6444 246.92 56.2733 246.416C55.9061 245.912 55.6229 245.342 55.4237 244.705C55.2284 244.068 55.1328 243.414 55.1367 242.742V242.191H55.8398V242.742ZM57.7969 242.227H52.9922V241.465H57.7969V242.227ZM55.8516 242.039H54.9727V239.918H55.8516V242.039ZM61.6992 249.949H60.8203V239.531H61.6992V249.949ZM59.5898 249.41H58.7226V239.789H59.5898V249.41ZM69.7383 242.73C69.7383 243.449 69.6015 244.158 69.328 244.857C69.0546 245.557 68.6875 246.178 68.2266 246.721C67.7695 247.264 67.2695 247.672 66.7266 247.945L66.1758 247.219C66.6719 246.98 67.1328 246.621 67.5586 246.141C67.9883 245.656 68.332 245.113 68.5898 244.512C68.8477 243.91 68.9766 243.316 68.9766 242.73V241.008H69.7383V242.73ZM69.9023 242.73C69.9023 243.305 70.0312 243.877 70.2891 244.447C70.5469 245.014 70.8906 245.52 71.3203 245.965C71.75 246.41 72.2188 246.742 72.7266 246.961L72.2108 247.688C71.6444 247.43 71.1289 247.047 70.6641 246.539C70.2031 246.031 69.8359 245.447 69.5625 244.787C69.293 244.123 69.1602 243.438 69.1641 242.73V241.008H69.9023V242.73ZM72.3867 241.371H66.5155V240.609H72.3867V241.371ZM74.7655 249.949H73.8398V239.531H74.7655V249.949ZM81.7383 246.293H80.8358V244.711H81.7383V246.293ZM86.0391 244.887H76.5586V244.172H86.0391V244.887ZM81.7383 240.738H80.8358V239.473H81.7383V240.738ZM81.5976 240.984C81.5976 241.512 81.4061 241.969 81.0233 242.355C80.6405 242.738 80.1269 243.041 79.4823 243.264C78.8417 243.482 78.125 243.625 77.332 243.691L77.0625 242.988C77.75 242.945 78.377 242.838 78.9434 242.666C79.5098 242.49 79.959 242.26 80.291 241.975C80.623 241.686 80.7891 241.355 80.7891 240.984V240.832H81.5976V240.984ZM81.7969 240.984C81.793 241.355 81.957 241.686 82.2891 241.975C82.625 242.26 83.0742 242.49 83.6367 242.666C84.2031 242.838 84.8319 242.945 85.5233 242.988L85.2421 243.691C84.453 243.625 83.7382 243.482 83.0976 243.264C82.4569 243.041 81.9453 242.738 81.5625 242.355C81.1797 241.969 80.9883 241.512 80.9883 240.984V240.832H81.7969V240.984ZM85.078 241.172H77.5312V240.445H85.078V241.172ZM84.8203 248.109H78.6328V249.387H77.7188V247.453H83.9179V246.551H77.6953V245.859H84.8203V248.109ZM85.1367 249.832H77.7188V249.129H85.1367V249.832ZM97.9102 240.855H91.1367V240.094H97.9102V240.855ZM99.4688 244.688H89.9297V243.926H99.4688V244.688ZM98.2147 240.867C98.2147 241.473 98.1952 242.023 98.1561 242.52C98.1171 243.012 98.0234 243.578 97.875 244.219L96.9608 244.16C97.0663 243.73 97.1425 243.326 97.1894 242.947C97.2401 242.568 97.2715 242.236 97.2832 241.951C97.2949 241.662 97.3007 241.324 97.3007 240.938V240.867V240.094H98.2147V240.867ZM98.2617 249.809H91.1016V246.129H98.2617V249.809ZM92.0156 249.059H97.3477V246.855H92.0156V249.059ZM102.797 240.188C103.25 240.188 103.658 240.291 104.021 240.498C104.385 240.705 104.67 240.996 104.877 241.371C105.084 241.746 105.187 242.172 105.187 242.648C105.187 243.125 105.084 243.547 104.877 243.914C104.67 244.281 104.385 244.568 104.021 244.775C103.662 244.982 103.254 245.086 102.797 245.086C102.336 245.086 101.926 244.982 101.566 244.775C101.207 244.568 100.926 244.281 100.723 243.914C100.519 243.547 100.418 243.125 100.418 242.648C100.418 242.172 100.519 241.746 100.723 241.371C100.926 240.996 101.207 240.705 101.566 240.498C101.926 240.291 102.336 240.188 102.797 240.188ZM102.797 240.984C102.5 240.984 102.234 241.055 102 241.195C101.766 241.336 101.58 241.535 101.443 241.793C101.31 242.047 101.246 242.332 101.25 242.648C101.246 242.965 101.31 243.25 101.443 243.504C101.58 243.754 101.766 243.951 102 244.096C102.234 244.24 102.5 244.312 102.797 244.312C103.09 244.312 103.353 244.24 103.588 244.096C103.826 243.951 104.012 243.754 104.144 243.504C104.277 243.25 104.344 242.965 104.344 242.648C104.344 242.332 104.277 242.047 104.144 241.793C104.012 241.535 103.826 241.336 103.588 241.195C103.353 241.055 103.09 240.984 102.797 240.984ZM109.148 245.742H108.269V239.543H109.148V245.742ZM108.551 242.988H106.547V242.227H108.551V242.988ZM106.887 245.672H106.019V239.742H106.887V245.672ZM109.148 249.949H108.246V247.066H102.129V246.328H109.148V249.949Z" fill="#B2B1B6"/> +<path d="M316.062 248H314.641V238.156H314.578L311.828 239.984V238.562L314.641 236.688H316.062V248ZM322.781 248.156C321.948 248.156 321.237 247.93 320.648 247.477C320.06 247.023 319.609 246.362 319.297 245.492C318.984 244.622 318.828 243.573 318.828 242.344C318.828 241.13 318.984 240.089 319.297 239.219C319.609 238.344 320.06 237.677 320.648 237.219C321.242 236.76 321.953 236.531 322.781 236.531C323.604 236.531 324.312 236.76 324.906 237.219C325.5 237.677 325.953 238.344 326.266 239.219C326.578 240.089 326.734 241.13 326.734 242.344C326.734 243.573 326.581 244.622 326.273 245.492C325.966 246.362 325.516 247.023 324.922 247.477C324.328 247.93 323.615 248.156 322.781 248.156ZM322.781 246.906C323.323 246.906 323.789 246.729 324.18 246.375C324.57 246.021 324.865 245.503 325.062 244.82C325.26 244.138 325.359 243.312 325.359 242.344C325.359 241.375 325.258 240.547 325.055 239.859C324.852 239.172 324.557 238.648 324.172 238.289C323.786 237.93 323.323 237.75 322.781 237.75C322.24 237.75 321.776 237.93 321.391 238.289C321.005 238.648 320.708 239.172 320.5 239.859C320.292 240.547 320.188 241.375 320.188 242.344C320.188 243.312 320.292 244.138 320.5 244.82C320.708 245.503 321.003 246.021 321.383 246.375C321.768 246.729 322.234 246.906 322.781 246.906ZM328.328 244.531L333.422 236.688H334.266V238.469H333.672L329.844 244.359V244.453H336.734V245.688H328.328V244.531ZM333.812 245.344V244.797V236.688H335.156V248H333.812V245.344ZM338.641 251.203H337.484L338.344 246.953H339.859L338.641 251.203ZM345.5 248.156C344.667 248.156 343.956 247.93 343.367 247.477C342.779 247.023 342.328 246.362 342.016 245.492C341.703 244.622 341.547 243.573 341.547 242.344C341.547 241.13 341.703 240.089 342.016 239.219C342.328 238.344 342.779 237.677 343.367 237.219C343.961 236.76 344.672 236.531 345.5 236.531C346.323 236.531 347.031 236.76 347.625 237.219C348.219 237.677 348.672 238.344 348.984 239.219C349.297 240.089 349.453 241.13 349.453 242.344C349.453 243.573 349.299 244.622 348.992 245.492C348.685 246.362 348.234 247.023 347.641 247.477C347.047 247.93 346.333 248.156 345.5 248.156ZM345.5 246.906C346.042 246.906 346.508 246.729 346.898 246.375C347.289 246.021 347.583 245.503 347.781 244.82C347.979 244.138 348.078 243.312 348.078 242.344C348.078 241.375 347.977 240.547 347.773 239.859C347.57 239.172 347.276 238.648 346.891 238.289C346.505 237.93 346.042 237.75 345.5 237.75C344.958 237.75 344.495 237.93 344.109 238.289C343.724 238.648 343.427 239.172 343.219 239.859C343.01 240.547 342.906 241.375 342.906 242.344C342.906 243.312 343.01 244.138 343.219 244.82C343.427 245.503 343.721 246.021 344.102 246.375C344.487 246.729 344.953 246.906 345.5 246.906ZM355.031 248.156C354.198 248.156 353.487 247.93 352.898 247.477C352.31 247.023 351.859 246.362 351.547 245.492C351.234 244.622 351.078 243.573 351.078 242.344C351.078 241.13 351.234 240.089 351.547 239.219C351.859 238.344 352.31 237.677 352.898 237.219C353.492 236.76 354.203 236.531 355.031 236.531C355.854 236.531 356.562 236.76 357.156 237.219C357.75 237.677 358.203 238.344 358.516 239.219C358.828 240.089 358.984 241.13 358.984 242.344C358.984 243.573 358.831 244.622 358.523 245.492C358.216 246.362 357.766 247.023 357.172 247.477C356.578 247.93 355.865 248.156 355.031 248.156ZM355.031 246.906C355.573 246.906 356.039 246.729 356.43 246.375C356.82 246.021 357.115 245.503 357.312 244.82C357.51 244.138 357.609 243.312 357.609 242.344C357.609 241.375 357.508 240.547 357.305 239.859C357.102 239.172 356.807 238.648 356.422 238.289C356.036 237.93 355.573 237.75 355.031 237.75C354.49 237.75 354.026 237.93 353.641 238.289C353.255 238.648 352.958 239.172 352.75 239.859C352.542 240.547 352.438 241.375 352.438 242.344C352.438 243.312 352.542 244.138 352.75 244.82C352.958 245.503 353.253 246.021 353.633 246.375C354.018 246.729 354.484 246.906 355.031 246.906ZM364.562 248.156C363.729 248.156 363.018 247.93 362.43 247.477C361.841 247.023 361.391 246.362 361.078 245.492C360.766 244.622 360.609 243.573 360.609 242.344C360.609 241.13 360.766 240.089 361.078 239.219C361.391 238.344 361.841 237.677 362.43 237.219C363.023 236.76 363.734 236.531 364.562 236.531C365.385 236.531 366.094 236.76 366.688 237.219C367.281 237.677 367.734 238.344 368.047 239.219C368.359 240.089 368.516 241.13 368.516 242.344C368.516 243.573 368.362 244.622 368.055 245.492C367.747 246.362 367.297 247.023 366.703 247.477C366.109 247.93 365.396 248.156 364.562 248.156ZM364.562 246.906C365.104 246.906 365.57 246.729 365.961 246.375C366.352 246.021 366.646 245.503 366.844 244.82C367.042 244.138 367.141 243.312 367.141 242.344C367.141 241.375 367.039 240.547 366.836 239.859C366.633 239.172 366.339 238.648 365.953 238.289C365.568 237.93 365.104 237.75 364.562 237.75C364.021 237.75 363.557 237.93 363.172 238.289C362.786 238.648 362.49 239.172 362.281 239.859C362.073 240.547 361.969 241.375 361.969 242.344C361.969 243.312 362.073 244.138 362.281 244.82C362.49 245.503 362.784 246.021 363.164 246.375C363.549 246.729 364.016 246.906 364.562 246.906ZM379.141 245.453H377.906V242.359H379.141V245.453ZM385.359 245.938H384.125V235.391H385.359V245.938ZM385.703 248.969H375.828V247.938H385.703V248.969ZM377.062 248.234H375.828V244.906H377.062V248.234ZM373.828 241.828C375.688 241.818 377.333 241.789 378.766 241.742C380.198 241.69 381.568 241.583 382.875 241.422L382.953 242.312C381.604 242.526 380.19 242.667 378.711 242.734C377.232 242.802 375.661 242.833 374 242.828L373.828 241.828ZM384.453 244.5H381.25V243.609H384.453V244.5ZM378.391 235.953C379.062 235.953 379.659 236.052 380.18 236.25C380.706 236.448 381.112 236.732 381.398 237.102C381.685 237.471 381.828 237.896 381.828 238.375C381.828 238.865 381.685 239.289 381.398 239.648C381.112 240.008 380.708 240.286 380.188 240.484C379.667 240.682 379.068 240.781 378.391 240.781C377.708 240.781 377.107 240.682 376.586 240.484C376.07 240.286 375.669 240.008 375.383 239.648C375.096 239.289 374.953 238.865 374.953 238.375C374.953 237.896 375.096 237.471 375.383 237.102C375.669 236.732 376.073 236.448 376.594 236.25C377.115 236.052 377.714 235.953 378.391 235.953ZM378.391 236.891C377.943 236.885 377.547 236.945 377.203 237.07C376.859 237.19 376.591 237.365 376.398 237.594C376.211 237.823 376.12 238.083 376.125 238.375C376.12 238.672 376.211 238.935 376.398 239.164C376.591 239.388 376.859 239.562 377.203 239.688C377.547 239.812 377.943 239.875 378.391 239.875C378.828 239.875 379.219 239.812 379.562 239.688C379.906 239.562 380.174 239.388 380.367 239.164C380.56 238.935 380.656 238.672 380.656 238.375C380.656 238.083 380.56 237.823 380.367 237.594C380.174 237.365 379.906 237.19 379.562 237.07C379.219 236.945 378.828 236.885 378.391 236.891Z" fill="#56555A"/> +<path d="M24 270H399V300H24V270Z" fill="white"/> +<mask id="mask2_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="270" width="375" height="30"> +<path d="M24 270H399V300H24V270Z" fill="white"/> +</mask> +<g mask="url(#mask2_1835_8259)"> +<path d="M24 271H399V269H24V271Z" fill="#F1F0F5"/> +</g> +<path d="M48.7266 283.187H46.0547V282.426H48.7266V283.187ZM49.125 287.184H48.1992V279.543H49.125V287.184ZM49.418 289.727H42.4336V288.953H49.418V289.727ZM43.3594 289.328H42.4336V286.492H43.3594V289.328ZM43.9453 281.687C43.9453 282.309 43.8223 282.896 43.5762 283.451C43.3301 284.002 42.9844 284.486 42.5391 284.904C42.0977 285.318 41.5898 285.633 41.0156 285.848L40.5352 285.098C41.043 284.918 41.498 284.654 41.9004 284.307C42.3027 283.959 42.6172 283.559 42.8437 283.105C43.0703 282.648 43.1836 282.176 43.1836 281.687V280.832H43.9453V281.687ZM44.1094 281.687C44.1094 282.133 44.2187 282.566 44.4375 282.988C44.6562 283.41 44.959 283.785 45.3457 284.113C45.7324 284.441 46.1758 284.691 46.6758 284.863L46.1953 285.602C45.6367 285.398 45.1426 285.1 44.7129 284.705C44.2871 284.311 43.9551 283.854 43.7168 283.334C43.4785 282.814 43.3594 282.266 43.3594 281.687V280.832H44.1094V281.687ZM46.4414 281.148H40.8281V280.387H46.4414V281.148ZM57.1523 284.43H55.1484V283.645H57.1523V284.43ZM53.7539 282.742C53.75 283.437 53.6504 284.117 53.4551 284.781C53.2637 285.445 52.9844 286.043 52.6172 286.574C52.2539 287.102 51.8242 287.516 51.3281 287.816L50.7773 287.113C51.2383 286.848 51.6387 286.482 51.9785 286.018C52.3184 285.553 52.5781 285.035 52.7578 284.465C52.9414 283.895 53.0352 283.32 53.0391 282.742V282.191H53.7539V282.742ZM53.9062 282.742C53.9102 283.305 54.002 283.855 54.1816 284.395C54.3652 284.934 54.6289 285.424 54.9727 285.865C55.3164 286.303 55.7187 286.645 56.1797 286.891L55.6523 287.582C55.1484 287.309 54.7109 286.92 54.3398 286.416C53.9727 285.912 53.6895 285.342 53.4902 284.705C53.2949 284.068 53.1992 283.414 53.2031 282.742V282.191H53.9062V282.742ZM55.8633 282.227H51.0586V281.465H55.8633V282.227ZM53.918 282.039H53.0391V279.918H53.918V282.039ZM59.7656 289.949H58.8867V279.531H59.7656V289.949ZM57.6562 289.41H56.7891V279.789H57.6562V289.41ZM67.6406 281.699C67.6406 282.285 67.5176 282.832 67.2715 283.34C67.0254 283.848 66.6797 284.287 66.2344 284.658C65.7891 285.029 65.2773 285.309 64.6992 285.496L64.2422 284.77C64.7578 284.613 65.2168 284.381 65.6191 284.072C66.0215 283.764 66.334 283.406 66.5566 283C66.7793 282.59 66.8906 282.156 66.8906 281.699V281.254H67.6406V281.699ZM67.793 281.699C67.793 282.121 67.9023 282.521 68.1211 282.9C68.3398 283.279 68.6426 283.615 69.0293 283.908C69.4199 284.197 69.8711 284.418 70.3828 284.57L69.9492 285.297C69.3711 285.117 68.8633 284.85 68.4258 284.494C67.9883 284.139 67.6484 283.723 67.4062 283.246C67.1641 282.766 67.043 282.25 67.043 281.699V281.254H67.793V281.699ZM70.1484 281.512H64.5352V280.773H70.1484V281.512ZM67.8164 281.066H66.8906V279.484H67.8164V281.066ZM72.3867 285.707H71.4727V279.531H72.3867V285.707ZM73.957 282.953H72.1289V282.18H73.957V282.953ZM72.3867 289.809H65.8125V286.187H72.3867V289.809ZM66.7148 289.059H71.4727V286.914H66.7148V289.059ZM82.5586 282.637H79.3477V281.863H82.5586V282.637ZM82.5586 285.93H79.3477V285.168H82.5586V285.93ZM77.4141 280.34C77.918 280.34 78.3672 280.488 78.7617 280.785C79.1602 281.082 79.4687 281.506 79.6875 282.057C79.9062 282.607 80.0156 283.246 80.0156 283.973C80.0156 284.703 79.9062 285.342 79.6875 285.889C79.4687 286.432 79.1602 286.852 78.7617 287.148C78.3672 287.445 77.918 287.594 77.4141 287.594C76.9023 287.594 76.4473 287.445 76.0488 287.148C75.6543 286.852 75.3477 286.432 75.1289 285.889C74.9102 285.342 74.8008 284.703 74.8008 283.973C74.8008 283.246 74.9102 282.607 75.1289 282.057C75.3477 281.506 75.6543 281.082 76.0488 280.785C76.4473 280.488 76.9023 280.34 77.4141 280.34ZM77.4141 281.16C77.0742 281.16 76.7734 281.277 76.5117 281.512C76.2539 281.746 76.0508 282.076 75.9023 282.502C75.7539 282.924 75.6797 283.414 75.6797 283.973C75.6797 284.531 75.7539 285.023 75.9023 285.449C76.0508 285.871 76.2539 286.197 76.5117 286.428C76.7734 286.658 77.0742 286.773 77.4141 286.773C77.75 286.773 78.0508 286.658 78.3164 286.428C78.582 286.197 78.7871 285.869 78.9316 285.443C79.0762 285.018 79.1484 284.527 79.1484 283.973C79.1484 283.418 79.0762 282.928 78.9316 282.502C78.7871 282.076 78.582 281.746 78.3164 281.512C78.0508 281.277 77.75 281.16 77.4141 281.16ZM83.25 289.973H82.3359V279.531H83.25V289.973ZM88.3359 282.73C88.3359 283.437 88.2031 284.141 87.9375 284.84C87.6719 285.535 87.3105 286.158 86.8535 286.709C86.3965 287.26 85.9023 287.672 85.3711 287.945L84.8086 287.219C85.3047 286.977 85.7656 286.613 86.1914 286.129C86.6211 285.645 86.9629 285.102 87.2168 284.5C87.4746 283.898 87.6055 283.309 87.6094 282.73V281.008H88.3359V282.73ZM88.5117 282.73C88.5078 283.277 88.625 283.832 88.8633 284.395C89.1055 284.957 89.4336 285.467 89.8477 285.924C90.2617 286.377 90.7187 286.723 91.2187 286.961L90.6914 287.687C90.1484 287.422 89.6543 287.029 89.209 286.51C88.7676 285.99 88.418 285.4 88.1602 284.74C87.9023 284.076 87.7734 283.406 87.7734 282.73V281.008H88.5117V282.73ZM90.8555 281.371H85.1836V280.609H90.8555V281.371ZM93.0469 289.949H92.1328V279.531H93.0469V289.949ZM94.793 284.535H92.8359V283.75H94.793V284.535Z" fill="#B2B1B6"/> +<path d="M349.656 286.398L353.477 280.516H354.109V281.852H353.664L350.793 286.27V286.34H355.961V287.266H349.656V286.398ZM353.77 287.008V286.598V280.516H354.777V289H353.77V287.008ZM365.055 281.992H361.984V281.23H365.055V281.992ZM365.066 284.066H361.984V283.293H365.066V284.066ZM365.617 285.707H364.691V279.531H365.617V285.707ZM362.254 284.957H357.473V280.328H362.254V284.957ZM358.387 284.207H361.352V281.078H358.387V284.207ZM362.16 286.012C362.879 286.012 363.5 286.088 364.023 286.24C364.547 286.393 364.949 286.617 365.23 286.914C365.512 287.211 365.652 287.566 365.652 287.98C365.652 288.391 365.512 288.74 365.23 289.029C364.949 289.322 364.547 289.545 364.023 289.697C363.5 289.85 362.879 289.926 362.16 289.926C361.437 289.926 360.814 289.85 360.291 289.697C359.771 289.545 359.371 289.322 359.09 289.029C358.809 288.74 358.668 288.391 358.668 287.98C358.668 287.566 358.809 287.211 359.09 286.914C359.371 286.617 359.771 286.393 360.291 286.24C360.814 286.088 361.437 286.012 362.16 286.012ZM362.16 286.727C361.629 286.73 361.17 286.783 360.783 286.885C360.396 286.982 360.1 287.125 359.893 287.312C359.686 287.5 359.582 287.723 359.582 287.98C359.582 288.23 359.686 288.447 359.893 288.631C360.1 288.814 360.396 288.955 360.783 289.053C361.17 289.15 361.629 289.199 362.16 289.199C362.687 289.199 363.145 289.15 363.531 289.053C363.922 288.955 364.221 288.814 364.428 288.631C364.635 288.447 364.738 288.23 364.738 287.98C364.738 287.723 364.635 287.5 364.428 287.312C364.221 287.125 363.924 286.982 363.537 286.885C363.15 286.783 362.691 286.73 362.16 286.727Z" fill="#B2B1B6"/> +<mask id="mask3_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="375" y="279" width="8" height="12"> +<path d="M383 283C383 280.791 381.209 279 379 279C376.791 279 375 280.791 375 283V287C375 289.209 376.791 291 379 291C381.209 291 383 289.209 383 287V283Z" fill="white"/> +</mask> +<g mask="url(#mask3_1835_8259)"> +<path d="M377 281L381 285L377 289" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +</g> +<path d="M390 316H40C35.5817 316 32 319.582 32 324V348C32 352.418 35.5817 356 40 356H390C394.418 356 398 352.418 398 348V324C398 319.582 394.418 316 390 316Z" fill="white"/> +<path d="M52.4062 339.633H50.4219V329.234H52.4062V339.633ZM50.7031 334.977H47.875V333.352H50.7031V334.977ZM48.0078 330.273C48.0026 331.539 47.7422 332.693 47.2266 333.734C46.7109 334.771 45.9609 335.669 44.9766 336.43C43.9922 337.185 42.8073 337.779 41.4219 338.211L40.6016 336.617C41.6953 336.273 42.638 335.831 43.4297 335.289C44.2266 334.742 44.8333 334.12 45.25 333.422C45.6719 332.724 45.8854 331.974 45.8906 331.172V330.273H48.0078ZM47.1641 331.906H41.3437V330.273H47.1641V331.906ZM52.7734 343.195H43.0234V341.586H52.7734V343.195ZM45.0469 342.508H43.0234V338.57H45.0469V342.508ZM59.0547 331.258C59.0547 332.227 58.9089 333.125 58.6172 333.953C58.3307 334.781 57.8932 335.503 57.3047 336.117C56.7161 336.727 55.987 337.18 55.1172 337.477L54.0469 335.914C54.8073 335.654 55.4401 335.286 55.9453 334.812C56.4505 334.333 56.8229 333.792 57.0625 333.187C57.3021 332.583 57.4245 331.94 57.4297 331.258V329.969H59.0547V331.258ZM59.4297 331.453C59.4297 332.052 59.5469 332.617 59.7812 333.148C60.0208 333.68 60.3828 334.154 60.8672 334.57C61.3568 334.982 61.9635 335.302 62.6875 335.531L61.625 337.078C60.7917 336.802 60.0911 336.388 59.5234 335.836C58.9557 335.279 58.5286 334.628 58.2422 333.883C57.9557 333.138 57.8151 332.328 57.8203 331.453V329.969H59.4297V331.453ZM65.5312 337.648H63.5391V329.203H65.5312V337.648ZM67.4531 334.203H64.9687V332.539H67.4531V334.203ZM60.8672 337.937C61.8464 337.937 62.6953 338.047 63.4141 338.266C64.138 338.479 64.6927 338.794 65.0781 339.211C65.4687 339.622 65.6641 340.112 65.6641 340.68C65.6641 341.258 65.4687 341.753 65.0781 342.164C64.6927 342.576 64.138 342.891 63.4141 343.109C62.6953 343.328 61.8464 343.437 60.8672 343.437C59.8724 343.437 59.0078 343.328 58.2734 343.109C57.5443 342.891 56.9818 342.576 56.5859 342.164C56.1901 341.753 55.9922 341.258 55.9922 340.68C55.9922 340.112 56.1901 339.622 56.5859 339.211C56.9818 338.794 57.5443 338.479 58.2734 338.266C59.0078 338.047 59.8724 337.937 60.8672 337.937ZM60.8672 339.5C60.2474 339.495 59.724 339.539 59.2969 339.633C58.8698 339.721 58.5443 339.854 58.3203 340.031C58.1016 340.208 57.9948 340.424 58 340.68C57.9948 340.945 58.1016 341.167 58.3203 341.344C58.5391 341.521 58.8594 341.654 59.2812 341.742C59.7083 341.831 60.237 341.875 60.8672 341.875C61.487 341.875 62.0078 341.831 62.4297 341.742C62.8516 341.654 63.1693 341.521 63.3828 341.344C63.5964 341.167 63.7031 340.945 63.7031 340.68C63.7031 340.424 63.5937 340.208 63.375 340.031C63.1615 339.849 62.8437 339.714 62.4219 339.625C62 339.536 61.4818 339.495 60.8672 339.5ZM69.7266 345.297H68.0703L68.8437 340.852H71.0781L69.7266 345.297ZM82.9297 331.227C82.9297 332.07 82.7031 332.841 82.25 333.539C81.8021 334.232 81.1484 334.815 80.2891 335.289C79.4297 335.758 78.4115 336.073 77.2344 336.234L76.4922 334.68C77.487 334.56 78.3385 334.323 79.0469 333.969C79.7604 333.609 80.2969 333.193 80.6562 332.719C81.0156 332.24 81.1953 331.742 81.1953 331.227V330.797H82.9297V331.227ZM83.5 331.227C83.5 331.742 83.6771 332.24 84.0312 332.719C84.3906 333.193 84.9245 333.609 85.6328 333.969C86.3464 334.323 87.2083 334.56 88.2187 334.68L87.5 336.234C86.3125 336.073 85.2865 335.758 84.4219 335.289C83.5573 334.815 82.8984 334.232 82.4453 333.539C81.9922 332.841 81.7656 332.07 81.7656 331.227V330.797H83.5V331.227ZM83.2969 343.445H81.3203V338.203H83.2969V343.445ZM88.8359 338.656H75.8672V337.07H88.8359V338.656ZM87.6641 331.523H77.0312V329.969H87.6641V331.523ZM101.062 340.32H99.0547V329.203H101.062V340.32ZM102.883 335.531H100.352V333.891H102.883V335.531ZM101.547 343.195H91.5234V341.586H101.547V343.195ZM93.5391 342.062H91.5234V339.586H93.5391V342.062ZM94.9687 338.125H92.9844V336.039H94.9687V338.125ZM89.5391 337.391C91.1849 337.391 92.7474 337.359 94.2266 337.297C95.7057 337.229 97.0964 337.102 98.3984 336.914L98.5469 338.281C97.2969 338.521 96.0078 338.682 94.6797 338.766C93.3516 338.849 91.8385 338.904 90.1406 338.93C90.0625 338.93 89.9948 338.93 89.9375 338.93C89.8802 338.93 89.8125 338.93 89.7344 338.93L89.5391 337.391ZM98.0391 331.805H89.8984V330.367H98.0391V331.805ZM93.9687 332.195C94.6615 332.195 95.2708 332.284 95.7969 332.461C96.3229 332.633 96.7292 332.888 97.0156 333.227C97.3021 333.56 97.4479 333.958 97.4531 334.422C97.4479 334.859 97.3021 335.242 97.0156 335.57C96.7292 335.893 96.3229 336.146 95.7969 336.328C95.2708 336.505 94.6615 336.594 93.9687 336.594C93.2708 336.594 92.6589 336.505 92.1328 336.328C91.6068 336.151 91.1979 335.901 90.9062 335.578C90.6198 335.25 90.4766 334.865 90.4766 334.422C90.4766 333.958 90.6198 333.56 90.9062 333.227C91.1979 332.888 91.6042 332.633 92.125 332.461C92.651 332.284 93.2656 332.195 93.9687 332.195ZM93.9687 333.531C93.625 333.531 93.3359 333.562 93.1016 333.625C92.8672 333.687 92.6875 333.786 92.5625 333.922C92.4427 334.057 92.3828 334.224 92.3828 334.422C92.3828 334.594 92.4427 334.745 92.5625 334.875C92.6875 335 92.8672 335.096 93.1016 335.164C93.3411 335.227 93.6302 335.258 93.9687 335.258C94.2969 335.258 94.5781 335.227 94.8125 335.164C95.0521 335.096 95.2318 335 95.3516 334.875C95.4766 334.745 95.5391 334.594 95.5391 334.422C95.5391 334.224 95.4792 334.057 95.3594 333.922C95.2396 333.786 95.0599 333.687 94.8203 333.625C94.5859 333.562 94.3021 333.531 93.9687 333.531ZM94.9687 331.008H92.9844V329.164H94.9687V331.008ZM105.164 345.297H103.508L104.281 340.852H106.516L105.164 345.297ZM123.687 332.609H111.852V331.016H123.687V332.609ZM124.305 341.992H111.305V340.383H124.305V341.992ZM118.75 341.008H116.773V338.469H118.75V341.008ZM117.766 333.227C118.745 333.227 119.599 333.336 120.328 333.555C121.062 333.773 121.625 334.094 122.016 334.516C122.411 334.932 122.609 335.424 122.609 335.992C122.609 336.57 122.411 337.07 122.016 337.492C121.625 337.909 121.065 338.232 120.336 338.461C119.607 338.685 118.75 338.799 117.766 338.805C116.766 338.799 115.901 338.685 115.172 338.461C114.443 338.232 113.88 337.909 113.484 337.492C113.094 337.07 112.901 336.57 112.906 335.992C112.901 335.419 113.094 334.924 113.484 334.508C113.88 334.091 114.443 333.773 115.172 333.555C115.906 333.336 116.771 333.227 117.766 333.227ZM117.766 334.781C117.141 334.786 116.62 334.833 116.203 334.922C115.792 335.005 115.479 335.138 115.266 335.32C115.052 335.497 114.948 335.721 114.953 335.992C114.948 336.263 115.052 336.49 115.266 336.672C115.479 336.849 115.792 336.984 116.203 337.078C116.62 337.167 117.141 337.211 117.766 337.211C118.375 337.211 118.885 337.167 119.297 337.078C119.713 336.984 120.029 336.849 120.242 336.672C120.456 336.49 120.562 336.263 120.562 335.992C120.562 335.721 120.456 335.497 120.242 335.32C120.029 335.138 119.713 335.005 119.297 334.922C118.885 334.833 118.375 334.786 117.766 334.781ZM118.75 332.008H116.773V329.359H118.75V332.008ZM137.109 339.633H135.125V329.234H137.109V339.633ZM135.406 334.977H132.578V333.352H135.406V334.977ZM132.711 330.273C132.706 331.539 132.445 332.693 131.93 333.734C131.414 334.771 130.664 335.669 129.68 336.43C128.695 337.185 127.51 337.779 126.125 338.211L125.305 336.617C126.398 336.273 127.341 335.831 128.133 335.289C128.93 334.742 129.536 334.12 129.953 333.422C130.375 332.724 130.589 331.974 130.594 331.172V330.273H132.711ZM131.867 331.906H126.047V330.273H131.867V331.906ZM137.477 343.195H127.727V341.586H137.477V343.195ZM129.75 342.508H127.727V338.57H129.75V342.508ZM140.602 345.297H138.945L139.719 340.852H141.953L140.602 345.297ZM153.805 331.227C153.805 332.07 153.578 332.841 153.125 333.539C152.677 334.232 152.023 334.815 151.164 335.289C150.305 335.758 149.286 336.073 148.109 336.234L147.367 334.68C148.362 334.56 149.214 334.323 149.922 333.969C150.635 333.609 151.172 333.193 151.531 332.719C151.891 332.24 152.07 331.742 152.07 331.227V330.797H153.805V331.227ZM154.375 331.227C154.375 331.742 154.552 332.24 154.906 332.719C155.266 333.193 155.799 333.609 156.508 333.969C157.221 334.323 158.083 334.56 159.094 334.68L158.375 336.234C157.187 336.073 156.161 335.758 155.297 335.289C154.432 334.815 153.773 334.232 153.32 333.539C152.867 332.841 152.641 332.07 152.641 331.227V330.797H154.375V331.227ZM154.172 343.445H152.195V338.203H154.172V343.445ZM159.711 338.656H146.742V337.07H159.711V338.656ZM158.539 331.523H147.906V329.969H158.539V331.523ZM171.781 343.437H169.812V329.203H171.781V343.437ZM173.891 336.422H171.344V334.789H173.891V336.422ZM168.844 332.937H160.492V331.336H168.844V332.937ZM164.703 333.727C165.385 333.727 166.003 333.872 166.555 334.164C167.112 334.451 167.547 334.852 167.859 335.367C168.177 335.883 168.339 336.466 168.344 337.117C168.339 337.773 168.177 338.359 167.859 338.875C167.547 339.385 167.112 339.786 166.555 340.078C166.003 340.365 165.385 340.508 164.703 340.508C164.01 340.508 163.388 340.365 162.836 340.078C162.284 339.786 161.852 339.385 161.539 338.875C161.227 338.359 161.07 337.773 161.07 337.117C161.07 336.466 161.227 335.883 161.539 335.367C161.852 334.852 162.284 334.451 162.836 334.164C163.388 333.872 164.01 333.727 164.703 333.727ZM164.703 335.352C164.37 335.357 164.073 335.43 163.812 335.57C163.552 335.711 163.346 335.917 163.195 336.187C163.049 336.453 162.977 336.763 162.977 337.117C162.977 337.482 163.049 337.797 163.195 338.062C163.346 338.323 163.552 338.523 163.812 338.664C164.073 338.805 164.37 338.878 164.703 338.883C165.036 338.878 165.333 338.805 165.594 338.664C165.859 338.523 166.062 338.323 166.203 338.062C166.349 337.797 166.422 337.482 166.422 337.117C166.422 336.763 166.349 336.453 166.203 336.187C166.062 335.917 165.859 335.711 165.594 335.57C165.333 335.43 165.036 335.357 164.703 335.352ZM165.695 331.945H163.711V329.43H165.695V331.945ZM191.094 336.336H178.102V334.773H191.094V336.336ZM189.539 333.984H179.711V332.414H189.539V333.984ZM189.437 331.086H181.703V333.75H179.711V329.508H189.437V331.086ZM189.484 340.883H181.562V342.164H179.602V339.469H187.516V338.672H179.594V337.172H189.484V340.883ZM189.859 343.32H179.602V341.773H189.859V343.32ZM195.844 330.211C196.552 330.211 197.185 330.419 197.742 330.836C198.305 331.247 198.742 331.839 199.055 332.609C199.367 333.375 199.523 334.266 199.523 335.281C199.523 336.302 199.367 337.198 199.055 337.969C198.742 338.734 198.305 339.323 197.742 339.734C197.185 340.146 196.552 340.352 195.844 340.352C195.125 340.352 194.487 340.146 193.93 339.734C193.372 339.323 192.935 338.734 192.617 337.969C192.299 337.198 192.141 336.302 192.141 335.281C192.141 334.266 192.299 333.375 192.617 332.609C192.935 331.839 193.372 331.247 193.93 330.836C194.487 330.419 195.125 330.211 195.844 330.211ZM195.844 332.016C195.484 332.01 195.172 332.135 194.906 332.391C194.641 332.646 194.432 333.018 194.281 333.508C194.13 333.997 194.057 334.589 194.062 335.281C194.057 335.974 194.13 336.565 194.281 337.055C194.432 337.544 194.641 337.917 194.906 338.172C195.172 338.422 195.484 338.547 195.844 338.547C196.203 338.547 196.518 338.422 196.789 338.172C197.06 337.917 197.268 337.544 197.414 337.055C197.56 336.565 197.633 335.974 197.633 335.281C197.633 334.589 197.56 333.997 197.414 333.508C197.268 333.013 197.06 332.641 196.789 332.391C196.518 332.135 196.203 332.01 195.844 332.016ZM203.922 343.477H201.945V329.203H203.922V343.477ZM202.797 335.953H198.93V334.352H202.797V335.953ZM213.187 336.516H211.227V334.398H213.187V336.516ZM212.234 329.422C213.281 329.422 214.193 329.534 214.969 329.758C215.75 329.977 216.349 330.294 216.766 330.711C217.187 331.128 217.398 331.617 217.398 332.18C217.398 332.742 217.187 333.232 216.766 333.648C216.349 334.065 215.753 334.385 214.977 334.609C214.201 334.828 213.286 334.935 212.234 334.93C211.187 334.935 210.273 334.828 209.492 334.609C208.711 334.385 208.107 334.065 207.68 333.648C207.258 333.232 207.047 332.742 207.047 332.18C207.047 331.617 207.26 331.128 207.687 330.711C208.115 330.294 208.716 329.977 209.492 329.758C210.273 329.534 211.187 329.422 212.234 329.422ZM212.234 330.953C211.573 330.953 211.008 331 210.539 331.094C210.076 331.182 209.721 331.32 209.477 331.508C209.237 331.69 209.117 331.914 209.117 332.18C209.117 332.456 209.237 332.687 209.477 332.875C209.721 333.057 210.073 333.195 210.531 333.289C210.995 333.378 211.562 333.422 212.234 333.422C212.896 333.422 213.458 333.378 213.922 333.289C214.391 333.195 214.745 333.057 214.984 332.875C215.224 332.687 215.344 332.456 215.344 332.18C215.344 331.914 215.221 331.69 214.977 331.508C214.732 331.32 214.378 331.182 213.914 331.094C213.451 331 212.891 330.953 212.234 330.953ZM217.172 343.281H207.258V338.43H217.172V343.281ZM209.219 341.68H215.219V340.008H209.219V341.68ZM218.727 337.492H205.758V335.914H218.727V337.492Z" fill="#56555A"/> +<path d="M386 364H44C37.3726 364 32 369.373 32 376V556C32 562.627 37.3726 568 44 568H386C392.627 568 398 562.627 398 556V376C398 369.373 392.627 364 386 364Z" fill="white"/> +<path d="M52.3184 385H50.5488V378.191H50.502L48.5625 379.422V377.852L50.6602 376.516H52.3184V385ZM57.4922 378.76C57.4883 379.525 57.375 380.262 57.1523 380.969C56.9297 381.676 56.5977 382.307 56.1562 382.861C55.7187 383.412 55.1875 383.824 54.5625 384.098L53.7422 382.937C54.2969 382.695 54.7676 382.35 55.1543 381.9C55.5449 381.447 55.8359 380.949 56.0273 380.406C56.2187 379.863 56.3145 379.314 56.3145 378.76V378.15H57.4922V378.76ZM57.7969 378.76C57.793 379.283 57.8828 379.803 58.0664 380.318C58.2539 380.83 58.5332 381.305 58.9043 381.742C59.2754 382.176 59.7324 382.521 60.2754 382.779L59.4492 383.916C58.8437 383.643 58.3301 383.238 57.9082 382.703C57.4863 382.164 57.168 381.555 56.9531 380.875C56.7383 380.191 56.6328 379.486 56.6367 378.76V378.15H57.7969V378.76ZM59.9766 378.344H54.1055V377.154H59.9766V378.344ZM57.8086 377.775H56.3086V375.648H57.8086V377.775ZM62.3555 386.078H60.8555V375.402H62.3555V386.078ZM63.9375 380.805H62.0273V379.551H63.9375V380.805Z" fill="#56555A"/> +<path d="M364.586 382.398L368.406 376.516H369.039V377.852H368.594L365.723 382.27V382.34H370.891V383.266H364.586V382.398ZM368.699 383.008V382.598V376.516H369.707V385H368.699V383.008ZM379.984 377.992H376.914V377.23H379.984V377.992ZM379.996 380.066H376.914V379.293H379.996V380.066ZM380.547 381.707H379.621V375.531H380.547V381.707ZM377.184 380.957H372.402V376.328H377.184V380.957ZM373.316 380.207H376.281V377.078H373.316V380.207ZM377.09 382.012C377.809 382.012 378.43 382.088 378.953 382.24C379.477 382.393 379.879 382.617 380.16 382.914C380.441 383.211 380.582 383.566 380.582 383.98C380.582 384.391 380.441 384.74 380.16 385.029C379.879 385.322 379.477 385.545 378.953 385.697C378.43 385.85 377.809 385.926 377.09 385.926C376.367 385.926 375.744 385.85 375.221 385.697C374.701 385.545 374.301 385.322 374.02 385.029C373.738 384.74 373.598 384.391 373.598 383.98C373.598 383.566 373.738 383.211 374.02 382.914C374.301 382.617 374.701 382.393 375.221 382.24C375.744 382.088 376.367 382.012 377.09 382.012ZM377.09 382.727C376.559 382.73 376.1 382.783 375.713 382.885C375.326 382.982 375.029 383.125 374.822 383.312C374.615 383.5 374.512 383.723 374.512 383.98C374.512 384.23 374.615 384.447 374.822 384.631C375.029 384.814 375.326 384.955 375.713 385.053C376.1 385.15 376.559 385.199 377.09 385.199C377.617 385.199 378.074 385.15 378.461 385.053C378.852 384.955 379.15 384.814 379.357 384.631C379.564 384.447 379.668 384.23 379.668 383.98C379.668 383.723 379.564 383.5 379.357 383.312C379.15 383.125 378.854 382.982 378.467 382.885C378.08 382.783 377.621 382.73 377.09 382.727Z" fill="#B2B1B6"/> +<path d="M364 386.916H381.859V387.73H364V386.916Z" fill="#B2B1B6"/> +<path d="M382 398H48C43.5817 398 40 401.582 40 406V430C40 434.418 43.5817 438 48 438H382C386.418 438 390 434.418 390 430V406C390 401.582 386.418 398 382 398Z" fill="#F9F8FD"/> +<path d="M51.3203 412.82H52.6406V411.625H54.4844V417.078H49.4375V411.625H51.3203V412.82ZM52.6406 415.477V414.328H51.3203V415.477H52.6406ZM57.2109 412.82H58.4766V411.625H60.375V417.078H55.3125V411.625H57.2109V412.82ZM58.4766 415.477V414.328H57.2109V415.477H58.4766ZM61.3984 419.719H48.4297V418.125H61.3984V419.719ZM55.8906 418.703H53.8828V416.641H55.8906V418.703ZM54.8906 420.414C55.9167 420.414 56.7995 420.513 57.5391 420.711C58.2839 420.909 58.8542 421.195 59.25 421.57C59.6458 421.945 59.8464 422.396 59.8516 422.922C59.8464 423.458 59.6458 423.914 59.25 424.289C58.8594 424.669 58.2917 424.956 57.5469 425.148C56.8021 425.346 55.9167 425.443 54.8906 425.437C53.849 425.437 52.9557 425.341 52.2109 425.148C51.4714 424.956 50.9036 424.672 50.5078 424.297C50.1172 423.922 49.9219 423.464 49.9219 422.922C49.9219 422.396 50.1172 421.945 50.5078 421.57C50.9036 421.195 51.4714 420.909 52.2109 420.711C52.9557 420.513 53.849 420.414 54.8906 420.414ZM54.8906 421.898C54.2187 421.898 53.6615 421.937 53.2187 422.016C52.7812 422.089 52.4531 422.203 52.2344 422.359C52.0208 422.51 51.9167 422.698 51.9219 422.922C51.9167 423.151 52.0234 423.341 52.2422 423.492C52.4661 423.643 52.7943 423.758 53.2266 423.836C53.6641 423.914 54.2187 423.953 54.8906 423.953C55.5417 423.953 56.0833 423.914 56.5156 423.836C56.9531 423.758 57.2812 423.643 57.5 423.492C57.7187 423.341 57.8281 423.151 57.8281 422.922C57.8281 422.698 57.7187 422.51 57.5 422.359C57.2812 422.203 56.9557 422.089 56.5234 422.016C56.0911 421.937 55.5469 421.898 54.8906 421.898ZM66.3594 413.992C66.3542 414.831 66.237 415.615 66.0078 416.344C65.7839 417.073 65.4297 417.719 64.9453 418.281C64.4661 418.844 63.8594 419.271 63.125 419.562L62.0547 418.039C62.6797 417.784 63.1979 417.445 63.6094 417.023C64.0208 416.602 64.3203 416.135 64.5078 415.625C64.7005 415.109 64.7969 414.565 64.7969 413.992V413.07H66.3594V413.992ZM66.7031 413.992C66.7031 414.539 66.7917 415.049 66.9687 415.523C67.1458 415.992 67.4219 416.414 67.7969 416.789C68.1771 417.159 68.6615 417.458 69.25 417.687L68.2109 419.211C67.513 418.935 66.9401 418.542 66.4922 418.031C66.0495 417.516 65.7214 416.917 65.5078 416.234C65.2995 415.552 65.1979 414.805 65.2031 413.992V413.07H66.7031V413.992ZM68.8828 413.859H62.5234V412.273H68.8828V413.859ZM74.4687 419.844H72.5703V411.234H74.4687V419.844ZM73.0937 416.289H70.8125V414.68H73.0937V416.289ZM71.4453 419.406H69.5547V411.477H71.4453V419.406ZM69.6094 420.055C70.6094 420.055 71.4792 420.164 72.2187 420.383C72.9635 420.596 73.5365 420.906 73.9375 421.312C74.3385 421.714 74.5391 422.19 74.5391 422.742C74.5391 423.294 74.3385 423.773 73.9375 424.18C73.5365 424.586 72.9635 424.896 72.2187 425.109C71.474 425.328 70.6042 425.437 69.6094 425.437C68.6094 425.437 67.7396 425.328 67 425.109C66.2604 424.896 65.6901 424.586 65.2891 424.18C64.888 423.773 64.6875 423.294 64.6875 422.742C64.6875 422.19 64.888 421.714 65.2891 421.312C65.6901 420.906 66.2604 420.596 67 420.383C67.7396 420.164 68.6094 420.055 69.6094 420.055ZM69.6094 421.57C68.9896 421.57 68.4609 421.615 68.0234 421.703C67.5911 421.786 67.2578 421.919 67.0234 422.102C66.7943 422.279 66.6823 422.492 66.6875 422.742C66.6823 423.003 66.7943 423.221 67.0234 423.398C67.2526 423.57 67.5833 423.701 68.0156 423.789C68.4479 423.872 68.9792 423.917 69.6094 423.922C70.2396 423.917 70.7708 423.872 71.2031 423.789C71.6354 423.701 71.9635 423.57 72.1875 423.398C72.4167 423.221 72.5339 423.003 72.5391 422.742C72.5339 422.492 72.4167 422.279 72.1875 422.102C71.9635 421.919 71.6302 421.786 71.1875 421.703C70.75 421.615 70.224 421.57 69.6094 421.57ZM87.9844 425.477H85.9609V411.203H87.9844V425.477ZM80.2578 412.211C80.9714 412.211 81.612 412.419 82.1797 412.836C82.7526 413.247 83.1979 413.839 83.5156 414.609C83.8385 415.375 84 416.266 84 417.281C84 418.302 83.8385 419.198 83.5156 419.969C83.1979 420.734 82.7526 421.323 82.1797 421.734C81.612 422.146 80.9714 422.352 80.2578 422.352C79.5339 422.357 78.8854 422.154 78.3125 421.742C77.7448 421.326 77.2995 420.734 76.9766 419.969C76.6536 419.198 76.4922 418.302 76.4922 417.281C76.4922 416.266 76.6536 415.375 76.9766 414.609C77.2995 413.839 77.7448 413.247 78.3125 412.836C78.8854 412.419 79.5339 412.211 80.2578 412.211ZM80.2578 414.016C79.888 414.01 79.5625 414.135 79.2812 414.391C79.0052 414.641 78.7917 415.013 78.6406 415.508C78.4948 415.997 78.4245 416.589 78.4297 417.281C78.4245 417.974 78.4948 418.565 78.6406 419.055C78.7917 419.544 79.0052 419.917 79.2812 420.172C79.5625 420.422 79.888 420.547 80.2578 420.547C80.6172 420.547 80.9349 420.422 81.2109 420.172C81.487 419.917 81.7005 419.544 81.8516 419.055C82.0026 418.565 82.0781 417.974 82.0781 417.281C82.0781 416.589 82.0026 415.997 81.8516 415.508C81.7005 415.018 81.487 414.646 81.2109 414.391C80.9349 414.135 80.6172 414.01 80.2578 414.016ZM100.484 412.898C100.479 413.628 100.26 414.292 99.8281 414.891C99.401 415.49 98.7656 415.99 97.9219 416.391C97.0781 416.792 96.0651 417.052 94.8828 417.172L94.1875 415.609C95.1667 415.516 95.9974 415.328 96.6797 415.047C97.3672 414.766 97.8776 414.437 98.2109 414.062C98.5495 413.687 98.7214 413.299 98.7266 412.898V412.492H100.484V412.898ZM101.453 412.898C101.453 413.305 101.622 413.695 101.961 414.07C102.305 414.445 102.82 414.773 103.508 415.055C104.195 415.331 105.036 415.516 106.031 415.609L105.312 417.172C104.13 417.052 103.115 416.794 102.266 416.398C101.422 415.997 100.779 415.497 100.336 414.898C99.8932 414.294 99.6693 413.628 99.6641 412.898V412.492H101.453V412.898ZM105.414 413.312H94.7891V411.734H105.414V413.312ZM106.586 419.734H93.6172V418.148H106.586V419.734ZM101.062 418.852H99.0859V416.273H101.062V418.852ZM105 425.437H103.016V422.344H95.0469V420.758H105V425.437ZM109.836 413.547H112.75V411.852H114.75V418.062H107.859V411.852H109.836V413.547ZM112.75 416.492V415.039H109.836V416.492H112.75ZM118.719 418.453H116.727V411.203H118.719V418.453ZM120.641 415.602H117.891V413.984H120.641V415.602ZM118.719 422.852H111.273V424.555H109.312V421.422H116.734V420.531H109.289V418.992H118.719V422.852ZM119.133 425.336H109.312V423.773H119.133V425.336Z" fill="#56555A"/> +<path d="M320.406 424.156C319.677 424.146 319.005 423.974 318.391 423.641C317.776 423.307 317.271 422.742 316.875 421.945C316.479 421.148 316.281 420.094 316.281 418.781C316.281 417.458 316.456 416.328 316.805 415.391C317.154 414.453 317.648 413.742 318.289 413.258C318.93 412.773 319.693 412.531 320.578 412.531C321.229 412.531 321.815 412.656 322.336 412.906C322.862 413.156 323.289 413.51 323.617 413.969C323.945 414.422 324.156 414.943 324.25 415.531H322.859C322.771 415.187 322.625 414.883 322.422 414.617C322.224 414.352 321.969 414.146 321.656 414C321.344 413.854 320.984 413.781 320.578 413.781C319.958 413.781 319.424 413.951 318.977 414.289C318.534 414.628 318.195 415.122 317.961 415.773C317.727 416.419 317.609 417.193 317.609 418.094H317.75C317.969 417.776 318.227 417.505 318.523 417.281C318.82 417.052 319.148 416.88 319.508 416.766C319.872 416.651 320.255 416.594 320.656 416.594C321.323 416.594 321.937 416.755 322.5 417.078C323.062 417.401 323.51 417.849 323.844 418.422C324.177 418.99 324.344 419.63 324.344 420.344C324.344 421.057 324.18 421.706 323.852 422.289C323.523 422.867 323.06 423.326 322.461 423.664C321.867 423.997 321.182 424.161 320.406 424.156ZM320.406 422.922C320.885 422.922 321.32 422.805 321.711 422.57C322.102 422.336 322.411 422.026 322.641 421.641C322.87 421.25 322.984 420.823 322.984 420.359C322.984 419.901 322.875 419.479 322.656 419.094C322.437 418.708 322.133 418.401 321.742 418.172C321.352 417.943 320.917 417.828 320.437 417.828C319.953 417.828 319.51 417.945 319.109 418.18C318.714 418.414 318.396 418.729 318.156 419.125C317.922 419.516 317.802 419.932 317.797 420.375C317.797 420.818 317.911 421.234 318.141 421.625C318.37 422.01 318.682 422.323 319.078 422.562C319.474 422.802 319.917 422.922 320.406 422.922ZM326 420.531L331.094 412.687H331.937V414.469H331.344L327.516 420.359V420.453H334.406V421.687H326V420.531ZM331.484 421.344V420.797V412.687H332.828V424H331.484V421.344ZM336.312 427.203H335.156L336.016 422.953H337.531L336.312 427.203ZM343.172 424.156C342.339 424.156 341.628 423.93 341.039 423.477C340.451 423.023 340 422.362 339.687 421.492C339.375 420.622 339.219 419.573 339.219 418.344C339.219 417.13 339.375 416.089 339.687 415.219C340 414.344 340.451 413.677 341.039 413.219C341.633 412.76 342.344 412.531 343.172 412.531C343.995 412.531 344.703 412.76 345.297 413.219C345.891 413.677 346.344 414.344 346.656 415.219C346.969 416.089 347.125 417.13 347.125 418.344C347.125 419.573 346.971 420.622 346.664 421.492C346.357 422.362 345.906 423.023 345.312 423.477C344.719 423.93 344.005 424.156 343.172 424.156ZM343.172 422.906C343.714 422.906 344.18 422.729 344.57 422.375C344.961 422.021 345.255 421.503 345.453 420.82C345.651 420.138 345.75 419.312 345.75 418.344C345.75 417.375 345.648 416.547 345.445 415.859C345.242 415.172 344.948 414.648 344.562 414.289C344.177 413.93 343.714 413.75 343.172 413.75C342.63 413.75 342.167 413.93 341.781 414.289C341.396 414.648 341.099 415.172 340.891 415.859C340.682 416.547 340.578 417.375 340.578 418.344C340.578 419.312 340.682 420.138 340.891 420.82C341.099 421.503 341.393 422.021 341.773 422.375C342.159 422.729 342.625 422.906 343.172 422.906ZM352.703 424.156C351.87 424.156 351.159 423.93 350.57 423.477C349.982 423.023 349.531 422.362 349.219 421.492C348.906 420.622 348.75 419.573 348.75 418.344C348.75 417.13 348.906 416.089 349.219 415.219C349.531 414.344 349.982 413.677 350.57 413.219C351.164 412.76 351.875 412.531 352.703 412.531C353.526 412.531 354.234 412.76 354.828 413.219C355.422 413.677 355.875 414.344 356.187 415.219C356.5 416.089 356.656 417.13 356.656 418.344C356.656 419.573 356.503 420.622 356.195 421.492C355.888 422.362 355.437 423.023 354.844 423.477C354.25 423.93 353.536 424.156 352.703 424.156ZM352.703 422.906C353.245 422.906 353.711 422.729 354.102 422.375C354.492 422.021 354.786 421.503 354.984 420.82C355.182 420.138 355.281 419.312 355.281 418.344C355.281 417.375 355.18 416.547 354.977 415.859C354.773 415.172 354.479 414.648 354.094 414.289C353.708 413.93 353.245 413.75 352.703 413.75C352.161 413.75 351.698 413.93 351.312 414.289C350.927 414.648 350.63 415.172 350.422 415.859C350.214 416.547 350.109 417.375 350.109 418.344C350.109 419.312 350.214 420.138 350.422 420.82C350.63 421.503 350.924 422.021 351.305 422.375C351.69 422.729 352.156 422.906 352.703 422.906ZM362.234 424.156C361.401 424.156 360.69 423.93 360.102 423.477C359.513 423.023 359.062 422.362 358.75 421.492C358.437 420.622 358.281 419.573 358.281 418.344C358.281 417.13 358.437 416.089 358.75 415.219C359.062 414.344 359.513 413.677 360.102 413.219C360.695 412.76 361.406 412.531 362.234 412.531C363.057 412.531 363.766 412.76 364.359 413.219C364.953 413.677 365.406 414.344 365.719 415.219C366.031 416.089 366.187 417.13 366.187 418.344C366.187 419.573 366.034 420.622 365.727 421.492C365.419 422.362 364.969 423.023 364.375 423.477C363.781 423.93 363.068 424.156 362.234 424.156ZM362.234 422.906C362.776 422.906 363.242 422.729 363.633 422.375C364.023 422.021 364.318 421.503 364.516 420.82C364.714 420.138 364.812 419.312 364.812 418.344C364.812 417.375 364.711 416.547 364.508 415.859C364.305 415.172 364.01 414.648 363.625 414.289C363.24 413.93 362.776 413.75 362.234 413.75C361.693 413.75 361.229 413.93 360.844 414.289C360.458 414.648 360.161 415.172 359.953 415.859C359.745 416.547 359.641 417.375 359.641 418.344C359.641 419.312 359.745 420.138 359.953 420.82C360.161 421.503 360.456 422.021 360.836 422.375C361.221 422.729 361.687 422.906 362.234 422.906Z" fill="#56555A"/> +<path d="M375.348 423.09H374.422V420.77H375.348V423.09ZM380.012 423.453H379.086V415.543H380.012V423.453ZM380.27 425.727H372.863V424.953H380.27V425.727ZM373.789 425.176H372.863V422.68H373.789V425.176ZM371.363 420.371C372.758 420.363 373.992 420.342 375.066 420.307C376.141 420.268 377.168 420.187 378.148 420.066L378.207 420.734C377.195 420.895 376.135 421 375.025 421.051C373.916 421.102 372.738 421.125 371.492 421.121L371.363 420.371ZM379.332 422.375H376.93V421.707H379.332V422.375ZM374.785 415.965C375.289 415.965 375.736 416.039 376.127 416.187C376.521 416.336 376.826 416.549 377.041 416.826C377.256 417.104 377.363 417.422 377.363 417.781C377.363 418.148 377.256 418.467 377.041 418.736C376.826 419.006 376.523 419.215 376.133 419.363C375.742 419.512 375.293 419.586 374.785 419.586C374.273 419.586 373.822 419.512 373.432 419.363C373.045 419.215 372.744 419.006 372.529 418.736C372.314 418.467 372.207 418.148 372.207 417.781C372.207 417.422 372.314 417.104 372.529 416.826C372.744 416.549 373.047 416.336 373.437 416.187C373.828 416.039 374.277 415.965 374.785 415.965ZM374.785 416.668C374.449 416.664 374.152 416.709 373.895 416.803C373.637 416.893 373.436 417.023 373.291 417.195C373.15 417.367 373.082 417.562 373.086 417.781C373.082 418.004 373.15 418.201 373.291 418.373C373.436 418.541 373.637 418.672 373.895 418.766C374.152 418.859 374.449 418.906 374.785 418.906C375.113 418.906 375.406 418.859 375.664 418.766C375.922 418.672 376.123 418.541 376.268 418.373C376.412 418.201 376.484 418.004 376.484 417.781C376.484 417.562 376.412 417.367 376.268 417.195C376.123 417.023 375.922 416.893 375.664 416.803C375.406 416.709 375.113 416.664 374.785 416.668Z" fill="#56555A"/> +<path d="M382 446H48C43.5817 446 40 449.582 40 454V478C40 482.418 43.5817 486 48 486H382C386.418 486 390 482.418 390 478V454C390 449.582 386.418 446 382 446Z" fill="#F9F8FD"/> +<path d="M61.4297 471.781H48.4297V470.172H61.4297V471.781ZM55.8828 470.57H53.9219V467.086H55.8828V470.57ZM51.8047 462.336H58V460.117H59.9844V467.531H49.8047V460.117H51.8047V462.336ZM58 465.937V463.914H51.8047V465.937H58ZM73.8359 467.398H63.7891V465.805H73.8359V467.398ZM75.2578 471.711H62.2578V470.07H75.2578V471.711ZM73.7344 462.016H65.7578V466.469H63.7891V460.406H73.7344V462.016ZM88.3984 473.437H86.5234V459.203H88.3984V473.437ZM83.8828 466.281H80.7734V464.695H83.8828V466.281ZM85.375 472.812H83.5V459.539H85.375V472.812ZM82.2969 460.906C82.2917 462.318 82.1224 463.596 81.7891 464.742C81.4609 465.888 80.9089 466.945 80.1328 467.914C79.362 468.878 78.3281 469.732 77.0312 470.477L75.9062 469.078C76.9844 468.437 77.849 467.737 78.5 466.977C79.1562 466.211 79.6302 465.367 79.9219 464.445C80.2135 463.523 80.362 462.479 80.3672 461.312V460.906H82.2969ZM81.0078 462.508H76.6875V460.906H81.0078V462.508ZM101.805 467.266H99.8125V459.234H101.805V467.266ZM101.805 473.281H92.2812V467.906H101.805V473.281ZM94.2422 471.68H99.8516V469.484H94.2422V471.68ZM94.0156 459.875C94.7448 459.875 95.4062 460.021 96 460.312C96.5937 460.599 97.0599 461.005 97.3984 461.531C97.737 462.052 97.9062 462.643 97.9062 463.305C97.9062 463.945 97.737 464.526 97.3984 465.047C97.0599 465.562 96.5937 465.969 96 466.266C95.4062 466.557 94.7448 466.703 94.0156 466.703C93.2812 466.703 92.6172 466.557 92.0234 466.266C91.4349 465.969 90.9714 465.562 90.6328 465.047C90.2943 464.526 90.125 463.945 90.125 463.305C90.125 462.643 90.2943 462.052 90.6328 461.531C90.9714 461.005 91.4349 460.599 92.0234 460.312C92.6172 460.021 93.2812 459.875 94.0156 459.875ZM94.0156 461.555C93.6354 461.555 93.2969 461.622 93 461.758C92.7083 461.893 92.4792 462.094 92.3125 462.359C92.151 462.625 92.0703 462.94 92.0703 463.305C92.0703 463.654 92.151 463.958 92.3125 464.219C92.4792 464.474 92.7083 464.672 93 464.812C93.2969 464.953 93.6354 465.023 94.0156 465.023C94.3854 465.023 94.7135 464.953 95 464.812C95.2917 464.672 95.5182 464.474 95.6797 464.219C95.8464 463.958 95.9297 463.654 95.9297 463.305C95.9297 462.94 95.849 462.625 95.6875 462.359C95.526 462.094 95.2995 461.893 95.0078 461.758C94.7161 461.622 94.3854 461.555 94.0156 461.555Z" fill="#56555A"/> +<path d="M316.359 468.531L321.453 460.687H322.297V462.469H321.703L317.875 468.359V468.453H324.766V469.687H316.359V468.531ZM321.844 469.344V468.797V460.687H323.187V472H321.844V469.344ZM330.328 472.156C329.495 472.156 328.784 471.93 328.195 471.477C327.607 471.023 327.156 470.362 326.844 469.492C326.531 468.622 326.375 467.573 326.375 466.344C326.375 465.13 326.531 464.089 326.844 463.219C327.156 462.344 327.607 461.677 328.195 461.219C328.789 460.76 329.5 460.531 330.328 460.531C331.151 460.531 331.859 460.76 332.453 461.219C333.047 461.677 333.5 462.344 333.812 463.219C334.125 464.089 334.281 465.13 334.281 466.344C334.281 467.573 334.128 468.622 333.82 469.492C333.513 470.362 333.062 471.023 332.469 471.477C331.875 471.93 331.161 472.156 330.328 472.156ZM330.328 470.906C330.87 470.906 331.336 470.729 331.727 470.375C332.117 470.021 332.411 469.503 332.609 468.82C332.807 468.138 332.906 467.312 332.906 466.344C332.906 465.375 332.805 464.547 332.602 463.859C332.398 463.172 332.104 462.648 331.719 462.289C331.333 461.93 330.87 461.75 330.328 461.75C329.786 461.75 329.323 461.93 328.937 462.289C328.552 462.648 328.255 463.172 328.047 463.859C327.839 464.547 327.734 465.375 327.734 466.344C327.734 467.312 327.839 468.138 328.047 468.82C328.255 469.503 328.549 470.021 328.93 470.375C329.315 470.729 329.781 470.906 330.328 470.906ZM336.312 475.203H335.156L336.016 470.953H337.531L336.312 475.203ZM343.172 472.156C342.339 472.156 341.628 471.93 341.039 471.477C340.451 471.023 340 470.362 339.687 469.492C339.375 468.622 339.219 467.573 339.219 466.344C339.219 465.13 339.375 464.089 339.687 463.219C340 462.344 340.451 461.677 341.039 461.219C341.633 460.76 342.344 460.531 343.172 460.531C343.995 460.531 344.703 460.76 345.297 461.219C345.891 461.677 346.344 462.344 346.656 463.219C346.969 464.089 347.125 465.13 347.125 466.344C347.125 467.573 346.971 468.622 346.664 469.492C346.357 470.362 345.906 471.023 345.312 471.477C344.719 471.93 344.005 472.156 343.172 472.156ZM343.172 470.906C343.714 470.906 344.18 470.729 344.57 470.375C344.961 470.021 345.255 469.503 345.453 468.82C345.651 468.138 345.75 467.312 345.75 466.344C345.75 465.375 345.648 464.547 345.445 463.859C345.242 463.172 344.948 462.648 344.562 462.289C344.177 461.93 343.714 461.75 343.172 461.75C342.63 461.75 342.167 461.93 341.781 462.289C341.396 462.648 341.099 463.172 340.891 463.859C340.682 464.547 340.578 465.375 340.578 466.344C340.578 467.312 340.682 468.138 340.891 468.82C341.099 469.503 341.393 470.021 341.773 470.375C342.159 470.729 342.625 470.906 343.172 470.906ZM352.703 472.156C351.87 472.156 351.159 471.93 350.57 471.477C349.982 471.023 349.531 470.362 349.219 469.492C348.906 468.622 348.75 467.573 348.75 466.344C348.75 465.13 348.906 464.089 349.219 463.219C349.531 462.344 349.982 461.677 350.57 461.219C351.164 460.76 351.875 460.531 352.703 460.531C353.526 460.531 354.234 460.76 354.828 461.219C355.422 461.677 355.875 462.344 356.187 463.219C356.5 464.089 356.656 465.13 356.656 466.344C356.656 467.573 356.503 468.622 356.195 469.492C355.888 470.362 355.437 471.023 354.844 471.477C354.25 471.93 353.536 472.156 352.703 472.156ZM352.703 470.906C353.245 470.906 353.711 470.729 354.102 470.375C354.492 470.021 354.786 469.503 354.984 468.82C355.182 468.138 355.281 467.312 355.281 466.344C355.281 465.375 355.18 464.547 354.977 463.859C354.773 463.172 354.479 462.648 354.094 462.289C353.708 461.93 353.245 461.75 352.703 461.75C352.161 461.75 351.698 461.93 351.312 462.289C350.927 462.648 350.63 463.172 350.422 463.859C350.214 464.547 350.109 465.375 350.109 466.344C350.109 467.312 350.214 468.138 350.422 468.82C350.63 469.503 350.924 470.021 351.305 470.375C351.69 470.729 352.156 470.906 352.703 470.906ZM362.234 472.156C361.401 472.156 360.69 471.93 360.102 471.477C359.513 471.023 359.062 470.362 358.75 469.492C358.437 468.622 358.281 467.573 358.281 466.344C358.281 465.13 358.437 464.089 358.75 463.219C359.062 462.344 359.513 461.677 360.102 461.219C360.695 460.76 361.406 460.531 362.234 460.531C363.057 460.531 363.766 460.76 364.359 461.219C364.953 461.677 365.406 462.344 365.719 463.219C366.031 464.089 366.187 465.13 366.187 466.344C366.187 467.573 366.034 468.622 365.727 469.492C365.419 470.362 364.969 471.023 364.375 471.477C363.781 471.93 363.068 472.156 362.234 472.156ZM362.234 470.906C362.776 470.906 363.242 470.729 363.633 470.375C364.023 470.021 364.318 469.503 364.516 468.82C364.714 468.138 364.812 467.312 364.812 466.344C364.812 465.375 364.711 464.547 364.508 463.859C364.305 463.172 364.01 462.648 363.625 462.289C363.24 461.93 362.776 461.75 362.234 461.75C361.693 461.75 361.229 461.93 360.844 462.289C360.458 462.648 360.161 463.172 359.953 463.859C359.745 464.547 359.641 465.375 359.641 466.344C359.641 467.312 359.745 468.138 359.953 468.82C360.161 469.503 360.456 470.021 360.836 470.375C361.221 470.729 361.687 470.906 362.234 470.906Z" fill="#56555A"/> +<path d="M375.348 471.09H374.422V468.77H375.348V471.09ZM380.012 471.453H379.086V463.543H380.012V471.453ZM380.27 473.727H372.863V472.953H380.27V473.727ZM373.789 473.176H372.863V470.68H373.789V473.176ZM371.363 468.371C372.758 468.363 373.992 468.342 375.066 468.307C376.141 468.268 377.168 468.187 378.148 468.066L378.207 468.734C377.195 468.895 376.135 469 375.025 469.051C373.916 469.102 372.738 469.125 371.492 469.121L371.363 468.371ZM379.332 470.375H376.93V469.707H379.332V470.375ZM374.785 463.965C375.289 463.965 375.736 464.039 376.127 464.187C376.521 464.336 376.826 464.549 377.041 464.826C377.256 465.104 377.363 465.422 377.363 465.781C377.363 466.148 377.256 466.467 377.041 466.736C376.826 467.006 376.523 467.215 376.133 467.363C375.742 467.512 375.293 467.586 374.785 467.586C374.273 467.586 373.822 467.512 373.432 467.363C373.045 467.215 372.744 467.006 372.529 466.736C372.314 466.467 372.207 466.148 372.207 465.781C372.207 465.422 372.314 465.104 372.529 464.826C372.744 464.549 373.047 464.336 373.437 464.187C373.828 464.039 374.277 463.965 374.785 463.965ZM374.785 464.668C374.449 464.664 374.152 464.709 373.895 464.803C373.637 464.893 373.436 465.023 373.291 465.195C373.15 465.367 373.082 465.562 373.086 465.781C373.082 466.004 373.15 466.201 373.291 466.373C373.436 466.541 373.637 466.672 373.895 466.766C374.152 466.859 374.449 466.906 374.785 466.906C375.113 466.906 375.406 466.859 375.664 466.766C375.922 466.672 376.123 466.541 376.268 466.373C376.412 466.201 376.484 466.004 376.484 465.781C376.484 465.562 376.412 465.367 376.268 465.195C376.123 465.023 375.922 464.893 375.664 464.803C375.406 464.709 375.113 464.664 374.785 464.668Z" fill="#56555A"/> +<path d="M382 494H48C43.5817 494 40 497.582 40 502V526C40 530.418 43.5817 534 48 534H382C386.418 534 390 530.418 390 526V502C390 497.582 386.418 494 382 494Z" fill="#F9F8FD"/> +<mask id="mask4_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="48" y="502" width="60" height="25"> +<path d="M108 502H48V527H108V502Z" fill="white"/> +<path d="M48 502H108V526H48V502Z" fill="black"/> +</mask> +<g mask="url(#mask4_1835_8259)"> +<path d="M108 525H48V527H108V525Z" fill="#B575FF"/> +</g> +<path d="M53.5156 511.086C53.5104 512.206 53.3516 513.273 53.0391 514.289C52.7266 515.305 52.2656 516.206 51.6562 516.992C51.0469 517.773 50.3125 518.365 49.4531 518.766L48.3125 517.195C49.0781 516.852 49.7292 516.357 50.2656 515.711C50.8073 515.06 51.2135 514.336 51.4844 513.539C51.7604 512.737 51.8984 511.919 51.8984 511.086V509.43H53.5156V511.086ZM53.9297 511.086C53.9297 511.883 54.0651 512.659 54.3359 513.414C54.6068 514.164 55.0078 514.844 55.5391 515.453C56.0755 516.057 56.7292 516.518 57.5 516.836L56.4219 518.398C55.5417 518.029 54.7969 517.474 54.1875 516.734C53.5781 515.99 53.1198 515.133 52.8125 514.164C52.5052 513.195 52.3542 512.169 52.3594 511.086V509.43H53.9297V511.086ZM56.9141 510.219H48.8828V508.594H56.9141V510.219ZM60.3281 521.437H58.3047V507.203H60.3281V521.437ZM69.7109 516.5H67.75V514.43H69.7109V516.5ZM75.1953 514.727H62.2812V513.273H75.1953V514.727ZM69.7031 508.922H67.7266V507.203H69.7031V508.922ZM69.3516 509.289C69.3516 509.977 69.1224 510.578 68.6641 511.094C68.2057 511.609 67.5234 512.023 66.6172 512.336C65.7161 512.643 64.6198 512.831 63.3281 512.898L62.7891 511.43C63.8828 511.378 64.7891 511.25 65.5078 511.047C66.2318 510.839 66.7604 510.583 67.0937 510.281C67.4323 509.979 67.6016 509.648 67.6016 509.289V509H69.3516V509.289ZM69.8359 509.289C69.8307 509.648 69.9974 509.979 70.3359 510.281C70.6745 510.583 71.2057 510.839 71.9297 511.047C72.6536 511.25 73.5677 511.378 74.6719 511.43L74.0937 512.898C72.8073 512.831 71.7135 512.641 70.8125 512.328C69.9167 512.016 69.237 511.604 68.7734 511.094C68.3099 510.578 68.0807 509.977 68.0859 509.289V509H69.8359V509.289ZM73.9687 509.805H63.5V508.328H73.9687V509.805ZM73.6406 519.086H65.7187V520.469H63.7578V517.75H71.6719V517.055H63.75V515.625H73.6406V519.086ZM74.0156 521.336H63.7578V519.875H74.0156V521.336ZM92.0469 521.437H90.125V507.203H92.0469V521.437ZM90.6484 514.328H88.2344V512.711H90.6484V514.328ZM88.7969 520.75H86.9297V507.461H88.7969V520.75ZM82.3516 517.008H80.3594V508.797H82.3516V517.008ZM81.3125 516.242C82.1354 516.242 82.9349 516.214 83.7109 516.156C84.4922 516.099 85.2943 515.99 86.1172 515.828L86.3281 517.547C85.4271 517.703 84.5651 517.815 83.7422 517.883C82.9245 517.945 82.1146 517.974 81.3125 517.969H80.3594V516.242H81.3125ZM104.211 510.734H99.9766V509.125H104.211V510.734ZM104.211 513.82H99.9766V512.227H104.211V513.82ZM105.594 521.437H103.609V517.836H95.8281V516.258H105.594V521.437ZM105.594 515.625H103.609V507.203H105.594V515.625ZM97.5781 507.977C98.276 507.977 98.9115 508.125 99.4844 508.422C100.062 508.719 100.516 509.135 100.844 509.672C101.172 510.203 101.338 510.799 101.344 511.461C101.338 512.138 101.172 512.745 100.844 513.281C100.516 513.818 100.065 514.237 99.4922 514.539C98.9193 514.841 98.2812 514.992 97.5781 514.992C96.8646 514.992 96.2187 514.841 95.6406 514.539C95.0677 514.237 94.6146 513.818 94.2812 513.281C93.9531 512.74 93.7891 512.133 93.7891 511.461C93.7891 510.799 93.9531 510.203 94.2812 509.672C94.6146 509.135 95.0677 508.719 95.6406 508.422C96.2187 508.125 96.8646 507.977 97.5781 507.977ZM97.5781 509.664C97.2083 509.664 96.8802 509.734 96.5937 509.875C96.3073 510.016 96.0833 510.224 95.9219 510.5C95.7604 510.776 95.6797 511.096 95.6797 511.461C95.6797 511.836 95.7604 512.161 95.9219 512.437C96.0833 512.714 96.3073 512.927 96.5937 513.078C96.8802 513.229 97.2083 513.305 97.5781 513.305C97.9323 513.305 98.25 513.229 98.5312 513.078C98.8125 512.927 99.0339 512.714 99.1953 512.437C99.3568 512.161 99.4375 511.836 99.4375 511.461C99.4375 511.096 99.3568 510.776 99.1953 510.5C99.0339 510.224 98.8099 510.016 98.5234 509.875C98.2422 509.734 97.9271 509.664 97.5781 509.664Z" fill="#B2B1B6"/> +<path d="M361.766 520.156C360.932 520.156 360.221 519.93 359.633 519.477C359.044 519.023 358.594 518.362 358.281 517.492C357.969 516.622 357.812 515.573 357.812 514.344C357.812 513.125 357.969 512.081 358.281 511.211C358.594 510.341 359.047 509.677 359.641 509.219C360.234 508.76 360.943 508.531 361.766 508.531C362.589 508.531 363.297 508.76 363.891 509.219C364.484 509.677 364.937 510.341 365.25 511.211C365.562 512.081 365.719 513.125 365.719 514.344C365.719 515.573 365.565 516.622 365.258 517.492C364.951 518.362 364.5 519.023 363.906 519.477C363.312 519.93 362.599 520.156 361.766 520.156ZM361.766 518.906C362.307 518.906 362.771 518.729 363.156 518.375C363.542 518.021 363.836 517.503 364.039 516.82C364.242 516.138 364.344 515.312 364.344 514.344C364.344 513.375 364.242 512.547 364.039 511.859C363.836 511.172 363.542 510.648 363.156 510.289C362.771 509.93 362.307 509.75 361.766 509.75C361.224 509.75 360.76 509.93 360.375 510.289C359.99 510.648 359.693 511.172 359.484 511.859C359.276 512.547 359.172 513.375 359.172 514.344C359.172 515.312 359.273 516.138 359.477 516.82C359.68 517.503 359.977 518.021 360.367 518.375C360.758 518.729 361.224 518.906 361.766 518.906Z" fill="#B2B1B6"/> +<path d="M375.348 519.09H374.422V516.77H375.348V519.09ZM380.012 519.453H379.086V511.543H380.012V519.453ZM380.27 521.727H372.863V520.953H380.27V521.727ZM373.789 521.176H372.863V518.68H373.789V521.176ZM371.363 516.371C372.758 516.363 373.992 516.342 375.066 516.307C376.141 516.268 377.168 516.187 378.148 516.066L378.207 516.734C377.195 516.895 376.135 517 375.025 517.051C373.916 517.102 372.738 517.125 371.492 517.121L371.363 516.371ZM379.332 518.375H376.93V517.707H379.332V518.375ZM374.785 511.965C375.289 511.965 375.736 512.039 376.127 512.187C376.521 512.336 376.826 512.549 377.041 512.826C377.256 513.104 377.363 513.422 377.363 513.781C377.363 514.148 377.256 514.467 377.041 514.736C376.826 515.006 376.523 515.215 376.133 515.363C375.742 515.512 375.293 515.586 374.785 515.586C374.273 515.586 373.822 515.512 373.432 515.363C373.045 515.215 372.744 515.006 372.529 514.736C372.314 514.467 372.207 514.148 372.207 513.781C372.207 513.422 372.314 513.104 372.529 512.826C372.744 512.549 373.047 512.336 373.437 512.187C373.828 512.039 374.277 511.965 374.785 511.965ZM374.785 512.668C374.449 512.664 374.152 512.709 373.895 512.803C373.637 512.893 373.436 513.023 373.291 513.195C373.15 513.367 373.082 513.562 373.086 513.781C373.082 514.004 373.15 514.201 373.291 514.373C373.436 514.541 373.637 514.672 373.895 514.766C374.152 514.859 374.449 514.906 374.785 514.906C375.113 514.906 375.406 514.859 375.664 514.766C375.922 514.672 376.123 514.541 376.268 514.373C376.412 514.201 376.484 514.004 376.484 513.781C376.484 513.562 376.412 513.367 376.268 513.195C376.123 513.023 375.922 512.893 375.664 512.803C375.406 512.709 375.113 512.664 374.785 512.668Z" fill="#56555A"/> +<path d="M58.0488 551.953H48.3223V550.764H58.0488V551.953ZM53.9062 551.314H52.4238V549.732H53.9062V551.314ZM53.9062 547.014H52.4238V545.443H53.9062V547.014ZM53.6426 547.277C53.6426 547.82 53.4687 548.303 53.1211 548.725C52.7773 549.143 52.2715 549.482 51.6035 549.744C50.9355 550.006 50.127 550.17 49.1777 550.236L48.7207 549.111C49.5371 549.057 50.2168 548.939 50.7598 548.76C51.3027 548.576 51.6992 548.357 51.9492 548.104C52.2031 547.85 52.3301 547.574 52.3301 547.277V547.066H53.6426V547.277ZM54.0059 547.277C54.002 547.57 54.127 547.846 54.3809 548.104C54.6348 548.357 55.0312 548.576 55.5703 548.76C56.1133 548.939 56.793 549.057 57.6094 549.111L57.1582 550.236C56.209 550.17 55.4004 550.006 54.7324 549.744C54.0645 549.482 53.5566 549.143 53.209 548.725C52.8613 548.303 52.6895 547.82 52.6934 547.277V547.066H54.0059V547.277ZM57.1055 547.547H49.2539V546.363H57.1055V547.547ZM53.168 552.451C53.9453 552.451 54.6113 552.521 55.166 552.662C55.7207 552.803 56.1445 553.008 56.4375 553.277C56.7305 553.547 56.8789 553.875 56.8828 554.262C56.8789 554.652 56.7305 554.982 56.4375 555.252C56.1445 555.525 55.7207 555.73 55.166 555.867C54.6113 556.008 53.9453 556.078 53.168 556.078C52.3828 556.078 51.7109 556.008 51.1523 555.867C50.5977 555.73 50.1719 555.525 49.875 555.252C49.5781 554.982 49.4297 554.652 49.4297 554.262C49.4297 553.875 49.5781 553.547 49.875 553.277C50.1719 553.008 50.5977 552.803 51.1523 552.662C51.7109 552.521 52.3828 552.451 53.168 552.451ZM53.168 553.559C52.6641 553.555 52.248 553.58 51.9199 553.635C51.5957 553.686 51.3516 553.764 51.1875 553.869C51.0273 553.971 50.9492 554.102 50.9531 554.262C50.9492 554.426 51.0273 554.561 51.1875 554.666C51.3516 554.768 51.5957 554.844 51.9199 554.895C52.248 554.945 52.6641 554.971 53.168 554.971C53.6602 554.971 54.0684 554.945 54.3926 554.895C54.7207 554.844 54.9668 554.768 55.1309 554.666C55.2949 554.561 55.377 554.426 55.377 554.262C55.377 554.102 55.2949 553.971 55.1309 553.869C54.9668 553.764 54.7207 553.686 54.3926 553.635C54.0684 553.58 53.6602 553.555 53.168 553.559ZM61.1836 546.053C61.6523 546.053 62.0742 546.164 62.4492 546.387C62.8242 546.605 63.1172 546.914 63.3281 547.312C63.543 547.707 63.6504 548.156 63.6504 548.66C63.6504 549.168 63.543 549.617 63.3281 550.008C63.1172 550.398 62.8242 550.703 62.4492 550.922C62.0742 551.141 61.6523 551.25 61.1836 551.25C60.7148 551.25 60.2949 551.141 59.9238 550.922C59.5527 550.703 59.2617 550.398 59.0508 550.008C58.8437 549.617 58.7402 549.168 58.7402 548.66C58.7402 548.16 58.8437 547.711 59.0508 547.312C59.2617 546.914 59.5527 546.605 59.9238 546.387C60.2949 546.164 60.7148 546.053 61.1836 546.053ZM61.1836 547.33C60.9648 547.33 60.7715 547.383 60.6035 547.488C60.4355 547.59 60.3047 547.742 60.2109 547.945C60.1172 548.145 60.0723 548.383 60.0762 548.66C60.0723 548.937 60.1172 549.178 60.2109 549.381C60.3047 549.58 60.4355 549.734 60.6035 549.844C60.7715 549.953 60.9648 550.008 61.1836 550.008C61.3984 550.008 61.5898 549.953 61.7578 549.844C61.9297 549.734 62.0605 549.58 62.1504 549.381C62.2441 549.178 62.291 548.937 62.291 548.66C62.291 548.383 62.2441 548.145 62.1504 547.945C62.0605 547.742 61.9316 547.59 61.7637 547.488C61.5957 547.383 61.4023 547.33 61.1836 547.33ZM67.8516 551.795H66.4277V545.426H67.8516V551.795ZM66.832 549.205H65.1035V548.01H66.832V549.205ZM65.5605 551.736H64.166V545.607H65.5605V551.736ZM67.8516 556.078H66.3691V553.453H60.4805V552.264H67.8516V556.078Z" fill="#56555A"/> +<path d="M327.797 555H326.73V547.617H326.684L324.621 548.988V547.922L326.73 546.516H327.797V555ZM332.836 555.117C332.211 555.117 331.678 554.947 331.236 554.607C330.795 554.268 330.457 553.771 330.223 553.119C329.988 552.467 329.871 551.68 329.871 550.758C329.871 549.848 329.988 549.066 330.223 548.414C330.457 547.758 330.795 547.258 331.236 546.914C331.682 546.57 332.215 546.398 332.836 546.398C333.453 546.398 333.984 546.57 334.43 546.914C334.875 547.258 335.215 547.758 335.449 548.414C335.684 549.066 335.801 549.848 335.801 550.758C335.801 551.68 335.686 552.467 335.455 553.119C335.225 553.771 334.887 554.268 334.441 554.607C333.996 554.947 333.461 555.117 332.836 555.117ZM332.836 554.18C333.242 554.18 333.592 554.047 333.885 553.781C334.178 553.516 334.398 553.127 334.547 552.615C334.695 552.104 334.77 551.484 334.77 550.758C334.77 550.031 334.693 549.41 334.541 548.895C334.389 548.379 334.168 547.986 333.879 547.717C333.59 547.447 333.242 547.312 332.836 547.312C332.43 547.312 332.082 547.447 331.793 547.717C331.504 547.986 331.281 548.379 331.125 548.895C330.969 549.41 330.891 550.031 330.891 550.758C330.891 551.484 330.969 552.104 331.125 552.615C331.281 553.127 331.502 553.516 331.787 553.781C332.076 554.047 332.426 554.18 332.836 554.18ZM336.996 552.398L340.816 546.516H341.449V547.852H341.004L338.133 552.27V552.34H343.301V553.266H336.996V552.398ZM341.109 553.008V552.598V546.516H342.117V555H341.109V553.008ZM344.73 557.402H343.863L344.508 554.215H345.645L344.73 557.402ZM349.875 555.117C349.25 555.117 348.717 554.947 348.275 554.607C347.834 554.268 347.496 553.771 347.262 553.119C347.027 552.467 346.91 551.68 346.91 550.758C346.91 549.848 347.027 549.066 347.262 548.414C347.496 547.758 347.834 547.258 348.275 546.914C348.721 546.57 349.254 546.398 349.875 546.398C350.492 546.398 351.023 546.57 351.469 546.914C351.914 547.258 352.254 547.758 352.488 548.414C352.723 549.066 352.84 549.848 352.84 550.758C352.84 551.68 352.725 552.467 352.494 553.119C352.264 553.771 351.926 554.268 351.48 554.607C351.035 554.947 350.5 555.117 349.875 555.117ZM349.875 554.18C350.281 554.18 350.631 554.047 350.924 553.781C351.217 553.516 351.437 553.127 351.586 552.615C351.734 552.104 351.809 551.484 351.809 550.758C351.809 550.031 351.732 549.41 351.58 548.895C351.428 548.379 351.207 547.986 350.918 547.717C350.629 547.447 350.281 547.312 349.875 547.312C349.469 547.312 349.121 547.447 348.832 547.717C348.543 547.986 348.32 548.379 348.164 548.895C348.008 549.41 347.93 550.031 347.93 550.758C347.93 551.484 348.008 552.104 348.164 552.615C348.32 553.127 348.541 553.516 348.826 553.781C349.115 554.047 349.465 554.18 349.875 554.18ZM357.023 555.117C356.398 555.117 355.865 554.947 355.424 554.607C354.982 554.268 354.645 553.771 354.41 553.119C354.176 552.467 354.059 551.68 354.059 550.758C354.059 549.848 354.176 549.066 354.41 548.414C354.645 547.758 354.982 547.258 355.424 546.914C355.869 546.57 356.402 546.398 357.023 546.398C357.641 546.398 358.172 546.57 358.617 546.914C359.062 547.258 359.402 547.758 359.637 548.414C359.871 549.066 359.988 549.848 359.988 550.758C359.988 551.68 359.873 552.467 359.643 553.119C359.412 553.771 359.074 554.268 358.629 554.607C358.184 554.947 357.648 555.117 357.023 555.117ZM357.023 554.18C357.43 554.18 357.779 554.047 358.072 553.781C358.365 553.516 358.586 553.127 358.734 552.615C358.883 552.104 358.957 551.484 358.957 550.758C358.957 550.031 358.881 549.41 358.729 548.895C358.576 548.379 358.355 547.986 358.066 547.717C357.777 547.447 357.43 547.312 357.023 547.312C356.617 547.312 356.27 547.447 355.98 547.717C355.691 547.986 355.469 548.379 355.312 548.895C355.156 549.41 355.078 550.031 355.078 550.758C355.078 551.484 355.156 552.104 355.312 552.615C355.469 553.127 355.689 553.516 355.975 553.781C356.264 554.047 356.613 554.18 357.023 554.18ZM364.172 555.117C363.547 555.117 363.014 554.947 362.572 554.607C362.131 554.268 361.793 553.771 361.559 553.119C361.324 552.467 361.207 551.68 361.207 550.758C361.207 549.848 361.324 549.066 361.559 548.414C361.793 547.758 362.131 547.258 362.572 546.914C363.018 546.57 363.551 546.398 364.172 546.398C364.789 546.398 365.32 546.57 365.766 546.914C366.211 547.258 366.551 547.758 366.785 548.414C367.02 549.066 367.137 549.848 367.137 550.758C367.137 551.68 367.021 552.467 366.791 553.119C366.561 553.771 366.223 554.268 365.777 554.607C365.332 554.947 364.797 555.117 364.172 555.117ZM364.172 554.18C364.578 554.18 364.928 554.047 365.221 553.781C365.514 553.516 365.734 553.127 365.883 552.615C366.031 552.104 366.105 551.484 366.105 550.758C366.105 550.031 366.029 549.41 365.877 548.895C365.725 548.379 365.504 547.986 365.215 547.717C364.926 547.447 364.578 547.312 364.172 547.312C363.766 547.312 363.418 547.447 363.129 547.717C362.84 547.986 362.617 548.379 362.461 548.895C362.305 549.41 362.227 550.031 362.227 550.758C362.227 551.484 362.305 552.104 362.461 552.615C362.617 553.127 362.838 553.516 363.123 553.781C363.412 554.047 363.762 554.18 364.172 554.18ZM375.105 553.09H374.18V550.77H375.105V553.09ZM379.77 553.453H378.844V545.543H379.77V553.453ZM380.027 555.727H372.621V554.953H380.027V555.727ZM373.547 555.176H372.621V552.68H373.547V555.176ZM371.121 550.371C372.516 550.363 373.75 550.342 374.824 550.307C375.898 550.268 376.926 550.187 377.906 550.066L377.965 550.734C376.953 550.895 375.893 551 374.783 551.051C373.674 551.102 372.496 551.125 371.25 551.121L371.121 550.371ZM379.09 552.375H376.687V551.707H379.09V552.375ZM374.543 545.965C375.047 545.965 375.494 546.039 375.885 546.187C376.279 546.336 376.584 546.549 376.799 546.826C377.014 547.104 377.121 547.422 377.121 547.781C377.121 548.148 377.014 548.467 376.799 548.736C376.584 549.006 376.281 549.215 375.891 549.363C375.5 549.512 375.051 549.586 374.543 549.586C374.031 549.586 373.58 549.512 373.189 549.363C372.803 549.215 372.502 549.006 372.287 548.736C372.072 548.467 371.965 548.148 371.965 547.781C371.965 547.422 372.072 547.104 372.287 546.826C372.502 546.549 372.805 546.336 373.195 546.187C373.586 546.039 374.035 545.965 374.543 545.965ZM374.543 546.668C374.207 546.664 373.91 546.709 373.652 546.803C373.395 546.893 373.193 547.023 373.049 547.195C372.908 547.367 372.84 547.562 372.844 547.781C372.84 548.004 372.908 548.201 373.049 548.373C373.193 548.541 373.395 548.672 373.652 548.766C373.91 548.859 374.207 548.906 374.543 548.906C374.871 548.906 375.164 548.859 375.422 548.766C375.68 548.672 375.881 548.541 376.025 548.373C376.17 548.201 376.242 548.004 376.242 547.781C376.242 547.562 376.17 547.367 376.025 547.195C375.881 547.023 375.68 546.893 375.422 546.803C375.164 546.709 374.871 546.664 374.543 546.668Z" fill="#B2B1B6"/> +<path d="M199 584H44C37.3726 584 32 589.373 32 596V612C32 618.627 37.3726 624 44 624H199C205.627 624 211 618.627 211 612V596C211 589.373 205.627 584 199 584Z" fill="#E7E6EB"/> +<path d="M88.6328 607.453H86.6406V597.234H88.6328V607.453ZM89.0234 611.195H79.1094V609.586H89.0234V611.195ZM81.125 610.242H79.1094V606.43H81.125V610.242ZM80.8437 598.133C81.5625 598.133 82.2187 598.286 82.8125 598.594C83.4115 598.901 83.8802 599.328 84.2187 599.875C84.5625 600.422 84.7344 601.034 84.7344 601.711C84.7344 602.404 84.5625 603.026 84.2187 603.578C83.8802 604.125 83.4141 604.555 82.8203 604.867C82.2266 605.174 81.5677 605.328 80.8437 605.328C80.1198 605.328 79.4609 605.174 78.8672 604.867C78.2786 604.555 77.8125 604.125 77.4687 603.578C77.125 603.026 76.9531 602.404 76.9531 601.711C76.9531 601.034 77.125 600.422 77.4687 599.875C77.8125 599.328 78.2786 598.901 78.8672 598.594C79.4609 598.286 80.1198 598.133 80.8437 598.133ZM80.8437 599.867C80.474 599.867 80.1406 599.943 79.8437 600.094C79.5521 600.24 79.3203 600.453 79.1484 600.734C78.9818 601.01 78.8984 601.336 78.8984 601.711C78.8984 602.102 78.9818 602.437 79.1484 602.719C79.3203 603 79.5521 603.216 79.8437 603.367C80.1406 603.518 80.474 603.591 80.8437 603.586C81.2083 603.591 81.5339 603.518 81.8203 603.367C82.112 603.216 82.3411 603 82.5078 602.719C82.6745 602.437 82.7578 602.102 82.7578 601.711C82.7578 601.336 82.6745 601.01 82.5078 600.734C82.3411 600.453 82.112 600.24 81.8203 600.094C81.5286 599.943 81.2031 599.867 80.8437 599.867ZM96.3203 607.633H94.3125V604.492H96.3203V607.633ZM102.609 607.977H100.609V597.234H102.609V607.977ZM102.922 611.195H92.3125V609.586H102.922V611.195ZM94.3203 610.016H92.3125V606.945H94.3203V610.016ZM90.5078 603.539C92.4036 603.523 94.0703 603.49 95.5078 603.437C96.9453 603.38 98.3255 603.268 99.6484 603.102L99.75 604.531C98.375 604.76 96.9349 604.917 95.4297 605C93.9297 605.078 92.3672 605.115 90.7422 605.109L90.5078 603.539ZM101.063 606.844H97.8906V605.484H101.063V606.844ZM95.1328 597.711C95.8151 597.711 96.4271 597.818 96.9687 598.031C97.5104 598.245 97.9323 598.547 98.2344 598.937C98.5365 599.323 98.6875 599.763 98.6875 600.258C98.6875 600.763 98.5365 601.203 98.2344 601.578C97.9323 601.953 97.5104 602.247 96.9687 602.461C96.4323 602.669 95.8203 602.773 95.1328 602.773C94.4349 602.773 93.8151 602.669 93.2734 602.461C92.737 602.247 92.3177 601.953 92.0156 601.578C91.7135 601.203 91.5625 600.763 91.5625 600.258C91.5625 599.763 91.7135 599.32 92.0156 598.93C92.3177 598.539 92.7396 598.24 93.2812 598.031C93.8229 597.818 94.4401 597.711 95.1328 597.711ZM95.1328 599.172C94.7943 599.172 94.5 599.214 94.25 599.297C94 599.38 93.8021 599.505 93.6562 599.672C93.5156 599.833 93.4479 600.029 93.4531 600.258C93.4479 600.487 93.5156 600.682 93.6562 600.844C93.8021 601.005 94 601.128 94.25 601.211C94.5 601.294 94.7943 601.336 95.1328 601.336C95.4609 601.336 95.7474 601.294 95.9922 601.211C96.2422 601.128 96.4375 601.005 96.5781 600.844C96.7187 600.682 96.7891 600.487 96.7891 600.258C96.7891 600.034 96.7187 599.839 96.5781 599.672C96.4375 599.505 96.2422 599.38 95.9922 599.297C95.7474 599.214 95.4609 599.172 95.1328 599.172ZM118.789 601.219H115.125V599.602H118.789V601.219ZM118.859 604.25H115.125V602.648H118.859V604.25ZM120.078 607.719H118.094V597.234H120.078V607.719ZM120.383 611.195H110.609V609.586H120.383V611.195ZM112.625 610.5H110.609V606.672H112.625V610.5ZM110.703 600.336H113.5V598.164H115.477V605.477H108.695V598.164H110.703V600.336ZM113.5 603.898V601.859H110.703V603.898H113.5ZM134.922 605.508H121.93V603.93H134.922V605.508ZM129.398 604.555H127.445V601.789H129.398V604.555ZM133.437 602.711H123.5V601.148H133.437V602.711ZM133.359 599.398H125.477V602.172H123.5V597.844H133.359V599.398ZM128.391 606.211C129.417 606.211 130.299 606.315 131.039 606.523C131.779 606.727 132.346 607.026 132.742 607.422C133.138 607.812 133.339 608.286 133.344 608.844C133.339 609.396 133.138 609.865 132.742 610.25C132.352 610.641 131.784 610.937 131.039 611.141C130.299 611.349 129.417 611.456 128.391 611.461C127.354 611.456 126.464 611.349 125.719 611.141C124.974 610.937 124.401 610.641 124 610.25C123.604 609.859 123.406 609.391 123.406 608.844C123.406 608.286 123.604 607.812 124 607.422C124.401 607.026 124.974 606.727 125.719 606.523C126.464 606.315 127.354 606.211 128.391 606.211ZM128.391 607.734C127.729 607.734 127.18 607.776 126.742 607.859C126.31 607.937 125.982 608.06 125.758 608.227C125.539 608.393 125.432 608.599 125.437 608.844C125.432 609.094 125.539 609.299 125.758 609.461C125.982 609.622 126.31 609.742 126.742 609.82C127.18 609.898 127.729 609.937 128.391 609.937C129.042 609.937 129.583 609.898 130.016 609.82C130.453 609.742 130.781 609.622 131 609.461C131.224 609.299 131.336 609.094 131.336 608.844C131.336 608.604 131.224 608.401 131 608.234C130.781 608.062 130.453 607.937 130.016 607.859C129.578 607.776 129.036 607.734 128.391 607.734ZM146.906 611.453H144.93V606.297H146.906V611.453ZM152.43 607.359H139.461V605.727H152.43V607.359ZM146.68 600.109C146.68 600.917 146.448 601.664 145.984 602.352C145.526 603.034 144.854 603.607 143.969 604.07C143.089 604.534 142.044 604.836 140.836 604.977L140.109 603.422C141.125 603.297 141.997 603.06 142.727 602.711C143.456 602.362 144.005 601.958 144.375 601.5C144.745 601.042 144.93 600.578 144.93 600.109V599.75H146.68V600.109ZM146.93 600.109C146.93 600.568 147.112 601.026 147.477 601.484C147.846 601.943 148.393 602.349 149.117 602.703C149.846 603.057 150.716 603.297 151.727 603.422L151.008 604.977C149.805 604.836 148.76 604.529 147.875 604.055C146.995 603.576 146.323 602.995 145.859 602.312C145.401 601.625 145.172 600.891 145.172 600.109V599.75H146.93V600.109ZM151.234 600.422H140.633V598.852H151.234V600.422ZM146.906 599.391H144.93V597.234H146.906V599.391ZM164.5 611.414H162.5V597.203H164.5V611.414ZM166.508 604.312H163.984V602.672H166.508V604.312ZM160.703 598.672C160.698 600.151 160.484 601.518 160.062 602.773C159.646 604.029 158.961 605.182 158.008 606.234C157.055 607.286 155.805 608.193 154.258 608.953L153.133 607.43C154.404 606.789 155.453 606.062 156.281 605.25C157.109 604.432 157.727 603.513 158.133 602.492C158.539 601.466 158.745 600.312 158.75 599.031V598.672H160.703ZM159.75 600.305H153.93V598.672H159.75V600.305Z" fill="#56555A"/> +<path d="M386 584H231C224.373 584 219 589.373 219 596V612C219 618.627 224.373 624 231 624H386C392.627 624 398 618.627 398 612V596C398 589.373 392.627 584 386 584Z" fill="#B575FF"/> +<path d="M268.828 601.086C268.823 602.206 268.664 603.273 268.352 604.289C268.039 605.305 267.578 606.206 266.969 606.992C266.359 607.773 265.625 608.365 264.766 608.766L263.625 607.195C264.391 606.852 265.042 606.357 265.578 605.711C266.12 605.06 266.526 604.336 266.797 603.539C267.073 602.737 267.211 601.919 267.211 601.086V599.43H268.828V601.086ZM269.242 601.086C269.242 601.883 269.378 602.659 269.648 603.414C269.919 604.164 270.32 604.844 270.852 605.453C271.388 606.057 272.042 606.518 272.812 606.836L271.734 608.398C270.854 608.029 270.109 607.474 269.5 606.734C268.891 605.99 268.432 605.133 268.125 604.164C267.818 603.195 267.667 602.169 267.672 601.086V599.43H269.242V601.086ZM272.227 600.219H264.195V598.594H272.227V600.219ZM275.641 611.437H273.617V597.203H275.641V611.437ZM285.023 606.5H283.062V604.43H285.023V606.5ZM290.508 604.727H277.594V603.273H290.508V604.727ZM285.016 598.922H283.039V597.203H285.016V598.922ZM284.664 599.289C284.664 599.977 284.435 600.578 283.977 601.094C283.518 601.609 282.836 602.023 281.93 602.336C281.029 602.643 279.932 602.831 278.641 602.898L278.102 601.43C279.195 601.378 280.102 601.25 280.82 601.047C281.544 600.839 282.073 600.583 282.406 600.281C282.745 599.979 282.914 599.648 282.914 599.289V599H284.664V599.289ZM285.148 599.289C285.143 599.648 285.31 599.979 285.648 600.281C285.987 600.583 286.518 600.839 287.242 601.047C287.966 601.25 288.88 601.378 289.984 601.43L289.406 602.898C288.12 602.831 287.026 602.641 286.125 602.328C285.229 602.016 284.549 601.604 284.086 601.094C283.622 600.578 283.393 599.977 283.398 599.289V599H285.148V599.289ZM289.281 599.805H278.812V598.328H289.281V599.805ZM288.953 609.086H281.031V610.469H279.07V607.75H286.984V607.055H279.062V605.625H288.953V609.086ZM289.328 611.336H279.07V609.875H289.328V611.336ZM307.359 611.437H305.437V597.203H307.359V611.437ZM305.961 604.328H303.547V602.711H305.961V604.328ZM304.109 610.75H302.242V597.461H304.109V610.75ZM297.664 607.008H295.672V598.797H297.664V607.008ZM296.625 606.242C297.448 606.242 298.247 606.214 299.023 606.156C299.805 606.099 300.607 605.99 301.43 605.828L301.641 607.547C300.74 607.703 299.878 607.815 299.055 607.883C298.237 607.945 297.427 607.974 296.625 607.969H295.672V606.242H296.625ZM319.523 600.734H315.289V599.125H319.523V600.734ZM319.523 603.82H315.289V602.227H319.523V603.82ZM320.906 611.437H318.922V607.836H311.141V606.258H320.906V611.437ZM320.906 605.625H318.922V597.203H320.906V605.625ZM312.891 597.977C313.589 597.977 314.224 598.125 314.797 598.422C315.375 598.719 315.828 599.135 316.156 599.672C316.484 600.203 316.651 600.799 316.656 601.461C316.651 602.138 316.484 602.745 316.156 603.281C315.828 603.818 315.378 604.237 314.805 604.539C314.232 604.841 313.594 604.992 312.891 604.992C312.177 604.992 311.531 604.841 310.953 604.539C310.38 604.237 309.927 603.818 309.594 603.281C309.266 602.74 309.102 602.133 309.102 601.461C309.102 600.799 309.266 600.203 309.594 599.672C309.927 599.135 310.38 598.719 310.953 598.422C311.531 598.125 312.177 597.977 312.891 597.977ZM312.891 599.664C312.521 599.664 312.193 599.734 311.906 599.875C311.62 600.016 311.396 600.224 311.234 600.5C311.073 600.776 310.992 601.096 310.992 601.461C310.992 601.836 311.073 602.161 311.234 602.437C311.396 602.714 311.62 602.927 311.906 603.078C312.193 603.229 312.521 603.305 312.891 603.305C313.245 603.305 313.562 603.229 313.844 603.078C314.125 602.927 314.346 602.714 314.508 602.437C314.669 602.161 314.75 601.836 314.75 601.461C314.75 601.096 314.669 600.776 314.508 600.5C314.346 600.224 314.122 600.016 313.836 599.875C313.555 599.734 313.24 599.664 312.891 599.664ZM333.906 611.453H331.93V606.297H333.906V611.453ZM339.43 607.359H326.461V605.727H339.43V607.359ZM333.68 600.109C333.68 600.917 333.448 601.664 332.984 602.352C332.526 603.034 331.854 603.607 330.969 604.07C330.089 604.534 329.044 604.836 327.836 604.977L327.109 603.422C328.125 603.297 328.997 603.06 329.727 602.711C330.456 602.362 331.005 601.958 331.375 601.5C331.745 601.042 331.93 600.578 331.93 600.109V599.75H333.68V600.109ZM333.93 600.109C333.93 600.568 334.112 601.026 334.477 601.484C334.846 601.943 335.393 602.349 336.117 602.703C336.846 603.057 337.716 603.297 338.727 603.422L338.008 604.977C336.805 604.836 335.76 604.529 334.875 604.055C333.995 603.576 333.323 602.995 332.859 602.312C332.401 601.625 332.172 600.891 332.172 600.109V599.75H333.93V600.109ZM338.234 600.422H327.633V598.852H338.234V600.422ZM333.906 599.391H331.93V597.234H333.906V599.391ZM351.5 611.414H349.5V597.203H351.5V611.414ZM353.508 604.312H350.984V602.672H353.508V604.312ZM347.703 598.672C347.698 600.151 347.484 601.518 347.062 602.773C346.646 604.029 345.961 605.182 345.008 606.234C344.055 607.286 342.805 608.193 341.258 608.953L340.133 607.43C341.404 606.789 342.453 606.062 343.281 605.25C344.109 604.432 344.727 603.513 345.133 602.492C345.539 601.466 345.745 600.312 345.75 599.031V598.672H347.703ZM346.75 600.305H340.93V598.672H346.75V600.305Z" fill="white"/> +<path d="M80.2334 43.1544C81.0801 43.1599 81.8548 43.3508 82.5576 43.7272C83.2604 44.1035 83.8276 44.7232 84.2593 45.5865C84.6965 46.4498 84.915 47.5759 84.915 48.9649C84.915 50.3263 84.7214 51.4994 84.334 52.4845C83.9466 53.464 83.3877 54.2138 82.6572 54.734C81.9323 55.2486 81.0801 55.506 80.1006 55.506C79.3369 55.506 78.6535 55.3593 78.0503 55.066C77.4526 54.7672 76.9684 54.3605 76.5977 53.8458C76.2324 53.3312 76.0055 52.7418 75.917 52.0777H78.042C78.1195 52.3932 78.2523 52.6671 78.4404 52.8995C78.6286 53.1319 78.861 53.3118 79.1377 53.4391C79.4199 53.5663 79.7409 53.63 80.1006 53.63C80.6761 53.63 81.1659 53.4667 81.5698 53.1402C81.9793 52.8137 82.2892 52.3434 82.4995 51.7291C82.7098 51.1148 82.8177 50.3788 82.8232 49.5211H82.6987C82.4995 49.8642 82.2422 50.1603 81.9268 50.4093C81.6169 50.6528 81.2627 50.8409 80.8643 50.9737C80.4714 51.1065 80.0563 51.173 79.6191 51.173C78.9053 51.173 78.2578 51.0069 77.6768 50.6749C77.1012 50.3373 76.6447 49.8725 76.3071 49.2804C75.9696 48.6883 75.8008 48.0214 75.8008 47.2799C75.8008 46.4941 75.9834 45.7885 76.3486 45.1632C76.7194 44.5323 77.2396 44.0398 77.9092 43.6856C78.5843 43.3259 79.359 43.1489 80.2334 43.1544ZM80.2334 44.8976C79.7962 44.8976 79.3978 45.0027 79.0381 45.213C78.6839 45.4177 78.4045 45.7 78.1997 46.0597C77.995 46.4138 77.8953 46.8012 77.9009 47.2218C77.9009 47.6479 78.0005 48.038 78.1997 48.3922C78.3989 48.7408 78.6729 49.0175 79.0215 49.2223C79.3701 49.427 79.7658 49.5294 80.2085 49.5294C80.6401 49.5294 81.0358 49.4215 81.3955 49.2057C81.7607 48.9898 82.0485 48.7049 82.2588 48.3507C82.4691 47.9965 82.5742 47.6147 82.5742 47.2052C82.5742 46.7957 82.4718 46.4138 82.2671 46.0597C82.0623 45.7055 81.7829 45.4233 81.4287 45.213C81.0745 45.0027 80.6761 44.8976 80.2334 44.8976ZM88.0444 53.8375C87.8065 53.8375 87.5879 53.7794 87.3887 53.6632C87.195 53.547 87.04 53.3893 86.9238 53.19C86.8076 52.9908 86.7523 52.775 86.7578 52.5426C86.7523 52.3157 86.8076 52.1054 86.9238 51.9117C87.04 51.7125 87.195 51.5576 87.3887 51.4469C87.5879 51.3307 87.8065 51.2726 88.0444 51.2726C88.2713 51.2726 88.4816 51.3307 88.6753 51.4469C88.8745 51.5576 89.0322 51.7125 89.1484 51.9117C89.2646 52.1054 89.3228 52.3157 89.3228 52.5426C89.3228 52.775 89.2646 52.9908 89.1484 53.19C89.0322 53.3893 88.8745 53.547 88.6753 53.6632C88.4816 53.7794 88.2713 53.8375 88.0444 53.8375ZM88.0444 47.3961C87.8065 47.3961 87.5879 47.338 87.3887 47.2218C87.195 47.1056 87.04 46.9479 86.9238 46.7486C86.8076 46.5494 86.7523 46.3336 86.7578 46.1012C86.7523 45.8743 86.8076 45.664 86.9238 45.4703C87.04 45.2711 87.195 45.1161 87.3887 45.0055C87.5879 44.8893 87.8065 44.8312 88.0444 44.8312C88.2713 44.8312 88.4816 44.8893 88.6753 45.0055C88.8745 45.1161 89.0322 45.2711 89.1484 45.4703C89.2646 45.664 89.3228 45.8743 89.3228 46.1012C89.3228 46.3336 89.2646 46.5494 89.1484 46.7486C89.0322 46.9479 88.8745 47.1056 88.6753 47.2218C88.4816 47.338 88.2713 47.3961 88.0444 47.3961ZM91.124 51.3805L96.3203 43.3204H97.748V45.7774H96.8599L93.3403 51.2311V51.3307H100.595V53.0987H91.124V51.3805ZM96.9595 52.5841L96.9844 51.8038V43.3204H99.0264V55.3399H96.9595V52.5841ZM107.053 55.3399H104.878V45.4288H104.812L101.998 47.2301V45.2462L104.978 43.3204H107.053V55.3399Z" fill="black"/> +<path opacity="0.35" d="M369.133 43.5H352.733C350.634 43.5 348.933 45.2013 348.933 47.3V51.7C348.933 53.7987 350.634 55.5 352.733 55.5H369.133C371.232 55.5 372.933 53.7987 372.933 51.7V47.3C372.933 45.2013 371.232 43.5 369.133 43.5Z" stroke="black"/> +<path opacity="0.4" d="M374.433 47.7812V51.8568C375.237 51.5117 375.761 50.7086 375.761 49.819C375.761 48.9294 375.237 48.1265 374.433 47.7812Z" fill="black"/> +<path d="M368.933 45H352.933C351.552 45 350.433 46.1193 350.433 47.5V51.5C350.433 52.8807 351.552 54 352.933 54H368.933C370.314 54 371.433 52.8807 371.433 51.5V47.5C371.433 46.1193 370.314 45 368.933 45Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M332.703 46.104C335.19 46.1041 337.582 47.0262 339.385 48.6796C339.52 48.8073 339.737 48.8057 339.871 48.676L341.169 47.4126C341.236 47.3468 341.274 47.2577 341.273 47.165C341.273 47.0724 341.234 46.9837 341.166 46.9187C336.435 42.544 328.971 42.544 324.24 46.9187C324.171 46.9837 324.132 47.0723 324.132 47.165C324.131 47.2577 324.169 47.3468 324.237 47.4126L325.534 48.676C325.668 48.8059 325.885 48.8075 326.021 48.6796C327.824 47.0261 330.216 46.104 332.703 46.104ZM332.7 50.3243C334.057 50.3242 335.366 50.8359 336.372 51.76C336.508 51.8912 336.723 51.8883 336.855 51.7536L338.142 50.4343C338.21 50.3651 338.248 50.2712 338.247 50.1737C338.246 50.0761 338.206 49.9831 338.137 49.9153C335.073 47.0244 330.329 47.0244 327.265 49.9153C327.196 49.9831 327.156 50.0762 327.155 50.1738C327.154 50.2713 327.192 50.3652 327.26 50.4343L328.547 51.7536C328.68 51.8883 328.894 51.8912 329.03 51.76C330.036 50.8365 331.343 50.3248 332.7 50.3243ZM335.224 53.1178C335.226 53.2232 335.189 53.3247 335.122 53.3985L332.945 55.8533C332.881 55.9254 332.794 55.966 332.704 55.966C332.613 55.966 332.526 55.9254 332.462 55.8533L330.285 53.3985C330.218 53.3247 330.181 53.2231 330.183 53.1177C330.185 53.0124 330.225 52.9126 330.295 52.842C331.686 51.5281 333.721 51.5281 335.112 52.842C335.182 52.9127 335.222 53.0125 335.224 53.1178Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M316.633 44.6819C316.633 44.0488 316.155 43.5356 315.566 43.5356H314.499C313.91 43.5356 313.433 44.0488 313.433 44.6819V54.6158C313.433 55.2489 313.91 55.7621 314.499 55.7621H315.566C316.155 55.7621 316.633 55.2489 316.633 54.6158V44.6819ZM309.199 45.9809H310.265C310.854 45.9809 311.332 46.5064 311.332 47.1547V54.5883C311.332 55.2366 310.854 55.7621 310.265 55.7621H309.199C308.609 55.7621 308.132 55.2366 308.132 54.5883V47.1547C308.132 46.5064 308.609 45.9809 309.199 45.9809ZM304.867 48.63H303.8C303.211 48.63 302.733 49.1622 302.733 49.8187V54.5734C302.733 55.2299 303.211 55.762 303.8 55.762H304.867C305.456 55.762 305.933 55.2299 305.933 54.5734V49.8187C305.933 49.1622 305.456 48.63 304.867 48.63ZM299.566 51.0753H298.499C297.91 51.0753 297.433 51.5999 297.433 52.247V54.5904C297.433 55.2375 297.91 55.7621 298.499 55.7621H299.566C300.155 55.7621 300.633 55.2375 300.633 54.5904V52.247C300.633 51.5999 300.155 51.0753 299.566 51.0753Z" fill="black"/> +</g> +</g> +</g> +<mask id="mask5_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="426" y="221" width="3" height="105"> +<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="white"/> +</mask> +<g mask="url(#mask5_1835_8259)"> +<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="url(#paint0_linear_1835_8259)"/> +</g> +<mask id="mask6_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="428" y="221" width="2" height="105"> +<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="white"/> +</mask> +<g mask="url(#mask6_1835_8259)"> +<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="url(#paint1_linear_1835_8259)"/> +</g> +<mask id="mask7_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="3" height="67"> +<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="white"/> +</mask> +<g mask="url(#mask7_1835_8259)"> +<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="url(#paint2_linear_1835_8259)"/> +</g> +<mask id="mask8_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="1" height="67"> +<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.354 0 200.307L0.706443 199.448V265.633V265.637Z" fill="white"/> +</mask> +<g mask="url(#mask8_1835_8259)"> +<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.354 0 200.307L0.706443 199.448V265.633V265.637Z" fill="url(#paint3_linear_1835_8259)"/> +</g> +<mask id="mask9_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="199" width="2" height="67"> +<path d="M2.11914 265.653H3.63295V199.447H2.11914V265.653Z" fill="white"/> +</mask> +<g mask="url(#mask9_1835_8259)"> +<path d="M2.11914 265.653H3.63295V199.447H2.11914V265.653Z" fill="url(#paint4_linear_1835_8259)"/> +</g> +<mask id="mask10_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="3" height="67"> +<path d="M2.11943 348.924H0.706543V282.72H2.11943V348.924Z" fill="white"/> +</mask> +<g mask="url(#mask10_1835_8259)"> +<path d="M2.11943 348.924H0.706543V282.72H2.11943V348.924Z" fill="url(#paint5_linear_1835_8259)"/> +</g> +<mask id="mask11_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="1" height="67"> +<path d="M0.706443 348.928L0 348.068C0.333038 341.036 0.357259 290.645 0 283.598L0.706443 282.738V348.924V348.928Z" fill="white"/> +</mask> +<g mask="url(#mask11_1835_8259)"> +<path d="M0.706443 348.928L0 348.068C0.333038 341.036 0.357259 290.645 0 283.598L0.706443 282.738V348.924V348.928Z" fill="url(#paint6_linear_1835_8259)"/> +</g> +<mask id="mask12_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="282" width="2" height="67"> +<path d="M2.11914 348.944H3.63295V282.738H2.11914V348.944Z" fill="white"/> +</mask> +<g mask="url(#mask12_1835_8259)"> +<path d="M2.11914 348.944H3.63295V282.738H2.11914V348.944Z" fill="url(#paint7_linear_1835_8259)"/> +</g> +<mask id="mask13_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="3" height="35"> +<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="white"/> +</mask> +<g mask="url(#mask13_1835_8259)"> +<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="url(#paint8_linear_1835_8259)"/> +</g> +<mask id="mask14_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="1" height="35"> +<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="white"/> +</mask> +<g mask="url(#mask14_1835_8259)"> +<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="url(#paint9_linear_1835_8259)"/> +</g> +<mask id="mask15_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="136" width="2" height="35"> +<path d="M2.11914 170.878H3.63295V136.895H2.11914V170.878Z" fill="white"/> +</mask> +<g mask="url(#mask15_1835_8259)"> +<path d="M2.11914 170.878H3.63295V136.895H2.11914V170.878Z" fill="url(#paint10_linear_1835_8259)"/> +</g> +<path d="M246.886 60.5405H179.37C171.773 60.5405 165.615 54.3824 165.615 46.7851C165.615 39.1878 171.773 33.0295 179.37 33.0295H246.886C254.483 33.0295 260.641 39.1878 260.641 46.7851C260.641 54.3824 254.483 60.5405 246.886 60.5405ZM243.083 40.7803C239.767 40.7803 237.079 43.4688 237.079 46.7851C237.079 50.1033 239.767 52.7899 243.083 52.7899C246.4 52.7899 249.088 50.1033 249.088 46.7851C249.088 43.4688 246.4 40.7803 243.083 40.7803Z" fill="#1D1D1B"/> +<mask id="mask16_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="40" width="13" height="13"> +<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="white"/> +</mask> +<g mask="url(#mask16_1835_8259)"> +<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="url(#paint11_linear_1835_8259)"/> +</g> +<mask id="mask17_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="41" width="12" height="12"> +<path d="M243.063 52.3916C242.504 52.3916 241.943 52.3089 241.4 52.1373C240.526 51.8628 239.747 51.3804 239.117 50.7526C238.473 50.1067 238.011 49.3216 237.746 48.4779C237.294 47.0347 237.419 45.422 238.182 44.0535C238.437 43.5994 238.75 43.1836 239.115 42.8203C239.745 42.1886 240.524 41.7082 241.398 41.4317C241.941 41.2621 242.502 41.1794 243.061 41.1794C243.715 41.1794 244.367 41.2924 244.982 41.5124C245.751 41.7889 246.464 42.2289 247.053 42.8203C247.419 43.1836 247.734 43.5994 247.986 44.0535C248.749 45.422 248.874 47.0347 248.42 48.4779C248.155 49.3216 247.697 50.1067 247.051 50.7526C246.462 51.342 245.749 51.782 244.98 52.0565C244.367 52.2765 243.717 52.3916 243.063 52.3916ZM243.083 43.3532C241.19 43.3532 239.654 44.8892 239.654 46.7845C239.654 48.6798 241.19 50.2158 243.083 50.2158C244.978 50.2158 246.516 48.6798 246.516 46.7845C246.516 44.8892 244.978 43.3532 243.083 43.3532Z" fill="white"/> +</mask> +<g mask="url(#mask17_1835_8259)"> +<rect x="235.513" y="39.4111" width="14.7748" height="14.7748" fill="url(#pattern0_1835_8259)"/> +</g> +<mask id="mask18_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="239" y="43" width="8" height="8"> +<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="white"/> +</mask> +<g mask="url(#mask18_1835_8259)"> +<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="url(#paint12_linear_1835_8259)"/> +</g> +<mask id="mask19_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="240" y="43" width="7" height="7"> +<path d="M243.081 49.7905C241.416 49.7905 240.08 48.4463 240.08 46.7892C240.08 45.124 241.416 43.7838 243.081 43.7838C244.74 43.7838 246.084 45.124 246.084 46.7892C246.084 47.2636 245.973 47.7156 245.778 48.1153C245.669 47.6369 245.241 47.2817 244.732 47.2817C244.139 47.2817 243.66 47.7621 243.66 48.3535C243.66 48.8823 244.042 49.3223 244.546 49.4091C244.112 49.6513 243.612 49.7905 243.081 49.7905Z" fill="white"/> +</mask> +<g mask="url(#mask19_1835_8259)"> +<rect x="238.337" y="42.2378" width="8.92141" height="8.92141" fill="url(#pattern1_1835_8259)"/> +</g> +<mask id="mask20_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="244" y="48" width="2" height="2"> +<path d="M244.732 49.4263C244.668 49.4263 244.607 49.4182 244.546 49.4081C245.077 49.1114 245.507 48.6593 245.778 48.1143C245.794 48.189 245.804 48.2698 245.804 48.3525C245.804 48.9439 245.324 49.4263 244.732 49.4263Z" fill="white"/> +</mask> +<g mask="url(#mask20_1835_8259)"> +<rect x="243.182" y="46.2739" width="4.07723" height="4.88459" fill="url(#pattern2_1835_8259)"/> +</g> +<mask id="mask21_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="243" y="47" width="3" height="3"> +<path d="M244.547 49.4082C244.042 49.3214 243.661 48.8814 243.661 48.3526C243.661 47.7612 244.139 47.2808 244.732 47.2808C245.241 47.2808 245.669 47.636 245.778 48.1144C245.507 48.6593 245.078 49.1115 244.547 49.4082Z" fill="white"/> +</mask> +<g mask="url(#mask21_1835_8259)"> +<rect x="242.173" y="46.2739" width="5.08643" height="4.88459" fill="url(#pattern3_1835_8259)"/> +</g> +<defs> +<pattern id="pattern0_1835_8259" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_1835_8259" transform="scale(0.0666667)"/> +</pattern> +<pattern id="pattern1_1835_8259" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image1_1835_8259" transform="scale(0.111111)"/> +</pattern> +<pattern id="pattern2_1835_8259" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image2_1835_8259" transform="scale(0.25 0.2)"/> +</pattern> +<pattern id="pattern3_1835_8259" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image3_1835_8259" transform="scale(0.2)"/> +</pattern> +<linearGradient id="paint0_linear_1835_8259" x1="427.525" y1="221.428" x2="427.525" y2="325.938" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2B1D2A"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2B1D2A"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint1_linear_1835_8259" x1="429.38" y1="221.455" x2="429.38" y2="325.943" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint2_linear_1835_8259" x1="1.41299" y1="199.429" x2="1.41299" y2="265.633" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint3_linear_1835_8259" x1="0.353221" y1="199.448" x2="0.353221" y2="265.637" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint4_linear_1835_8259" x1="2.87604" y1="265.653" x2="2.87604" y2="199.446" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint5_linear_1835_8259" x1="1.41299" y1="282.72" x2="1.41299" y2="348.924" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint6_linear_1835_8259" x1="0.353221" y1="282.738" x2="0.353221" y2="348.928" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint7_linear_1835_8259" x1="2.87604" y1="348.944" x2="2.87604" y2="282.737" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint8_linear_1835_8259" x1="1.41299" y1="136.878" x2="1.41299" y2="170.859" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint9_linear_1835_8259" x1="0.353222" y1="136.895" x2="0.353222" y2="170.862" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint10_linear_1835_8259" x1="2.87604" y1="170.878" x2="2.87604" y2="136.895" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint11_linear_1835_8259" x1="243.083" y1="52.4197" x2="243.083" y2="40.5892" gradientUnits="userSpaceOnUse"> +<stop stop-color="#666666"/> +<stop offset="1" stop-color="#010104"/> +</linearGradient> +<linearGradient id="paint12_linear_1835_8259" x1="243.083" y1="43.5652" x2="243.083" y2="50.325" gradientUnits="userSpaceOnUse"> +<stop stop-color="#0B131C"/> +<stop offset="1" stop-color="#354039"/> +</linearGradient> +<clipPath id="clip0_1835_8259"> +<rect width="382" height="827" fill="white" transform="translate(24 20)"/> +</clipPath> +<image id="image0_1835_8259" width="15" height="15" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAUBJREFUKJGFks1S3TAMhT/JshPndl8ehIH3X8LQ9m1uAP+IhXMbAs1U2nhkHR0dSfLz7s45sTRNRItYtEP8slz48/sXegb8n90/PGJnnxoCACKCqo4O7Jh+Cr6ZM1SJCuEL+LTtoIFoEdm81kop70dms/iNxbtz87C1b2aEYOAOIiOmYSd3902vYmbkJRMtEmMkpUQpdVBseSZbFWBLKExpIsaIiCIiXC4/iDHy+rrSWuO9lAFeluUvuJRCnjPIkJBzZkoJVSGEwDxn1vW6a/7K/Pk9pYSZMc8ZC4E3d1R3mWZhH7/70KOq4OCAqtJ756011nXluq47eJrnw/i9d2qt4yB8FCy1YMEIQdGt0+7+/UhEFdUxqNYq12uh9T628EkinFzY7ZJqa4d4v61ShJfnJwTw+4fHf9U4tZfnJwA+AH+jc5A39zmDAAAAAElFTkSuQmCC"/> +<image id="image1_1835_8259" width="9" height="9" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAABHNCSVQICAgIfAhkiAAAAMRJREFUGJWF0LFKA1EQheH/3GxW4qIkogSCjUGstLDQKnUqKx9CH0vs8kYhxNJCElJkCSy6985YhDUoQqb+ivmP2lnm/HOWF6SDI5Rqwj4g+4sUiJcPpPELGoyQ1SjF36i+fcavn2D9hp9c4Wc3yCJZA+LgHoaPaPqKVlP88BRvd8DSFlle4P07WM+hWsJXCXIgIjfCz5OzCVQLyAu808Ptk1C+A47onXtTIbWw7gXEDWHzQajKbY+O+95UyCJYQm7Abr5vonZV760IjhkAAAAASUVORK5CYII="/> +<image id="image2_1835_8259" width="4" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAFCAYAAABirU3bAAAABHNCSVQICAgIfAhkiAAAAEVJREFUCJljlFHV+M+ABFjY2FkYUAXYWBg8XFwZPnz8yHDi9CkGRj1Lk/+srKwMf//+Zfj37x9EBQPDfwYWFiYGBgYmBgAtwhBN2erPwAAAAABJRU5ErkJggg=="/> +<image id="image3_1835_8259" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABHNCSVQICAgIfAhkiAAAAGJJREFUCJk1wbEKglAAheH/yE0rp8A18A1samxpa+4BfNMew7EHEBPkgiBeT5PfJzWtNXT4XGES4fshMPewTCADK/JGRl7i04X368HzVgNGut7NGjkuPxxHUkooHArLG2B2f3kOIpEJnXBlAAAAAElFTkSuQmCC"/> +</defs> +</svg> diff --git a/client/src/assets/image/addMemberMockup.svg b/client/src/assets/image/addMemberMockup.svg new file mode 100644 index 000000000..1bf5892d3 --- /dev/null +++ b/client/src/assets/image/addMemberMockup.svg @@ -0,0 +1,317 @@ +<svg width="100%" height="100%" viewBox="0 0 430 867" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<path d="M358.532 867H71.3893C33.968 867 3.6333 836.665 3.6333 799.244V348.944V282.739V265.653V199.447V170.878V136.894V67.6347C3.6333 30.2134 33.968 -0.12131 71.3893 -0.12131H358.532C395.954 -0.12131 426.288 30.2134 426.288 67.6347V799.244C426.288 836.665 395.954 867 358.532 867ZM71.9202 1.8971C35.3203 1.8971 5.65171 31.5657 5.65171 68.1655V798.713C5.65171 835.312 35.3203 864.982 71.9202 864.982H358.001C394.601 864.982 424.27 835.312 424.27 798.713V68.1655C424.27 31.5657 394.601 1.8971 358.001 1.8971H71.9202ZM357.471 862.963H72.451C36.6727 862.963 7.67012 833.96 7.67012 798.182V68.6964C7.67012 32.9181 36.6727 3.91551 72.451 3.91551H357.471C393.247 3.91551 422.251 32.9181 422.251 68.6964V798.182C422.251 833.96 393.247 862.963 357.471 862.963ZM73.0908 6.49706C38.683 6.49706 10.7906 34.3895 10.7906 68.7973V798.081C10.7906 832.489 38.683 860.381 73.0908 860.381H356.831C391.239 860.381 419.131 832.489 419.131 798.081V68.7973C419.131 34.3895 391.239 6.49706 356.831 6.49706H73.0908Z" fill="#5E465D"/> +<path d="M358.001 864.981H71.9193C35.3195 864.981 5.65088 835.312 5.65088 798.713V68.1653C5.65088 31.5655 35.3195 1.89689 71.9193 1.89689H358.001C394.6 1.89689 424.269 31.5655 424.269 68.1653V798.713C424.269 835.312 394.6 864.981 358.001 864.981ZM72.4502 3.9153C36.6718 3.9153 7.66929 32.9179 7.66929 68.6962V798.181C7.66929 833.96 36.6718 862.963 72.4502 862.963H357.47C393.246 862.963 422.251 833.96 422.251 798.181V68.6962C422.251 32.9179 393.246 3.9153 357.47 3.9153H72.4502Z" fill="#A597A4"/> +<path d="M356.831 860.381H73.0908C38.6829 860.381 10.7905 832.489 10.7905 798.08V68.7972C10.7905 34.3893 38.6829 6.49689 73.0908 6.49689H356.831C391.239 6.49689 419.131 34.3893 419.131 68.7972V798.08C419.131 832.489 391.239 860.381 356.831 860.381ZM72.7739 20.3169C45.9593 20.3169 24.223 42.0552 24.223 68.8698V798.008C24.223 824.823 45.9593 846.561 72.7759 846.561H357.146C383.962 846.561 405.698 824.823 405.698 798.008V68.8698C405.698 42.0552 383.962 20.3169 357.146 20.3169H324.147H105.383C94.1145 20.3169 83.421 20.3169 72.7739 20.3169Z" fill="#1D1D1B"/> +<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> +<mask id="mask0_1837_9941" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> +<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> +</mask> +<g mask="url(#mask0_1837_9941)"> +<g clip-path="url(#clip0_1837_9941)"> +<mask id="mask1_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> +<path d="M406 20H24V847H406V20Z" fill="white"/> +</mask> +<g mask="url(#mask1_1837_9941)"> +<path d="M406 20H24V847H406V20Z" fill="#F1F0F5"/> +<path d="M51.8437 93.2812H41.9297V89.1094H51.8437V93.2812ZM43.8906 91.7892H49.8906V90.5937H43.8906V91.7892ZM52.7109 81.7267H41.0391V80.2345H52.7109V81.7267ZM46.9062 82.1017C48.4583 82.1017 49.6406 82.2734 50.4531 82.6172C51.2708 82.9557 51.6797 83.4583 51.6797 84.125C51.6797 84.7917 51.2708 85.297 50.4531 85.6407C49.6406 85.9845 48.4583 86.1562 46.9062 86.1562C45.3594 86.1562 44.1745 85.9845 43.3516 85.6407C42.5286 85.297 42.1172 84.7917 42.1172 84.125C42.1172 83.4583 42.5286 82.9557 43.3516 82.6172C44.1745 82.2734 45.3594 82.1017 46.9062 82.1017ZM46.9062 83.4375C46.2708 83.4375 45.7656 83.461 45.3906 83.5079C45.0156 83.5548 44.7318 83.6277 44.5391 83.7267C44.3464 83.8256 44.25 83.9583 44.25 84.125C44.25 84.2865 44.3464 84.4168 44.5391 84.5157C44.7318 84.6147 45.0208 84.6902 45.4062 84.7423C45.7917 84.7944 46.2917 84.8203 46.9062 84.8203C47.5312 84.8203 48.0339 84.7944 48.4141 84.7423C48.7995 84.6902 49.0859 84.6147 49.2734 84.5157C49.4609 84.4168 49.5547 84.2865 49.5547 84.125C49.5547 83.9583 49.4609 83.8256 49.2734 83.7267C49.0859 83.6277 48.8047 83.5548 48.4297 83.5079C48.0547 83.461 47.5469 83.4375 46.9062 83.4375ZM47.8984 81.3047H45.8984V79.0938H47.8984V81.3047ZM53.3984 88.3907H40.4297V86.8359H53.3984V88.3907ZM47.8984 87.6798H45.8984V85.6484H47.8984V87.6798Z" fill="#B2B1B6"/> +<path d="M73.2187 81.875H67.0781V80.25H73.2187V81.875ZM70.8594 87.1094H68.875V83.5312H70.8594V87.1094ZM74.3984 81.2344C74.3932 81.9687 74.3724 82.6458 74.3359 83.2656C74.2995 83.8854 74.2135 84.5651 74.0781 85.3047L72.1094 85.1328C72.25 84.388 72.3385 83.737 72.375 83.1797C72.4167 82.6224 72.4427 81.9818 72.4531 81.2578V81.1328V80.25H74.3984V81.1328V81.2344ZM77.875 89.8516H75.8281V79.2031H77.875V89.8516ZM79.6016 85.2187H77.0703V83.5547H79.6016V85.2187ZM78.3203 93.1953H68.3281V91.5859H78.3203V93.1953ZM70.3281 92.0937H68.3281V88.9062H70.3281V92.0937ZM66.2344 86.3437C67.9375 86.3437 69.513 86.3151 70.9609 86.2578C72.4141 86.2005 73.7839 86.0781 75.0703 85.8906L75.1641 87.3281C73.8464 87.5729 72.4635 87.7344 71.0156 87.8125C69.5677 87.8906 68.0312 87.9297 66.4062 87.9297L66.2344 86.3437ZM92.1719 93.4766H90.1797V79.2031H92.1719V93.4766ZM82.2891 88.5C83.6276 88.5104 84.8281 88.4818 85.8906 88.4141C86.9583 88.3411 88.0495 88.2135 89.1641 88.0312L89.3437 89.6406C88.2448 89.8333 87.1484 89.9661 86.0547 90.0391C84.9661 90.1068 83.7109 90.1406 82.2891 90.1406H81.0156V88.5H82.2891ZM87.7578 85.8828H83.0703V89.125H81.0156V84.3203H85.7266V82.0156H81V80.4062H87.7578V85.8828Z" fill="#56555A"/> +<path d="M406 114H24V270H406V114Z" fill="white"/> +<path d="M60.9609 151.188H58.1133V137.805H60.9609V151.188ZM58.875 145.551H55.3828V143.113H58.875V145.551ZM56.4141 150.496H53.625V138.215H56.4141V150.496ZM52.9922 142.34H42.5273V140.008H52.9922V142.34ZM47.7891 143.066C48.6875 143.066 49.4883 143.219 50.1914 143.523C50.9023 143.828 51.457 144.266 51.8555 144.836C52.2539 145.398 52.4531 146.051 52.4531 146.793C52.4531 147.512 52.2539 148.152 51.8555 148.715C51.457 149.27 50.9023 149.703 50.1914 150.016C49.4883 150.32 48.6875 150.473 47.7891 150.473C46.9062 150.473 46.1133 150.32 45.4102 150.016C44.7148 149.703 44.168 149.27 43.7695 148.715C43.3711 148.152 43.1719 147.512 43.1719 146.793C43.1719 146.051 43.3711 145.398 43.7695 144.836C44.168 144.266 44.7148 143.828 45.4102 143.523C46.1133 143.219 46.9062 143.066 47.7891 143.066ZM47.7891 145.211C47.4062 145.203 47.0664 145.262 46.7695 145.387C46.4805 145.512 46.2539 145.695 46.0898 145.938C45.9258 146.18 45.8438 146.465 45.8438 146.793C45.8438 147.113 45.9219 147.391 46.0781 147.625C46.2422 147.859 46.4688 148.043 46.7578 148.176C47.0547 148.301 47.3984 148.363 47.7891 148.363C48.1797 148.363 48.5234 148.301 48.8203 148.176C49.1172 148.043 49.3477 147.859 49.5117 147.625C49.6758 147.391 49.7578 147.113 49.7578 146.793C49.7578 146.465 49.6758 146.18 49.5117 145.938C49.3477 145.695 49.1172 145.512 48.8203 145.387C48.5234 145.262 48.1797 145.203 47.7891 145.211ZM49.2656 141.625H46.2773V138.016H49.2656V141.625ZM53.6719 151.41C55.2031 151.41 56.5234 151.562 57.6328 151.867C58.7422 152.164 59.5898 152.605 60.1758 153.191C60.7695 153.777 61.0664 154.477 61.0664 155.289C61.0664 156.109 60.7695 156.805 60.1758 157.375C59.5898 157.953 58.7422 158.395 57.6328 158.699C56.5234 159.004 55.2031 159.156 53.6719 159.156C52.1484 159.156 50.832 159.004 49.7227 158.699C48.6211 158.395 47.7734 157.953 47.1797 157.375C46.5859 156.805 46.2891 156.109 46.2891 155.289C46.2891 154.477 46.5859 153.777 47.1797 153.191C47.7734 152.605 48.6211 152.164 49.7227 151.867C50.832 151.562 52.1484 151.41 53.6719 151.41ZM53.6719 153.648C52.6953 153.641 51.8828 153.695 51.2344 153.812C50.5938 153.93 50.1055 154.113 49.7695 154.363C49.4414 154.613 49.2812 154.922 49.2891 155.289C49.2812 155.641 49.4414 155.938 49.7695 156.18C50.1055 156.414 50.5977 156.594 51.2461 156.719C51.8945 156.844 52.7031 156.906 53.6719 156.906C54.6406 156.906 55.4492 156.844 56.0977 156.719C56.7539 156.594 57.2422 156.414 57.5625 156.18C57.8906 155.945 58.0586 155.648 58.0664 155.289C58.0586 154.914 57.8906 154.605 57.5625 154.363C57.2422 154.113 56.7578 153.93 56.1094 153.812C55.4609 153.695 54.6484 153.641 53.6719 153.648ZM82.875 150.262H63.3867V147.895H82.875V150.262ZM74.5898 148.832H71.6602V144.684H74.5898V148.832ZM80.6484 146.066H65.7422V143.723H80.6484V146.066ZM80.5312 141.098H68.707V145.258H65.7422V138.766H80.5312V141.098ZM73.0781 151.316C74.6172 151.316 75.9414 151.473 77.0508 151.785C78.1602 152.09 79.0117 152.539 79.6055 153.133C80.1992 153.719 80.5 154.43 80.5078 155.266C80.5 156.094 80.1992 156.797 79.6055 157.375C79.0195 157.961 78.168 158.406 77.0508 158.711C75.9414 159.023 74.6172 159.184 73.0781 159.191C71.5234 159.184 70.1875 159.023 69.0703 158.711C67.9531 158.406 67.0938 157.961 66.4922 157.375C65.8984 156.789 65.6016 156.086 65.6016 155.266C65.6016 154.43 65.8984 153.719 66.4922 153.133C67.0938 152.539 67.9531 152.09 69.0703 151.785C70.1875 151.473 71.5234 151.316 73.0781 151.316ZM73.0781 153.602C72.0859 153.602 71.2617 153.664 70.6055 153.789C69.957 153.906 69.4648 154.09 69.1289 154.34C68.8008 154.59 68.6406 154.898 68.6484 155.266C68.6406 155.641 68.8008 155.949 69.1289 156.191C69.4648 156.434 69.957 156.613 70.6055 156.73C71.2617 156.848 72.0859 156.906 73.0781 156.906C74.0547 156.906 74.8672 156.848 75.5156 156.73C76.1719 156.613 76.6641 156.434 76.9922 156.191C77.3281 155.949 77.4961 155.641 77.4961 155.266C77.4961 154.906 77.3281 154.602 76.9922 154.352C76.6641 154.094 76.1719 153.906 75.5156 153.789C74.8594 153.664 74.0469 153.602 73.0781 153.602ZM102.551 159.156H99.7383V137.805H102.551V159.156ZM100.418 148.457H96.7969V146.066H100.418V148.457ZM97.6758 158.125H94.9336V138.191H97.6758V158.125ZM86.2148 151.832C87.7773 151.832 89.1172 151.797 90.2344 151.727C91.3516 151.656 92.5 151.516 93.6797 151.305L93.8906 153.73C92.7031 153.965 91.5352 154.121 90.3867 154.199C89.2461 154.27 87.8555 154.312 86.2148 154.328H84.7148V151.832H86.2148ZM92.6836 142.703H87.7148V153.039H84.7148V140.301H92.6836V142.703ZM112.16 141.59C112.152 142.98 111.926 144.277 111.481 145.48C111.035 146.676 110.352 147.719 109.43 148.609C108.516 149.5 107.391 150.16 106.055 150.59L104.555 148.234C105.695 147.867 106.652 147.34 107.426 146.652C108.199 145.957 108.77 145.176 109.137 144.309C109.512 143.441 109.703 142.535 109.711 141.59V140.195H112.16V141.59ZM112.734 141.578C112.734 142.445 112.91 143.27 113.262 144.051C113.613 144.824 114.156 145.52 114.891 146.137C115.625 146.746 116.543 147.215 117.645 147.543L116.238 149.875C114.926 149.484 113.828 148.879 112.945 148.059C112.063 147.23 111.398 146.266 110.953 145.164C110.516 144.055 110.297 142.859 110.297 141.578V140.195H112.734V141.578ZM116.988 141.637H105.363V139.246H116.988V141.637ZM121.781 150.473H118.793V137.805H121.781V150.473ZM124.664 145.211H120.938V142.773H124.664V145.211ZM114.785 150.895C116.262 150.895 117.539 151.059 118.617 151.387C119.703 151.707 120.535 152.176 121.113 152.793C121.691 153.41 121.981 154.148 121.981 155.008C121.981 155.867 121.691 156.605 121.113 157.223C120.535 157.848 119.703 158.324 118.617 158.652C117.539 158.988 116.262 159.156 114.785 159.156C113.293 159.156 111.996 158.988 110.895 158.652C109.793 158.324 108.945 157.848 108.352 157.223C107.766 156.605 107.473 155.867 107.473 155.008C107.473 154.148 107.766 153.41 108.352 152.793C108.945 152.176 109.789 151.707 110.883 151.387C111.984 151.059 113.285 150.895 114.785 150.895ZM114.785 153.215C113.856 153.215 113.066 153.281 112.418 153.414C111.777 153.547 111.293 153.75 110.965 154.023C110.637 154.289 110.477 154.617 110.484 155.008C110.477 155.414 110.637 155.754 110.965 156.027C111.293 156.293 111.777 156.496 112.418 156.637C113.059 156.77 113.848 156.836 114.785 156.836C115.715 156.836 116.492 156.77 117.117 156.637C117.75 156.496 118.227 156.293 118.547 156.027C118.875 155.754 119.039 155.414 119.039 155.008C119.039 154.609 118.875 154.277 118.547 154.012C118.227 153.746 117.75 153.547 117.117 153.414C116.492 153.281 115.715 153.215 114.785 153.215ZM136.91 139.316C137.988 139.316 138.949 139.629 139.793 140.254C140.645 140.871 141.312 141.758 141.797 142.914C142.281 144.062 142.527 145.398 142.535 146.922C142.527 148.453 142.281 149.797 141.797 150.953C141.312 152.102 140.645 152.984 139.793 153.602C138.949 154.219 137.988 154.527 136.91 154.527C135.816 154.527 134.844 154.219 133.992 153.602C133.141 152.984 132.473 152.102 131.988 150.953C131.512 149.797 131.273 148.453 131.273 146.922C131.273 145.398 131.512 144.062 131.988 142.914C132.473 141.758 133.141 140.871 133.992 140.254C134.844 139.629 135.816 139.316 136.91 139.316ZM136.91 142.023C136.363 142.016 135.883 142.203 135.469 142.586C135.055 142.969 134.73 143.527 134.496 144.262C134.27 144.996 134.156 145.883 134.156 146.922C134.156 147.961 134.27 148.848 134.496 149.582C134.73 150.316 135.055 150.875 135.469 151.258C135.883 151.633 136.363 151.82 136.91 151.82C137.465 151.82 137.949 151.633 138.363 151.258C138.777 150.875 139.094 150.316 139.312 149.582C139.539 148.848 139.652 147.961 139.652 146.922C139.652 145.883 139.539 144.996 139.312 144.262C139.094 143.52 138.777 142.961 138.363 142.586C137.949 142.203 137.465 142.016 136.91 142.023ZM150.996 145.281H147.176V142.785H150.996V145.281ZM150.996 151.504H147.176V149.078H150.996V151.504ZM147.984 159.156H144.984V137.805H147.984V159.156ZM159.41 159.156H156.34V151.27H159.41V159.156ZM166.816 159.156H163.781V151.27H166.816V159.156ZM171.387 152.102H151.887V149.688H171.387V152.102ZM161.578 138.531C163.094 138.531 164.441 138.73 165.621 139.129C166.801 139.527 167.715 140.09 168.363 140.816C169.02 141.543 169.348 142.387 169.348 143.348C169.348 144.293 169.02 145.121 168.363 145.832C167.715 146.535 166.801 147.082 165.621 147.473C164.441 147.863 163.094 148.059 161.578 148.059C160.062 148.059 158.719 147.863 157.547 147.473C156.375 147.082 155.461 146.535 154.805 145.832C154.156 145.121 153.832 144.293 153.832 143.348C153.832 142.387 154.156 141.543 154.805 140.816C155.461 140.09 156.375 139.527 157.547 139.129C158.719 138.73 160.062 138.531 161.578 138.531ZM161.578 140.922C160.617 140.93 159.785 141.027 159.082 141.215C158.387 141.395 157.852 141.668 157.477 142.035C157.102 142.395 156.918 142.832 156.926 143.348C156.918 143.84 157.102 144.262 157.477 144.613C157.852 144.965 158.387 145.234 159.082 145.422C159.785 145.602 160.617 145.691 161.578 145.691C162.539 145.691 163.371 145.602 164.074 145.422C164.777 145.234 165.316 144.969 165.691 144.625C166.074 144.273 166.266 143.848 166.266 143.348C166.266 142.832 166.074 142.395 165.691 142.035C165.316 141.668 164.777 141.395 164.074 141.215C163.379 141.027 162.547 140.93 161.578 140.922ZM181.137 154.258H178.16V150.777H181.137V154.258ZM190.559 159.156H187.594V137.805H190.559V159.156ZM173.578 153.133C176.234 153.117 178.57 153.074 180.586 153.004C182.609 152.926 184.555 152.762 186.422 152.512L186.609 154.727C184.547 155.086 182.426 155.32 180.246 155.43C178.066 155.531 175.695 155.582 173.133 155.582L172.734 153.133H173.578ZM186.117 142.551H173.156V140.207H186.117V142.551ZM179.625 143.395C180.672 143.395 181.602 143.562 182.414 143.898C183.234 144.227 183.867 144.695 184.312 145.305C184.766 145.914 184.992 146.613 184.992 147.402C184.992 148.184 184.766 148.879 184.312 149.488C183.867 150.09 183.234 150.559 182.414 150.895C181.602 151.23 180.672 151.398 179.625 151.398C178.594 151.398 177.676 151.23 176.871 150.895C176.066 150.559 175.438 150.09 174.984 149.488C174.539 148.879 174.316 148.184 174.316 147.402C174.316 146.613 174.539 145.914 174.984 145.305C175.438 144.695 176.066 144.227 176.871 143.898C177.676 143.562 178.594 143.395 179.625 143.395ZM179.625 145.656C179.141 145.656 178.711 145.727 178.336 145.867C177.969 146 177.68 146.199 177.469 146.465C177.258 146.73 177.152 147.043 177.152 147.402C177.152 147.77 177.254 148.082 177.457 148.34C177.668 148.59 177.961 148.785 178.336 148.926C178.711 149.059 179.141 149.125 179.625 149.125C180.125 149.125 180.566 149.059 180.949 148.926C181.332 148.785 181.625 148.59 181.828 148.34C182.031 148.082 182.133 147.77 182.133 147.402C182.133 147.043 182.031 146.73 181.828 146.465C181.625 146.199 181.332 146 180.949 145.867C180.566 145.727 180.125 145.656 179.625 145.656ZM181.16 141.543H178.16V137.91H181.16V141.543Z" fill="#56555A"/> +<path d="M47.3125 183.641C47.3125 184.599 47.1302 185.544 46.7656 186.477C46.401 187.409 45.9115 188.237 45.2969 188.961C44.6875 189.685 44.0208 190.229 43.2969 190.594L42.5625 189.625C43.224 189.307 43.8385 188.828 44.4062 188.188C44.9792 187.542 45.4375 186.818 45.7812 186.016C46.125 185.214 46.2969 184.422 46.2969 183.641V181.344H47.3125V183.641ZM47.5312 183.641C47.5312 184.406 47.7031 185.169 48.0469 185.93C48.3906 186.685 48.849 187.359 49.4219 187.953C49.9948 188.547 50.6198 188.99 51.2969 189.281L50.6094 190.25C49.8542 189.906 49.1667 189.396 48.5469 188.719C47.9323 188.042 47.4427 187.263 47.0781 186.383C46.7188 185.497 46.5417 184.583 46.5469 183.641V181.344H47.5312V183.641ZM50.8438 181.828H43.0156V180.812H50.8438V181.828ZM54.0156 193.266H52.7812V179.375H54.0156V193.266ZM63.3125 188.391H62.1094V186.281H63.3125V188.391ZM69.0469 186.516H56.4062V185.562H69.0469V186.516ZM63.3125 180.984H62.1094V179.297H63.3125V180.984ZM63.125 181.312C63.125 182.016 62.8698 182.625 62.3594 183.141C61.849 183.651 61.1641 184.055 60.3047 184.352C59.4505 184.643 58.4948 184.833 57.4375 184.922L57.0781 183.984C57.9948 183.927 58.8307 183.784 59.5859 183.555C60.3411 183.32 60.9401 183.013 61.3828 182.633C61.8255 182.247 62.0469 181.807 62.0469 181.312V181.109H63.125V181.312ZM63.3906 181.312C63.3854 181.807 63.6042 182.247 64.0469 182.633C64.4948 183.013 65.0938 183.32 65.8438 183.555C66.599 183.784 67.4375 183.927 68.3594 183.984L67.9844 184.922C66.9323 184.833 65.9792 184.643 65.125 184.352C64.2708 184.055 63.5885 183.651 63.0781 183.141C62.5677 182.625 62.3125 182.016 62.3125 181.312V181.109H63.3906V181.312ZM67.7656 181.562H57.7031V180.594H67.7656V181.562ZM67.4219 190.812H59.1719V192.516H57.9531V189.938H66.2188V188.734H57.9219V187.812H67.4219V190.812ZM67.8438 193.109H57.9531V192.172H67.8438V193.109ZM86.0938 193.266H84.8906V179.375H86.0938V193.266ZM85.25 186.078H82.5312V185.031H85.25V186.078ZM82.8906 192.547H81.7344V179.688H82.8906V192.547ZM76.1562 189.078H74.9375V181.078H76.1562V189.078ZM75.7969 188.578C76.625 188.583 77.4349 188.555 78.2266 188.492C79.0234 188.424 79.849 188.302 80.7031 188.125L80.8594 189.219C79.9427 189.385 79.0755 189.503 78.2578 189.57C77.4453 189.638 76.625 189.672 75.7969 189.672H74.9375V188.578H75.7969ZM98.7188 182.438H94.4688V181.422H98.7188V182.438ZM98.7188 185.562H94.4688V184.547H98.7188V185.562ZM99.5781 193.266H98.3438V189.312H90.2344V188.328H99.5781V193.266ZM99.5781 187.562H98.3438V179.375H99.5781V187.562ZM91.8906 180.172C92.5677 180.172 93.1797 180.312 93.7266 180.594C94.2734 180.875 94.7005 181.268 95.0078 181.773C95.3203 182.279 95.4792 182.849 95.4844 183.484C95.4792 184.135 95.3203 184.714 95.0078 185.219C94.7005 185.719 94.2734 186.112 93.7266 186.398C93.1797 186.68 92.5677 186.818 91.8906 186.812C91.2031 186.818 90.5859 186.68 90.0391 186.398C89.4922 186.112 89.0625 185.716 88.75 185.211C88.4375 184.706 88.2812 184.13 88.2812 183.484C88.2812 182.849 88.4375 182.279 88.75 181.773C89.0625 181.268 89.4922 180.875 90.0391 180.594C90.5859 180.312 91.2031 180.172 91.8906 180.172ZM91.8906 181.219C91.4219 181.219 91.0026 181.315 90.6328 181.508C90.263 181.701 89.974 181.971 89.7656 182.32C89.5573 182.664 89.4531 183.052 89.4531 183.484C89.4531 183.927 89.5573 184.323 89.7656 184.672C89.974 185.016 90.263 185.286 90.6328 185.484C91.0026 185.682 91.4219 185.781 91.8906 185.781C92.3438 185.781 92.7526 185.682 93.1172 185.484C93.487 185.286 93.776 185.016 93.9844 184.672C94.1927 184.323 94.2969 183.927 94.2969 183.484C94.2969 183.057 94.1927 182.669 93.9844 182.32C93.776 181.971 93.487 181.701 93.1172 181.508C92.7474 181.315 92.3385 181.219 91.8906 181.219ZM113.156 185.938H106.641V180.281H113.156V185.938ZM107.844 184.969H111.953V181.281H107.844V184.969ZM117.359 187.359H116.156V179.375H117.359V187.359ZM113.391 189.266C113.391 189.911 113.146 190.513 112.656 191.07C112.167 191.628 111.516 192.091 110.703 192.461C109.891 192.836 109.016 193.089 108.078 193.219L107.641 192.266C108.432 192.177 109.19 191.982 109.914 191.68C110.638 191.372 111.221 191.005 111.664 190.578C112.107 190.151 112.328 189.714 112.328 189.266V188.984H113.391V189.266ZM113.594 189.266C113.594 189.703 113.81 190.135 114.242 190.562C114.675 190.99 115.245 191.357 115.953 191.664C116.667 191.966 117.417 192.167 118.203 192.266L117.781 193.219C116.849 193.089 115.979 192.831 115.172 192.445C114.37 192.065 113.727 191.596 113.242 191.039C112.763 190.482 112.526 189.891 112.531 189.266V188.984H113.594V189.266ZM117.719 189.266H108.219V188.312H117.719V189.266ZM113.562 188.75H112.344V186.953H113.562V188.75ZM135.219 189.547H134V179.391H135.219V189.547ZM135.656 192.969H126.25V191.938H135.656V192.969ZM127.469 192.281H126.25V188.516H127.469V192.281ZM127.719 180.359C128.406 180.359 129.026 180.505 129.578 180.797C130.13 181.089 130.565 181.492 130.883 182.008C131.201 182.523 131.359 183.109 131.359 183.766C131.359 184.427 131.201 185.018 130.883 185.539C130.565 186.055 130.13 186.458 129.578 186.75C129.026 187.042 128.406 187.188 127.719 187.188C127.031 187.188 126.411 187.042 125.859 186.75C125.307 186.458 124.872 186.055 124.555 185.539C124.237 185.018 124.078 184.427 124.078 183.766C124.078 183.109 124.237 182.523 124.555 182.008C124.872 181.492 125.307 181.089 125.859 180.797C126.411 180.505 127.031 180.359 127.719 180.359ZM127.719 181.438C127.255 181.438 126.836 181.536 126.461 181.734C126.091 181.932 125.799 182.208 125.586 182.562C125.378 182.917 125.276 183.318 125.281 183.766C125.276 184.219 125.378 184.625 125.586 184.984C125.799 185.339 126.091 185.615 126.461 185.812C126.836 186.01 127.255 186.109 127.719 186.109C128.177 186.109 128.591 186.01 128.961 185.812C129.331 185.615 129.622 185.339 129.836 184.984C130.049 184.625 130.156 184.219 130.156 183.766C130.156 183.318 130.049 182.917 129.836 182.562C129.622 182.208 129.331 181.932 128.961 181.734C128.591 181.536 128.177 181.438 127.719 181.438ZM142.812 189.453H141.578V186.359H142.812V189.453ZM149.031 189.938H147.797V179.391H149.031V189.938ZM149.375 192.969H139.5V191.938H149.375V192.969ZM140.734 192.234H139.5V188.906H140.734V192.234ZM137.5 185.828C139.359 185.818 141.005 185.789 142.438 185.742C143.87 185.69 145.24 185.583 146.547 185.422L146.625 186.312C145.276 186.526 143.862 186.667 142.383 186.734C140.904 186.802 139.333 186.833 137.672 186.828L137.5 185.828ZM148.125 188.5H144.922V187.609H148.125V188.5ZM142.062 179.953C142.734 179.953 143.331 180.052 143.852 180.25C144.378 180.448 144.784 180.732 145.07 181.102C145.357 181.471 145.5 181.896 145.5 182.375C145.5 182.865 145.357 183.289 145.07 183.648C144.784 184.008 144.38 184.286 143.859 184.484C143.339 184.682 142.74 184.781 142.062 184.781C141.38 184.781 140.779 184.682 140.258 184.484C139.742 184.286 139.341 184.008 139.055 183.648C138.768 183.289 138.625 182.865 138.625 182.375C138.625 181.896 138.768 181.471 139.055 181.102C139.341 180.732 139.745 180.448 140.266 180.25C140.786 180.052 141.385 179.953 142.062 179.953ZM142.062 180.891C141.615 180.885 141.219 180.945 140.875 181.07C140.531 181.19 140.263 181.365 140.07 181.594C139.883 181.823 139.792 182.083 139.797 182.375C139.792 182.672 139.883 182.935 140.07 183.164C140.263 183.388 140.531 183.562 140.875 183.688C141.219 183.812 141.615 183.875 142.062 183.875C142.5 183.875 142.891 183.812 143.234 183.688C143.578 183.562 143.846 183.388 144.039 183.164C144.232 182.935 144.328 182.672 144.328 182.375C144.328 182.083 144.232 181.823 144.039 181.594C143.846 181.365 143.578 181.19 143.234 181.07C142.891 180.945 142.5 180.885 142.062 180.891ZM166.156 182.969H162.109V181.938H166.156V182.969ZM166.203 185.938H162.109V184.922H166.203V185.938ZM166.938 189.672H165.703V179.391H166.938V189.672ZM167.25 192.969H157.953V191.938H167.25V192.969ZM159.188 192.438H157.953V188.656H159.188V192.438ZM157.344 182.781H161.219V180.312H162.422V187.297H156.125V180.312H157.344V182.781ZM161.219 186.281V183.75H157.344V186.281H161.219ZM181.922 187.234H169.25V186.25H181.922V187.234ZM176.172 186.672H174.984V184.016H176.172V186.672ZM180.438 184.625H170.859V183.625H180.438V184.625ZM180.344 181.016H172.062V184.234H170.859V180.031H180.344V181.016ZM175.578 188.25C176.568 188.25 177.419 188.349 178.133 188.547C178.846 188.745 179.393 189.031 179.773 189.406C180.159 189.776 180.354 190.224 180.359 190.75C180.354 191.281 180.161 191.732 179.781 192.102C179.406 192.471 178.859 192.755 178.141 192.953C177.422 193.156 176.568 193.26 175.578 193.266C174.578 193.26 173.719 193.156 173 192.953C172.281 192.755 171.732 192.469 171.352 192.094C170.971 191.724 170.781 191.276 170.781 190.75C170.781 190.224 170.971 189.776 171.352 189.406C171.732 189.031 172.281 188.745 173 188.547C173.719 188.349 174.578 188.25 175.578 188.25ZM175.578 189.219C174.839 189.219 174.203 189.279 173.672 189.398C173.141 189.518 172.732 189.695 172.445 189.93C172.164 190.159 172.026 190.432 172.031 190.75C172.026 191.073 172.164 191.349 172.445 191.578C172.732 191.807 173.141 191.982 173.672 192.102C174.203 192.221 174.839 192.281 175.578 192.281C176.307 192.281 176.938 192.221 177.469 192.102C178 191.982 178.409 191.807 178.695 191.578C178.982 191.349 179.125 191.073 179.125 190.75C179.125 190.432 178.982 190.159 178.695 189.93C178.409 189.695 178 189.518 177.469 189.398C176.938 189.279 176.307 189.219 175.578 189.219ZM189.406 179.625C190.432 179.625 191.312 179.716 192.047 179.898C192.786 180.081 193.349 180.352 193.734 180.711C194.12 181.07 194.312 181.505 194.312 182.016C194.312 182.536 194.12 182.979 193.734 183.344C193.349 183.708 192.789 183.984 192.055 184.172C191.32 184.354 190.438 184.448 189.406 184.453C188.37 184.448 187.484 184.354 186.75 184.172C186.021 183.984 185.461 183.708 185.07 183.344C184.68 182.979 184.484 182.536 184.484 182.016C184.484 181.505 184.68 181.07 185.07 180.711C185.461 180.352 186.023 180.081 186.758 179.898C187.492 179.716 188.375 179.625 189.406 179.625ZM189.406 180.547C188.641 180.547 187.984 180.607 187.438 180.727C186.896 180.846 186.479 181.016 186.188 181.234C185.901 181.453 185.76 181.714 185.766 182.016C185.76 182.333 185.901 182.607 186.188 182.836C186.479 183.06 186.896 183.229 187.438 183.344C187.984 183.458 188.641 183.516 189.406 183.516C190.172 183.516 190.828 183.458 191.375 183.344C191.927 183.229 192.346 183.06 192.633 182.836C192.919 182.612 193.062 182.339 193.062 182.016C193.062 181.714 192.919 181.453 192.633 181.234C192.346 181.016 191.927 180.846 191.375 180.727C190.823 180.607 190.167 180.547 189.406 180.547ZM195.734 186.391H183.078V185.391H195.734V186.391ZM194.109 190.703H185.859V192.391H184.641V189.797H192.906V188.531H184.609V187.594H194.109V190.703ZM194.531 193.109H184.641V192.141H194.531V193.109ZM207.844 193.297H206.641V188.188H207.844V193.297ZM213.578 188.812H200.922V187.781H213.578V188.812ZM207.719 182.125C207.719 182.896 207.461 183.602 206.945 184.242C206.43 184.883 205.747 185.417 204.898 185.844C204.055 186.266 203.146 186.552 202.172 186.703L201.719 185.719C202.552 185.604 203.346 185.37 204.102 185.016C204.857 184.661 205.469 184.232 205.938 183.727C206.406 183.221 206.641 182.688 206.641 182.125V181.75H207.719V182.125ZM207.859 182.125C207.859 182.682 208.091 183.216 208.555 183.727C209.018 184.232 209.628 184.661 210.383 185.016C211.138 185.37 211.932 185.604 212.766 185.719L212.312 186.703C211.339 186.557 210.43 186.268 209.586 185.836C208.747 185.404 208.073 184.867 207.562 184.227C207.052 183.581 206.797 182.88 206.797 182.125V181.75H207.859V182.125ZM212.359 182.109H202.156V181.109H212.359V182.109ZM207.844 181.453H206.641V179.375H207.844V181.453ZM225.5 193.266H224.281V179.375H225.5V193.266ZM227.75 186.062H225.188V185.031H227.75V186.062ZM221.906 180.875C221.901 182.224 221.677 183.5 221.234 184.703C220.797 185.901 220.104 187.008 219.156 188.023C218.208 189.034 217 189.901 215.531 190.625L214.844 189.656C216.13 189.016 217.208 188.263 218.078 187.398C218.953 186.529 219.607 185.565 220.039 184.508C220.477 183.451 220.698 182.307 220.703 181.078V180.875H221.906ZM221.328 181.906H215.484V180.875H221.328V181.906ZM235.516 182.781H228.547V181.781H235.516V182.781ZM232.031 183.719C232.609 183.719 233.125 183.854 233.578 184.125C234.036 184.396 234.393 184.771 234.648 185.25C234.909 185.724 235.042 186.266 235.047 186.875C235.042 187.49 234.909 188.036 234.648 188.516C234.393 188.995 234.036 189.372 233.578 189.648C233.125 189.924 232.609 190.062 232.031 190.062C231.464 190.062 230.951 189.924 230.492 189.648C230.039 189.372 229.685 188.995 229.43 188.516C229.174 188.036 229.047 187.49 229.047 186.875C229.047 186.271 229.177 185.729 229.438 185.25C229.698 184.771 230.052 184.396 230.5 184.125C230.953 183.854 231.464 183.719 232.031 183.719ZM232.031 184.75C231.667 184.755 231.341 184.852 231.055 185.039C230.768 185.221 230.544 185.474 230.383 185.797C230.221 186.115 230.141 186.474 230.141 186.875C230.141 187.281 230.221 187.643 230.383 187.961C230.544 188.279 230.768 188.529 231.055 188.711C231.341 188.893 231.667 188.984 232.031 188.984C232.396 188.984 232.724 188.893 233.016 188.711C233.307 188.529 233.536 188.279 233.703 187.961C233.87 187.643 233.953 187.281 233.953 186.875C233.953 186.474 233.87 186.115 233.703 185.797C233.536 185.474 233.307 185.221 233.016 185.039C232.724 184.852 232.396 184.755 232.031 184.75ZM240.406 193.266H239.234V179.375H240.406V193.266ZM239.625 186.25H236.969V185.234H239.625V186.25ZM237.391 192.578H236.234V179.719H237.391V192.578ZM232.656 182.391H231.438V179.797H232.656V182.391ZM253.141 181.344C253.141 182.141 252.883 182.872 252.367 183.539C251.852 184.201 251.174 184.755 250.336 185.203C249.497 185.646 248.604 185.948 247.656 186.109L247.172 185.141C247.99 185.021 248.773 184.776 249.523 184.406C250.279 184.031 250.891 183.576 251.359 183.039C251.828 182.503 252.062 181.938 252.062 181.344V180.75H253.141V181.344ZM253.438 181.344C253.438 181.938 253.672 182.503 254.141 183.039C254.609 183.576 255.219 184.031 255.969 184.406C256.724 184.776 257.51 185.021 258.328 185.141L257.875 186.109C256.917 185.948 256.018 185.646 255.18 185.203C254.341 184.755 253.664 184.201 253.148 183.539C252.633 182.872 252.375 182.141 252.375 181.344V180.75H253.438V181.344ZM253.328 193.266H252.125V187.953H253.328V193.266ZM259.078 188.312H246.422V187.297H259.078V188.312ZM257.875 181.25H247.609V180.25H257.875V181.25ZM268.5 185.406H265.766V184.359H268.5V185.406ZM264.156 183.375C264.156 184.328 264.023 185.258 263.758 186.164C263.492 187.065 263.109 187.875 262.609 188.594C262.115 189.307 261.536 189.865 260.875 190.266L260.094 189.344C260.719 188.979 261.266 188.479 261.734 187.844C262.203 187.208 262.562 186.505 262.812 185.734C263.062 184.958 263.188 184.172 263.188 183.375V180.688H264.156V183.375ZM264.375 183.328C264.375 184.073 264.492 184.815 264.727 185.555C264.961 186.289 265.297 186.961 265.734 187.57C266.177 188.18 266.698 188.661 267.297 189.016L266.594 189.969C265.938 189.573 265.37 189.023 264.891 188.32C264.411 187.617 264.047 186.833 263.797 185.969C263.552 185.104 263.432 184.224 263.438 183.328V180.688H264.375V183.328ZM272.156 193.266H270.969V179.375H272.156V193.266ZM269.281 192.562H268.125V179.672H269.281V192.562ZM278.438 190.703H277.234V186.547H278.438V190.703ZM283.641 190.703H282.406V186.547H283.641V190.703ZM286.797 191.484H274.078V190.453H286.797V191.484ZM280.406 180.25C281.391 180.255 282.266 180.406 283.031 180.703C283.802 180.995 284.404 181.414 284.836 181.961C285.268 182.503 285.484 183.125 285.484 183.828C285.484 184.536 285.268 185.159 284.836 185.695C284.404 186.232 283.802 186.648 283.031 186.945C282.266 187.242 281.391 187.391 280.406 187.391C279.422 187.391 278.544 187.242 277.773 186.945C277.008 186.648 276.409 186.232 275.977 185.695C275.544 185.159 275.328 184.536 275.328 183.828C275.328 183.125 275.544 182.503 275.977 181.961C276.409 181.414 277.008 180.995 277.773 180.703C278.544 180.406 279.422 180.255 280.406 180.25ZM280.406 181.266C279.651 181.26 278.977 181.365 278.383 181.578C277.794 181.786 277.336 182.086 277.008 182.477C276.68 182.867 276.516 183.318 276.516 183.828C276.516 184.339 276.68 184.789 277.008 185.18C277.336 185.57 277.794 185.875 278.383 186.094C278.977 186.312 279.651 186.422 280.406 186.422C281.156 186.422 281.826 186.312 282.414 186.094C283.003 185.875 283.464 185.57 283.797 185.18C284.13 184.789 284.297 184.339 284.297 183.828C284.297 183.318 284.13 182.867 283.797 182.477C283.464 182.086 283.003 181.786 282.414 181.578C281.826 181.365 281.156 181.26 280.406 181.266ZM54.0312 213.547H52.8125V203.391H54.0312V213.547ZM54.4688 216.969H45.0625V215.938H54.4688V216.969ZM46.2812 216.281H45.0625V212.516H46.2812V216.281ZM46.5312 204.359C47.2188 204.359 47.8385 204.505 48.3906 204.797C48.9427 205.089 49.3776 205.492 49.6953 206.008C50.013 206.523 50.1719 207.109 50.1719 207.766C50.1719 208.427 50.013 209.018 49.6953 209.539C49.3776 210.055 48.9427 210.458 48.3906 210.75C47.8385 211.042 47.2188 211.188 46.5312 211.188C45.8438 211.188 45.224 211.042 44.6719 210.75C44.1198 210.458 43.6849 210.055 43.3672 209.539C43.0495 209.018 42.8906 208.427 42.8906 207.766C42.8906 207.109 43.0495 206.523 43.3672 206.008C43.6849 205.492 44.1198 205.089 44.6719 204.797C45.224 204.505 45.8438 204.359 46.5312 204.359ZM46.5312 205.438C46.0677 205.438 45.6484 205.536 45.2734 205.734C44.9036 205.932 44.612 206.208 44.3984 206.562C44.1901 206.917 44.0885 207.318 44.0938 207.766C44.0885 208.219 44.1901 208.625 44.3984 208.984C44.612 209.339 44.9036 209.615 45.2734 209.812C45.6484 210.01 46.0677 210.109 46.5312 210.109C46.9896 210.109 47.4036 210.01 47.7734 209.812C48.1432 209.615 48.4349 209.339 48.6484 208.984C48.862 208.625 48.9688 208.219 48.9688 207.766C48.9688 207.318 48.862 206.917 48.6484 206.562C48.4349 206.208 48.1432 205.932 47.7734 205.734C47.4036 205.536 46.9896 205.438 46.5312 205.438ZM61.625 213.453H60.3906V210.359H61.625V213.453ZM67.8438 213.938H66.6094V203.391H67.8438V213.938ZM68.1875 216.969H58.3125V215.938H68.1875V216.969ZM59.5469 216.234H58.3125V212.906H59.5469V216.234ZM56.3125 209.828C58.1719 209.818 59.8177 209.789 61.25 209.742C62.6823 209.69 64.0521 209.583 65.3594 209.422L65.4375 210.312C64.0885 210.526 62.6745 210.667 61.1953 210.734C59.7161 210.802 58.1458 210.833 56.4844 210.828L56.3125 209.828ZM66.9375 212.5H63.7344V211.609H66.9375V212.5ZM60.875 203.953C61.5469 203.953 62.1432 204.052 62.6641 204.25C63.1901 204.448 63.5964 204.732 63.8828 205.102C64.1693 205.471 64.3125 205.896 64.3125 206.375C64.3125 206.865 64.1693 207.289 63.8828 207.648C63.5964 208.008 63.1927 208.286 62.6719 208.484C62.151 208.682 61.5521 208.781 60.875 208.781C60.1927 208.781 59.5911 208.682 59.0703 208.484C58.5547 208.286 58.1536 208.008 57.8672 207.648C57.5807 207.289 57.4375 206.865 57.4375 206.375C57.4375 205.896 57.5807 205.471 57.8672 205.102C58.1536 204.732 58.5573 204.448 59.0781 204.25C59.599 204.052 60.1979 203.953 60.875 203.953ZM60.875 204.891C60.4271 204.885 60.0312 204.945 59.6875 205.07C59.3438 205.19 59.0755 205.365 58.8828 205.594C58.6953 205.823 58.6042 206.083 58.6094 206.375C58.6042 206.672 58.6953 206.935 58.8828 207.164C59.0755 207.388 59.3438 207.562 59.6875 207.688C60.0312 207.812 60.4271 207.875 60.875 207.875C61.3125 207.875 61.7031 207.812 62.0469 207.688C62.3906 207.562 62.6589 207.388 62.8516 207.164C63.0443 206.935 63.1406 206.672 63.1406 206.375C63.1406 206.083 63.0443 205.823 62.8516 205.594C62.6589 205.365 62.3906 205.19 62.0469 205.07C61.7031 204.945 61.3125 204.885 60.875 204.891ZM84.9688 206.969H80.9219V205.938H84.9688V206.969ZM85.0156 209.938H80.9219V208.922H85.0156V209.938ZM85.75 213.672H84.5156V203.391H85.75V213.672ZM86.0625 216.969H76.7656V215.938H86.0625V216.969ZM78 216.438H76.7656V212.656H78V216.438ZM76.1562 206.781H80.0312V204.312H81.2344V211.297H74.9375V204.312H76.1562V206.781ZM80.0312 210.281V207.75H76.1562V210.281H80.0312ZM100.734 211.234H88.0625V210.25H100.734V211.234ZM94.9844 210.672H93.7969V208.016H94.9844V210.672ZM99.25 208.625H89.6719V207.625H99.25V208.625ZM99.1562 205.016H90.875V208.234H89.6719V204.031H99.1562V205.016ZM94.3906 212.25C95.3802 212.25 96.2318 212.349 96.9453 212.547C97.6589 212.745 98.2057 213.031 98.5859 213.406C98.9714 213.776 99.1667 214.224 99.1719 214.75C99.1667 215.281 98.974 215.732 98.5938 216.102C98.2188 216.471 97.6719 216.755 96.9531 216.953C96.2344 217.156 95.3802 217.26 94.3906 217.266C93.3906 217.26 92.5312 217.156 91.8125 216.953C91.0938 216.755 90.5443 216.469 90.1641 216.094C89.7839 215.724 89.5938 215.276 89.5938 214.75C89.5938 214.224 89.7839 213.776 90.1641 213.406C90.5443 213.031 91.0938 212.745 91.8125 212.547C92.5312 212.349 93.3906 212.25 94.3906 212.25ZM94.3906 213.219C93.651 213.219 93.0156 213.279 92.4844 213.398C91.9531 213.518 91.5443 213.695 91.2578 213.93C90.9766 214.159 90.8385 214.432 90.8438 214.75C90.8385 215.073 90.9766 215.349 91.2578 215.578C91.5443 215.807 91.9531 215.982 92.4844 216.102C93.0156 216.221 93.651 216.281 94.3906 216.281C95.1198 216.281 95.75 216.221 96.2812 216.102C96.8125 215.982 97.2214 215.807 97.5078 215.578C97.7943 215.349 97.9375 215.073 97.9375 214.75C97.9375 214.432 97.7943 214.159 97.5078 213.93C97.2214 213.695 96.8125 213.518 96.2812 213.398C95.75 213.279 95.1198 213.219 94.3906 213.219ZM108.219 203.625C109.245 203.625 110.125 203.716 110.859 203.898C111.599 204.081 112.161 204.352 112.547 204.711C112.932 205.07 113.125 205.505 113.125 206.016C113.125 206.536 112.932 206.979 112.547 207.344C112.161 207.708 111.602 207.984 110.867 208.172C110.133 208.354 109.25 208.448 108.219 208.453C107.182 208.448 106.297 208.354 105.562 208.172C104.833 207.984 104.273 207.708 103.883 207.344C103.492 206.979 103.297 206.536 103.297 206.016C103.297 205.505 103.492 205.07 103.883 204.711C104.273 204.352 104.836 204.081 105.57 203.898C106.305 203.716 107.188 203.625 108.219 203.625ZM108.219 204.547C107.453 204.547 106.797 204.607 106.25 204.727C105.708 204.846 105.292 205.016 105 205.234C104.713 205.453 104.573 205.714 104.578 206.016C104.573 206.333 104.713 206.607 105 206.836C105.292 207.06 105.708 207.229 106.25 207.344C106.797 207.458 107.453 207.516 108.219 207.516C108.984 207.516 109.641 207.458 110.188 207.344C110.74 207.229 111.159 207.06 111.445 206.836C111.732 206.612 111.875 206.339 111.875 206.016C111.875 205.714 111.732 205.453 111.445 205.234C111.159 205.016 110.74 204.846 110.188 204.727C109.635 204.607 108.979 204.547 108.219 204.547ZM114.547 210.391H101.891V209.391H114.547V210.391ZM112.922 214.703H104.672V216.391H103.453V213.797H111.719V212.531H103.422V211.594H112.922V214.703ZM113.344 217.109H103.453V216.141H113.344V217.109ZM131.219 217.266H129.984V203.375H131.219V217.266ZM127.109 204.891C127.104 206.266 126.875 207.552 126.422 208.75C125.974 209.948 125.266 211.052 124.297 212.062C123.328 213.068 122.089 213.932 120.578 214.656L119.906 213.656C121.245 213.021 122.357 212.271 123.242 211.406C124.133 210.542 124.794 209.583 125.227 208.531C125.664 207.474 125.885 206.323 125.891 205.078V204.891H127.109ZM126.391 205.891H120.547V204.891H126.391V205.891ZM140.188 205.109C140.188 205.865 139.94 206.552 139.445 207.172C138.951 207.786 138.292 208.297 137.469 208.703C136.651 209.104 135.76 209.375 134.797 209.516L134.344 208.547C135.167 208.432 135.943 208.208 136.672 207.875C137.401 207.542 137.987 207.135 138.43 206.656C138.872 206.177 139.094 205.661 139.094 205.109V204.688H140.188V205.109ZM140.688 205.109C140.688 205.661 140.911 206.177 141.359 206.656C141.807 207.135 142.396 207.542 143.125 207.875C143.859 208.208 144.641 208.432 145.469 208.547L144.984 209.516C144.026 209.375 143.135 209.104 142.312 208.703C141.49 208.297 140.831 207.786 140.336 207.172C139.841 206.552 139.594 205.865 139.594 205.109V204.688H140.688V205.109ZM145.094 205.078H134.719V204.078H145.094V205.078ZM146.266 211.547H133.547V210.531H146.266V211.547ZM140.609 214.391H139.391V211.156H140.609V214.391ZM144.844 216.969H135.172V215.938H144.844V216.969ZM136.406 216.328H135.172V213H136.406V216.328ZM153.719 204.281C154.682 204.281 155.549 204.44 156.32 204.758C157.096 205.076 157.703 205.523 158.141 206.102C158.578 206.68 158.797 207.344 158.797 208.094C158.797 208.849 158.578 209.518 158.141 210.102C157.703 210.68 157.096 211.128 156.32 211.445C155.549 211.758 154.682 211.911 153.719 211.906C152.755 211.911 151.888 211.758 151.117 211.445C150.352 211.128 149.747 210.68 149.305 210.102C148.862 209.518 148.641 208.849 148.641 208.094C148.641 207.344 148.862 206.68 149.305 206.102C149.747 205.523 150.352 205.076 151.117 204.758C151.888 204.44 152.755 204.281 153.719 204.281ZM153.719 205.281C152.979 205.281 152.312 205.398 151.719 205.633C151.125 205.867 150.656 206.201 150.312 206.633C149.974 207.06 149.807 207.547 149.812 208.094C149.807 208.646 149.974 209.135 150.312 209.562C150.656 209.99 151.122 210.32 151.711 210.555C152.305 210.789 152.974 210.906 153.719 210.906C154.458 210.906 155.125 210.789 155.719 210.555C156.312 210.32 156.776 209.99 157.109 209.562C157.443 209.135 157.609 208.646 157.609 208.094C157.609 207.547 157.44 207.06 157.102 206.633C156.763 206.201 156.297 205.867 155.703 205.633C155.115 205.398 154.453 205.281 153.719 205.281ZM160.109 215.422H147.391V214.391H160.109V215.422ZM173.938 215.547H161.219V214.516H173.938V215.547ZM168.141 214.969H166.938V211.531H168.141V214.969ZM172.328 208.609H164.031V211.422H162.812V207.609H171.125V205.422H162.781V204.406H172.328V208.609ZM172.656 211.891H162.812V210.875H172.656V211.891ZM189.719 206.344H185.734V205.359H189.719V206.344ZM189.75 208.953H185.734V207.984H189.75V208.953ZM186.172 210.125H179.719V204.234H186.172V210.125ZM180.938 209.156H184.969V205.219H180.938V209.156ZM190.562 211.375H189.344V203.375H190.562V211.375ZM186.562 213.266C186.562 213.911 186.318 214.51 185.828 215.062C185.339 215.615 184.688 216.078 183.875 216.453C183.068 216.828 182.198 217.078 181.266 217.203L180.844 216.266C181.635 216.177 182.393 215.984 183.117 215.688C183.841 215.385 184.424 215.021 184.867 214.594C185.31 214.161 185.531 213.719 185.531 213.266V212.984H186.562V213.266ZM186.781 213.266C186.776 213.703 186.99 214.135 187.422 214.562C187.859 214.99 188.432 215.357 189.141 215.664C189.854 215.966 190.604 216.167 191.391 216.266L190.969 217.203C190.036 217.073 189.169 216.815 188.367 216.43C187.57 216.049 186.93 215.583 186.445 215.031C185.961 214.479 185.719 213.891 185.719 213.266V212.984H186.781V213.266ZM190.891 213.266H181.406V212.297H190.891V213.266ZM186.781 212.844H185.531V210.953H186.781V212.844ZM201.328 207.906C201.323 208.859 201.154 209.781 200.82 210.672C200.492 211.557 200.036 212.341 199.453 213.023C198.87 213.706 198.214 214.224 197.484 214.578L196.781 213.625C197.453 213.312 198.06 212.857 198.602 212.258C199.148 211.659 199.576 210.982 199.883 210.227C200.19 209.466 200.344 208.693 200.344 207.906V206.656H201.328V207.906ZM201.531 207.906C201.531 208.641 201.682 209.367 201.984 210.086C202.286 210.799 202.698 211.448 203.219 212.031C203.745 212.609 204.339 213.057 205 213.375L204.281 214.328C203.562 213.974 202.924 213.466 202.367 212.805C201.81 212.143 201.372 211.388 201.055 210.539C200.737 209.685 200.578 208.807 200.578 207.906V206.656H201.531V207.906ZM204.688 206.797H197.156V205.797H204.688V206.797ZM201.562 206.359H200.328V203.641H201.562V206.359ZM207.656 217.266H206.438V203.375H207.656V217.266ZM209.984 210.125H207.375V209.078H209.984V210.125ZM222.203 213.547H220.984V203.391H222.203V213.547ZM222.641 216.969H213.234V215.938H222.641V216.969ZM214.453 216.281H213.234V212.516H214.453V216.281ZM214.703 204.359C215.391 204.359 216.01 204.505 216.562 204.797C217.115 205.089 217.549 205.492 217.867 206.008C218.185 206.523 218.344 207.109 218.344 207.766C218.344 208.427 218.185 209.018 217.867 209.539C217.549 210.055 217.115 210.458 216.562 210.75C216.01 211.042 215.391 211.188 214.703 211.188C214.016 211.188 213.396 211.042 212.844 210.75C212.292 210.458 211.857 210.055 211.539 209.539C211.221 209.018 211.062 208.427 211.062 207.766C211.062 207.109 211.221 206.523 211.539 206.008C211.857 205.492 212.292 205.089 212.844 204.797C213.396 204.505 214.016 204.359 214.703 204.359ZM214.703 205.438C214.24 205.438 213.82 205.536 213.445 205.734C213.076 205.932 212.784 206.208 212.57 206.562C212.362 206.917 212.26 207.318 212.266 207.766C212.26 208.219 212.362 208.625 212.57 208.984C212.784 209.339 213.076 209.615 213.445 209.812C213.82 210.01 214.24 210.109 214.703 210.109C215.161 210.109 215.576 210.01 215.945 209.812C216.315 209.615 216.607 209.339 216.82 208.984C217.034 208.625 217.141 208.219 217.141 207.766C217.141 207.318 217.034 206.917 216.82 206.562C216.607 206.208 216.315 205.932 215.945 205.734C215.576 205.536 215.161 205.438 214.703 205.438ZM229.312 207.641C229.312 208.599 229.13 209.544 228.766 210.477C228.401 211.409 227.911 212.237 227.297 212.961C226.688 213.685 226.021 214.229 225.297 214.594L224.562 213.625C225.224 213.307 225.839 212.828 226.406 212.188C226.979 211.542 227.438 210.818 227.781 210.016C228.125 209.214 228.297 208.422 228.297 207.641V205.344H229.312V207.641ZM229.531 207.641C229.531 208.406 229.703 209.169 230.047 209.93C230.391 210.685 230.849 211.359 231.422 211.953C231.995 212.547 232.62 212.99 233.297 213.281L232.609 214.25C231.854 213.906 231.167 213.396 230.547 212.719C229.932 212.042 229.443 211.263 229.078 210.383C228.719 209.497 228.542 208.583 228.547 207.641V205.344H229.531V207.641ZM232.844 205.828H225.016V204.812H232.844V205.828ZM236.016 217.266H234.781V203.375H236.016V217.266ZM255.406 209.953H252.844V208.922H255.406V209.953ZM253.156 217.266H251.938V203.375H253.156V217.266ZM244.203 213.344H242.984V204.75H244.203V213.344ZM244.094 212.703C245.193 212.708 246.273 212.661 247.336 212.562C248.398 212.464 249.484 212.297 250.594 212.062L250.75 213.109C249.62 213.339 248.513 213.5 247.43 213.594C246.346 213.688 245.234 213.734 244.094 213.734H242.984V212.703H244.094ZM261.453 216.844H260.219V211.219H261.453V216.844ZM267.734 217.281H266.516V203.391H267.734V217.281ZM256.484 210.828C258.167 210.823 259.755 210.794 261.25 210.742C262.745 210.685 264.156 210.583 265.484 210.438L265.547 211.359C264.177 211.557 262.755 211.69 261.281 211.758C259.807 211.826 258.214 211.865 256.5 211.875H256.328L256.172 210.828H256.484ZM264.312 208.859H257.547V207.828H264.312V208.859ZM258.766 208.125H257.547V204.328H258.766V208.125ZM273.797 204.453C274.469 204.453 275.068 204.651 275.594 205.047C276.125 205.443 276.536 206.008 276.828 206.742C277.12 207.477 277.266 208.328 277.266 209.297C277.266 210.271 277.12 211.122 276.828 211.852C276.536 212.576 276.125 213.135 275.594 213.531C275.068 213.927 274.469 214.125 273.797 214.125C273.115 214.125 272.508 213.927 271.977 213.531C271.451 213.135 271.042 212.576 270.75 211.852C270.458 211.122 270.312 210.271 270.312 209.297C270.312 208.328 270.458 207.477 270.75 206.742C271.042 206.008 271.451 205.443 271.977 205.047C272.508 204.651 273.115 204.453 273.797 204.453ZM273.797 205.547C273.344 205.547 272.943 205.703 272.594 206.016C272.25 206.328 271.979 206.768 271.781 207.336C271.583 207.898 271.484 208.552 271.484 209.297C271.484 210.042 271.583 210.698 271.781 211.266C271.979 211.828 272.25 212.263 272.594 212.57C272.943 212.878 273.344 213.031 273.797 213.031C274.245 213.031 274.646 212.878 275 212.57C275.354 212.263 275.628 211.826 275.82 211.258C276.013 210.69 276.109 210.036 276.109 209.297C276.109 208.557 276.013 207.904 275.82 207.336C275.628 206.768 275.354 206.328 275 206.016C274.646 205.703 274.245 205.547 273.797 205.547ZM281.578 217.297H280.359V203.375H281.578V217.297ZM280.906 209.703H276.859V208.688H280.906V209.703ZM295.406 217.266H294.172V203.375H295.406V217.266ZM288.469 207.5C288.464 208.469 288.286 209.424 287.938 210.367C287.594 211.31 287.125 212.151 286.531 212.891C285.943 213.625 285.302 214.188 284.609 214.578L283.797 213.641C284.453 213.312 285.062 212.82 285.625 212.164C286.188 211.503 286.635 210.763 286.969 209.945C287.302 209.122 287.469 208.307 287.469 207.5V205.344H288.469V207.5ZM288.703 207.5C288.703 208.214 288.87 208.958 289.203 209.734C289.536 210.505 289.979 211.211 290.531 211.852C291.089 212.487 291.693 212.969 292.344 213.297L291.609 214.234C290.906 213.87 290.258 213.328 289.664 212.609C289.076 211.891 288.604 211.081 288.25 210.18C287.896 209.279 287.719 208.385 287.719 207.5V205.344H288.703V207.5ZM291.875 205.828H284.297V204.812H291.875V205.828ZM294.969 208.328H291.328V207.297H294.969V208.328ZM294.969 211.281H291.328V210.25H294.969V211.281ZM302.078 214.703H300.875V210.547H302.078V214.703ZM307.281 214.703H306.047V210.547H307.281V214.703ZM310.438 215.484H297.719V214.453H310.438V215.484ZM304.047 204.25C305.031 204.255 305.906 204.406 306.672 204.703C307.443 204.995 308.044 205.414 308.477 205.961C308.909 206.503 309.125 207.125 309.125 207.828C309.125 208.536 308.909 209.159 308.477 209.695C308.044 210.232 307.443 210.648 306.672 210.945C305.906 211.242 305.031 211.391 304.047 211.391C303.062 211.391 302.185 211.242 301.414 210.945C300.648 210.648 300.049 210.232 299.617 209.695C299.185 209.159 298.969 208.536 298.969 207.828C298.969 207.125 299.185 206.503 299.617 205.961C300.049 205.414 300.648 204.995 301.414 204.703C302.185 204.406 303.062 204.255 304.047 204.25ZM304.047 205.266C303.292 205.26 302.617 205.365 302.023 205.578C301.435 205.786 300.977 206.086 300.648 206.477C300.32 206.867 300.156 207.318 300.156 207.828C300.156 208.339 300.32 208.789 300.648 209.18C300.977 209.57 301.435 209.875 302.023 210.094C302.617 210.312 303.292 210.422 304.047 210.422C304.797 210.422 305.466 210.312 306.055 210.094C306.643 209.875 307.104 209.57 307.438 209.18C307.771 208.789 307.938 208.339 307.938 207.828C307.938 207.318 307.771 206.867 307.438 206.477C307.104 206.086 306.643 205.786 306.055 205.578C305.466 205.365 304.797 205.26 304.047 205.266Z" fill="#929195"/> +<path d="M380 230H50C45.5817 230 42 233.582 42 238V246C42 250.418 45.5817 254 50 254H380C384.418 254 388 250.418 388 246V238C388 233.582 384.418 230 380 230Z" fill="white"/> +<path d="M50.6602 243.188H47.9883V242.426H50.6602V243.188ZM51.0585 247.184H50.1327V239.543H51.0585V247.184ZM51.3516 249.727H44.3672V248.953H51.3516V249.727ZM45.2929 249.328H44.3672V246.492H45.2929V249.328ZM45.8789 241.688C45.8789 242.309 45.7559 242.896 45.5098 243.451C45.2637 244.002 44.918 244.486 44.4727 244.904C44.0312 245.318 43.5234 245.633 42.9492 245.848L42.4688 245.098C42.9765 244.918 43.4316 244.654 43.834 244.307C44.2363 243.959 44.5508 243.559 44.7773 243.105C45.0039 242.648 45.1172 242.176 45.1172 241.688V240.832H45.8789V241.688ZM46.0429 241.688C46.0429 242.133 46.1522 242.566 46.371 242.988C46.5897 243.41 46.8926 243.785 47.2793 244.113C47.666 244.441 48.1094 244.691 48.6094 244.863L48.1289 245.602C47.5703 245.398 47.0762 245.1 46.6465 244.705C46.2207 244.311 45.8887 243.854 45.6504 243.334C45.4121 242.814 45.2929 242.266 45.2929 241.688V240.832H46.0429V241.688ZM48.375 241.148H42.7617V240.387H48.375V241.148ZM59.0858 244.43H57.082V243.645H59.0858V244.43ZM55.6875 242.742C55.6836 243.438 55.584 244.117 55.3887 244.781C55.1973 245.445 54.918 246.043 54.5508 246.574C54.1875 247.102 53.7578 247.516 53.2617 247.816L52.7108 247.113C53.1718 246.848 53.5723 246.482 53.9121 246.018C54.252 245.553 54.5117 245.035 54.6914 244.465C54.875 243.895 54.9688 243.32 54.9727 242.742V242.191H55.6875V242.742ZM55.8398 242.742C55.8438 243.305 55.9355 243.855 56.1152 244.395C56.2988 244.934 56.5625 245.424 56.9062 245.865C57.25 246.303 57.6523 246.645 58.1133 246.891L57.5858 247.582C57.0819 247.309 56.6444 246.92 56.2733 246.416C55.9061 245.912 55.6229 245.342 55.4237 244.705C55.2284 244.068 55.1328 243.414 55.1367 242.742V242.191H55.8398V242.742ZM57.7969 242.227H52.9922V241.465H57.7969V242.227ZM55.8516 242.039H54.9727V239.918H55.8516V242.039ZM61.6992 249.949H60.8203V239.531H61.6992V249.949ZM59.5898 249.41H58.7226V239.789H59.5898V249.41ZM69.7383 242.73C69.7383 243.449 69.6015 244.158 69.328 244.857C69.0546 245.557 68.6875 246.178 68.2266 246.721C67.7695 247.264 67.2695 247.672 66.7266 247.945L66.1758 247.219C66.6719 246.98 67.1328 246.621 67.5586 246.141C67.9883 245.656 68.332 245.113 68.5898 244.512C68.8477 243.91 68.9766 243.316 68.9766 242.73V241.008H69.7383V242.73ZM69.9023 242.73C69.9023 243.305 70.0312 243.877 70.2891 244.447C70.5469 245.014 70.8906 245.52 71.3203 245.965C71.75 246.41 72.2188 246.742 72.7266 246.961L72.2108 247.688C71.6444 247.43 71.1289 247.047 70.6641 246.539C70.2031 246.031 69.8359 245.447 69.5625 244.787C69.293 244.123 69.1602 243.438 69.1641 242.73V241.008H69.9023V242.73ZM72.3867 241.371H66.5155V240.609H72.3867V241.371ZM74.7655 249.949H73.8398V239.531H74.7655V249.949ZM81.7383 246.293H80.8358V244.711H81.7383V246.293ZM86.0391 244.887H76.5586V244.172H86.0391V244.887ZM81.7383 240.738H80.8358V239.473H81.7383V240.738ZM81.5976 240.984C81.5976 241.512 81.4061 241.969 81.0233 242.355C80.6405 242.738 80.1269 243.041 79.4823 243.264C78.8417 243.482 78.125 243.625 77.332 243.691L77.0625 242.988C77.75 242.945 78.377 242.838 78.9434 242.666C79.5098 242.49 79.959 242.26 80.291 241.975C80.623 241.686 80.7891 241.355 80.7891 240.984V240.832H81.5976V240.984ZM81.7969 240.984C81.793 241.355 81.957 241.686 82.2891 241.975C82.625 242.26 83.0742 242.49 83.6367 242.666C84.2031 242.838 84.8319 242.945 85.5233 242.988L85.2421 243.691C84.453 243.625 83.7382 243.482 83.0976 243.264C82.4569 243.041 81.9453 242.738 81.5625 242.355C81.1797 241.969 80.9883 241.512 80.9883 240.984V240.832H81.7969V240.984ZM85.078 241.172H77.5312V240.445H85.078V241.172ZM84.8203 248.109H78.6328V249.387H77.7188V247.453H83.9179V246.551H77.6953V245.859H84.8203V248.109ZM85.1367 249.832H77.7188V249.129H85.1367V249.832ZM97.9102 240.855H91.1367V240.094H97.9102V240.855ZM99.4688 244.688H89.9297V243.926H99.4688V244.688ZM98.2147 240.867C98.2147 241.473 98.1952 242.023 98.1561 242.52C98.1171 243.012 98.0234 243.578 97.875 244.219L96.9608 244.16C97.0663 243.73 97.1425 243.326 97.1894 242.947C97.2401 242.568 97.2715 242.236 97.2832 241.951C97.2949 241.662 97.3007 241.324 97.3007 240.938V240.867V240.094H98.2147V240.867ZM98.2617 249.809H91.1016V246.129H98.2617V249.809ZM92.0156 249.059H97.3477V246.855H92.0156V249.059ZM102.797 240.188C103.25 240.188 103.658 240.291 104.021 240.498C104.385 240.705 104.67 240.996 104.877 241.371C105.084 241.746 105.187 242.172 105.187 242.648C105.187 243.125 105.084 243.547 104.877 243.914C104.67 244.281 104.385 244.568 104.021 244.775C103.662 244.982 103.254 245.086 102.797 245.086C102.336 245.086 101.926 244.982 101.566 244.775C101.207 244.568 100.926 244.281 100.723 243.914C100.519 243.547 100.418 243.125 100.418 242.648C100.418 242.172 100.519 241.746 100.723 241.371C100.926 240.996 101.207 240.705 101.566 240.498C101.926 240.291 102.336 240.188 102.797 240.188ZM102.797 240.984C102.5 240.984 102.234 241.055 102 241.195C101.766 241.336 101.58 241.535 101.443 241.793C101.31 242.047 101.246 242.332 101.25 242.648C101.246 242.965 101.31 243.25 101.443 243.504C101.58 243.754 101.766 243.951 102 244.096C102.234 244.24 102.5 244.312 102.797 244.312C103.09 244.312 103.353 244.24 103.588 244.096C103.826 243.951 104.012 243.754 104.144 243.504C104.277 243.25 104.344 242.965 104.344 242.648C104.344 242.332 104.277 242.047 104.144 241.793C104.012 241.535 103.826 241.336 103.588 241.195C103.353 241.055 103.09 240.984 102.797 240.984ZM109.148 245.742H108.269V239.543H109.148V245.742ZM108.551 242.988H106.547V242.227H108.551V242.988ZM106.887 245.672H106.019V239.742H106.887V245.672ZM109.148 249.949H108.246V247.066H102.129V246.328H109.148V249.949Z" fill="#B2B1B6"/> +<path d="M309.047 246.969L312.906 242.906C313.411 242.365 313.797 241.927 314.062 241.594C314.333 241.26 314.539 240.943 314.68 240.641C314.82 240.333 314.891 240.01 314.891 239.672C314.891 239.292 314.792 238.958 314.594 238.672C314.396 238.38 314.125 238.154 313.781 237.992C313.443 237.831 313.062 237.75 312.641 237.75C312.198 237.75 311.81 237.839 311.477 238.016C311.148 238.193 310.893 238.443 310.711 238.766C310.529 239.083 310.438 239.453 310.438 239.875H309.109C309.104 239.219 309.255 238.638 309.562 238.133C309.875 237.628 310.305 237.234 310.852 236.953C311.398 236.672 312.01 236.531 312.688 236.531C313.359 236.531 313.961 236.669 314.492 236.945C315.029 237.221 315.448 237.599 315.75 238.078C316.052 238.557 316.203 239.089 316.203 239.672C316.198 240.104 316.117 240.518 315.961 240.914C315.81 241.305 315.549 241.74 315.18 242.219C314.81 242.698 314.286 243.286 313.609 243.984L311.016 246.656V246.75H316.406V248H309.062L309.047 246.969ZM322.219 236.531C322.938 236.542 323.607 236.714 324.227 237.047C324.846 237.38 325.352 237.945 325.742 238.742C326.133 239.534 326.328 240.583 326.328 241.891C326.328 243.214 326.156 244.344 325.812 245.281C325.469 246.219 324.974 246.932 324.328 247.422C323.682 247.911 322.917 248.156 322.031 248.156C321.375 248.156 320.786 248.029 320.266 247.773C319.745 247.518 319.32 247.167 318.992 246.719C318.664 246.266 318.453 245.74 318.359 245.141H319.75C319.833 245.49 319.977 245.797 320.18 246.062C320.383 246.323 320.641 246.529 320.953 246.68C321.266 246.831 321.625 246.906 322.031 246.906C322.646 246.906 323.177 246.734 323.625 246.391C324.073 246.047 324.414 245.552 324.648 244.906C324.888 244.255 325.01 243.474 325.016 242.562H324.859C324.641 242.875 324.383 243.143 324.086 243.367C323.789 243.591 323.461 243.763 323.102 243.883C322.742 244.003 322.365 244.062 321.969 244.062C321.297 244.062 320.677 243.901 320.109 243.578C319.547 243.255 319.099 242.81 318.766 242.242C318.432 241.674 318.266 241.036 318.266 240.328C318.266 239.625 318.43 238.984 318.758 238.406C319.086 237.823 319.549 237.365 320.148 237.031C320.747 236.693 321.438 236.526 322.219 236.531ZM322.219 237.766C321.734 237.766 321.294 237.88 320.898 238.109C320.508 238.339 320.198 238.648 319.969 239.039C319.745 239.43 319.635 239.854 319.641 240.312C319.641 240.776 319.75 241.201 319.969 241.586C320.188 241.966 320.487 242.268 320.867 242.492C321.253 242.716 321.688 242.828 322.172 242.828C322.651 242.828 323.091 242.708 323.492 242.469C323.893 242.229 324.211 241.914 324.445 241.523C324.68 241.133 324.797 240.719 324.797 240.281C324.797 239.849 324.685 239.44 324.461 239.055C324.237 238.664 323.927 238.352 323.531 238.117C323.141 237.883 322.703 237.766 322.219 237.766ZM327.984 244.531L333.078 236.688H333.922V238.469H333.328L329.5 244.359V244.453H336.391V245.688H327.984V244.531ZM333.469 245.344V244.797V236.688H334.812V248H333.469V245.344ZM338.297 251.203H337.141L338 246.953H339.516L338.297 251.203ZM345.281 248.156C344.5 248.156 343.805 248.021 343.195 247.75C342.586 247.479 342.112 247.104 341.773 246.625C341.435 246.146 341.266 245.604 341.266 245C341.266 244.521 341.367 244.073 341.57 243.656C341.773 243.24 342.049 242.898 342.398 242.633C342.747 242.362 343.135 242.193 343.562 242.125V242.062C343.193 241.979 342.867 241.815 342.586 241.57C342.31 241.326 342.094 241.026 341.938 240.672C341.781 240.318 341.703 239.938 341.703 239.531C341.703 238.964 341.857 238.453 342.164 238C342.471 237.542 342.896 237.182 343.438 236.922C343.984 236.661 344.599 236.531 345.281 236.531C345.958 236.531 346.57 236.661 347.117 236.922C347.664 237.182 348.091 237.542 348.398 238C348.711 238.453 348.87 238.964 348.875 239.531C348.87 239.938 348.786 240.318 348.625 240.672C348.469 241.026 348.25 241.326 347.969 241.57C347.688 241.815 347.365 241.979 347 242.062V242.125C347.422 242.193 347.807 242.362 348.156 242.633C348.51 242.898 348.789 243.24 348.992 243.656C349.201 244.073 349.307 244.521 349.312 245C349.307 245.604 349.133 246.146 348.789 246.625C348.451 247.104 347.974 247.479 347.359 247.75C346.75 248.021 346.057 248.156 345.281 248.156ZM345.281 246.922C345.812 246.922 346.276 246.836 346.672 246.664C347.068 246.492 347.372 246.258 347.586 245.961C347.799 245.664 347.906 245.318 347.906 244.922C347.906 244.51 347.794 244.141 347.57 243.812C347.346 243.479 347.034 243.219 346.633 243.031C346.232 242.844 345.781 242.75 345.281 242.75C344.781 242.75 344.333 242.844 343.938 243.031C343.542 243.219 343.229 243.479 343 243.812C342.776 244.141 342.667 244.51 342.672 244.922C342.667 245.318 342.768 245.664 342.977 245.961C343.19 246.258 343.492 246.492 343.883 246.664C344.279 246.836 344.745 246.922 345.281 246.922ZM345.281 241.562C345.708 241.562 346.091 241.479 346.43 241.312C346.768 241.146 347.031 240.919 347.219 240.633C347.406 240.346 347.5 240.016 347.5 239.641C347.5 239.266 347.409 238.935 347.227 238.648C347.044 238.362 346.784 238.141 346.445 237.984C346.107 237.828 345.719 237.75 345.281 237.75C344.839 237.75 344.451 237.828 344.117 237.984C343.789 238.141 343.531 238.362 343.344 238.648C343.156 238.935 343.062 239.266 343.062 239.641C343.062 240.016 343.159 240.346 343.352 240.633C343.544 240.919 343.807 241.146 344.141 241.312C344.474 241.479 344.854 241.562 345.281 241.562ZM354.906 248.156C354.073 248.156 353.362 247.93 352.773 247.477C352.185 247.023 351.734 246.362 351.422 245.492C351.109 244.622 350.953 243.573 350.953 242.344C350.953 241.13 351.109 240.089 351.422 239.219C351.734 238.344 352.185 237.677 352.773 237.219C353.367 236.76 354.078 236.531 354.906 236.531C355.729 236.531 356.438 236.76 357.031 237.219C357.625 237.677 358.078 238.344 358.391 239.219C358.703 240.089 358.859 241.13 358.859 242.344C358.859 243.573 358.706 244.622 358.398 245.492C358.091 246.362 357.641 247.023 357.047 247.477C356.453 247.93 355.74 248.156 354.906 248.156ZM354.906 246.906C355.448 246.906 355.914 246.729 356.305 246.375C356.695 246.021 356.99 245.503 357.188 244.82C357.385 244.138 357.484 243.312 357.484 242.344C357.484 241.375 357.383 240.547 357.18 239.859C356.977 239.172 356.682 238.648 356.297 238.289C355.911 237.93 355.448 237.75 354.906 237.75C354.365 237.75 353.901 237.93 353.516 238.289C353.13 238.648 352.833 239.172 352.625 239.859C352.417 240.547 352.312 241.375 352.312 242.344C352.312 243.312 352.417 244.138 352.625 244.82C352.833 245.503 353.128 246.021 353.508 246.375C353.893 246.729 354.359 246.906 354.906 246.906ZM364.438 248.156C363.604 248.156 362.893 247.93 362.305 247.477C361.716 247.023 361.266 246.362 360.953 245.492C360.641 244.622 360.484 243.573 360.484 242.344C360.484 241.13 360.641 240.089 360.953 239.219C361.266 238.344 361.716 237.677 362.305 237.219C362.898 236.76 363.609 236.531 364.438 236.531C365.26 236.531 365.969 236.76 366.562 237.219C367.156 237.677 367.609 238.344 367.922 239.219C368.234 240.089 368.391 241.13 368.391 242.344C368.391 243.573 368.237 244.622 367.93 245.492C367.622 246.362 367.172 247.023 366.578 247.477C365.984 247.93 365.271 248.156 364.438 248.156ZM364.438 246.906C364.979 246.906 365.445 246.729 365.836 246.375C366.227 246.021 366.521 245.503 366.719 244.82C366.917 244.138 367.016 243.312 367.016 242.344C367.016 241.375 366.914 240.547 366.711 239.859C366.508 239.172 366.214 238.648 365.828 238.289C365.443 237.93 364.979 237.75 364.438 237.75C363.896 237.75 363.432 237.93 363.047 238.289C362.661 238.648 362.365 239.172 362.156 239.859C361.948 240.547 361.844 241.375 361.844 242.344C361.844 243.312 361.948 244.138 362.156 244.82C362.365 245.503 362.659 246.021 363.039 246.375C363.424 246.729 363.891 246.906 364.438 246.906ZM379.016 245.453H377.781V242.359H379.016V245.453ZM385.234 245.938H384V235.391H385.234V245.938ZM385.578 248.969H375.703V247.938H385.578V248.969ZM376.938 248.234H375.703V244.906H376.938V248.234ZM373.703 241.828C375.562 241.818 377.208 241.789 378.641 241.742C380.073 241.69 381.443 241.583 382.75 241.422L382.828 242.312C381.479 242.526 380.065 242.667 378.586 242.734C377.107 242.802 375.536 242.833 373.875 242.828L373.703 241.828ZM384.328 244.5H381.125V243.609H384.328V244.5ZM378.266 235.953C378.938 235.953 379.534 236.052 380.055 236.25C380.581 236.448 380.987 236.732 381.273 237.102C381.56 237.471 381.703 237.896 381.703 238.375C381.703 238.865 381.56 239.289 381.273 239.648C380.987 240.008 380.583 240.286 380.062 240.484C379.542 240.682 378.943 240.781 378.266 240.781C377.583 240.781 376.982 240.682 376.461 240.484C375.945 240.286 375.544 240.008 375.258 239.648C374.971 239.289 374.828 238.865 374.828 238.375C374.828 237.896 374.971 237.471 375.258 237.102C375.544 236.732 375.948 236.448 376.469 236.25C376.99 236.052 377.589 235.953 378.266 235.953ZM378.266 236.891C377.818 236.885 377.422 236.945 377.078 237.07C376.734 237.19 376.466 237.365 376.273 237.594C376.086 237.823 375.995 238.083 376 238.375C375.995 238.672 376.086 238.935 376.273 239.164C376.466 239.388 376.734 239.562 377.078 239.688C377.422 239.812 377.818 239.875 378.266 239.875C378.703 239.875 379.094 239.812 379.438 239.688C379.781 239.562 380.049 239.388 380.242 239.164C380.435 238.935 380.531 238.672 380.531 238.375C380.531 238.083 380.435 237.823 380.242 237.594C380.049 237.365 379.781 237.19 379.438 237.07C379.094 236.945 378.703 236.885 378.266 236.891Z" fill="#56555A"/> +<path d="M24 270H399V300H24V270Z" fill="white"/> +<mask id="mask2_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="270" width="375" height="30"> +<path d="M24 270H399V300H24V270Z" fill="white"/> +</mask> +<g mask="url(#mask2_1837_9941)"> +<path d="M24 271H399V269H24V271Z" fill="#F1F0F5"/> +</g> +<path d="M48.7266 283.187H46.0547V282.426H48.7266V283.187ZM49.125 287.184H48.1992V279.543H49.125V287.184ZM49.418 289.727H42.4336V288.953H49.418V289.727ZM43.3594 289.328H42.4336V286.492H43.3594V289.328ZM43.9453 281.687C43.9453 282.309 43.8223 282.896 43.5762 283.451C43.3301 284.002 42.9844 284.486 42.5391 284.904C42.0977 285.318 41.5898 285.633 41.0156 285.848L40.5352 285.098C41.043 284.918 41.498 284.654 41.9004 284.307C42.3027 283.959 42.6172 283.559 42.8437 283.105C43.0703 282.648 43.1836 282.176 43.1836 281.687V280.832H43.9453V281.687ZM44.1094 281.687C44.1094 282.133 44.2187 282.566 44.4375 282.988C44.6562 283.41 44.959 283.785 45.3457 284.113C45.7324 284.441 46.1758 284.691 46.6758 284.863L46.1953 285.602C45.6367 285.398 45.1426 285.1 44.7129 284.705C44.2871 284.311 43.9551 283.854 43.7168 283.334C43.4785 282.814 43.3594 282.266 43.3594 281.687V280.832H44.1094V281.687ZM46.4414 281.148H40.8281V280.387H46.4414V281.148ZM57.1523 284.43H55.1484V283.645H57.1523V284.43ZM53.7539 282.742C53.75 283.437 53.6504 284.117 53.4551 284.781C53.2637 285.445 52.9844 286.043 52.6172 286.574C52.2539 287.102 51.8242 287.516 51.3281 287.816L50.7773 287.113C51.2383 286.848 51.6387 286.482 51.9785 286.018C52.3184 285.553 52.5781 285.035 52.7578 284.465C52.9414 283.895 53.0352 283.32 53.0391 282.742V282.191H53.7539V282.742ZM53.9062 282.742C53.9102 283.305 54.002 283.855 54.1816 284.395C54.3652 284.934 54.6289 285.424 54.9727 285.865C55.3164 286.303 55.7187 286.645 56.1797 286.891L55.6523 287.582C55.1484 287.309 54.7109 286.92 54.3398 286.416C53.9727 285.912 53.6895 285.342 53.4902 284.705C53.2949 284.068 53.1992 283.414 53.2031 282.742V282.191H53.9062V282.742ZM55.8633 282.227H51.0586V281.465H55.8633V282.227ZM53.918 282.039H53.0391V279.918H53.918V282.039ZM59.7656 289.949H58.8867V279.531H59.7656V289.949ZM57.6562 289.41H56.7891V279.789H57.6562V289.41ZM67.6406 281.699C67.6406 282.285 67.5176 282.832 67.2715 283.34C67.0254 283.848 66.6797 284.287 66.2344 284.658C65.7891 285.029 65.2773 285.309 64.6992 285.496L64.2422 284.77C64.7578 284.613 65.2168 284.381 65.6191 284.072C66.0215 283.764 66.334 283.406 66.5566 283C66.7793 282.59 66.8906 282.156 66.8906 281.699V281.254H67.6406V281.699ZM67.793 281.699C67.793 282.121 67.9023 282.521 68.1211 282.9C68.3398 283.279 68.6426 283.615 69.0293 283.908C69.4199 284.197 69.8711 284.418 70.3828 284.57L69.9492 285.297C69.3711 285.117 68.8633 284.85 68.4258 284.494C67.9883 284.139 67.6484 283.723 67.4062 283.246C67.1641 282.766 67.043 282.25 67.043 281.699V281.254H67.793V281.699ZM70.1484 281.512H64.5352V280.773H70.1484V281.512ZM67.8164 281.066H66.8906V279.484H67.8164V281.066ZM72.3867 285.707H71.4727V279.531H72.3867V285.707ZM73.957 282.953H72.1289V282.18H73.957V282.953ZM72.3867 289.809H65.8125V286.187H72.3867V289.809ZM66.7148 289.059H71.4727V286.914H66.7148V289.059ZM82.5586 282.637H79.3477V281.863H82.5586V282.637ZM82.5586 285.93H79.3477V285.168H82.5586V285.93ZM77.4141 280.34C77.918 280.34 78.3672 280.488 78.7617 280.785C79.1602 281.082 79.4687 281.506 79.6875 282.057C79.9062 282.607 80.0156 283.246 80.0156 283.973C80.0156 284.703 79.9062 285.342 79.6875 285.889C79.4687 286.432 79.1602 286.852 78.7617 287.148C78.3672 287.445 77.918 287.594 77.4141 287.594C76.9023 287.594 76.4473 287.445 76.0488 287.148C75.6543 286.852 75.3477 286.432 75.1289 285.889C74.9102 285.342 74.8008 284.703 74.8008 283.973C74.8008 283.246 74.9102 282.607 75.1289 282.057C75.3477 281.506 75.6543 281.082 76.0488 280.785C76.4473 280.488 76.9023 280.34 77.4141 280.34ZM77.4141 281.16C77.0742 281.16 76.7734 281.277 76.5117 281.512C76.2539 281.746 76.0508 282.076 75.9023 282.502C75.7539 282.924 75.6797 283.414 75.6797 283.973C75.6797 284.531 75.7539 285.023 75.9023 285.449C76.0508 285.871 76.2539 286.197 76.5117 286.428C76.7734 286.658 77.0742 286.773 77.4141 286.773C77.75 286.773 78.0508 286.658 78.3164 286.428C78.582 286.197 78.7871 285.869 78.9316 285.443C79.0762 285.018 79.1484 284.527 79.1484 283.973C79.1484 283.418 79.0762 282.928 78.9316 282.502C78.7871 282.076 78.582 281.746 78.3164 281.512C78.0508 281.277 77.75 281.16 77.4141 281.16ZM83.25 289.973H82.3359V279.531H83.25V289.973ZM88.3359 282.73C88.3359 283.437 88.2031 284.141 87.9375 284.84C87.6719 285.535 87.3105 286.158 86.8535 286.709C86.3965 287.26 85.9023 287.672 85.3711 287.945L84.8086 287.219C85.3047 286.977 85.7656 286.613 86.1914 286.129C86.6211 285.645 86.9629 285.102 87.2168 284.5C87.4746 283.898 87.6055 283.309 87.6094 282.73V281.008H88.3359V282.73ZM88.5117 282.73C88.5078 283.277 88.625 283.832 88.8633 284.395C89.1055 284.957 89.4336 285.467 89.8477 285.924C90.2617 286.377 90.7187 286.723 91.2187 286.961L90.6914 287.687C90.1484 287.422 89.6543 287.029 89.209 286.51C88.7676 285.99 88.418 285.4 88.1602 284.74C87.9023 284.076 87.7734 283.406 87.7734 282.73V281.008H88.5117V282.73ZM90.8555 281.371H85.1836V280.609H90.8555V281.371ZM93.0469 289.949H92.1328V279.531H93.0469V289.949ZM94.793 284.535H92.8359V283.75H94.793V284.535Z" fill="#B2B1B6"/> +<path d="M352.809 289.117C352.223 289.117 351.701 289.016 351.244 288.812C350.787 288.609 350.432 288.328 350.178 287.969C349.924 287.609 349.797 287.203 349.797 286.75C349.797 286.391 349.873 286.055 350.025 285.742C350.178 285.43 350.385 285.174 350.646 284.975C350.908 284.771 351.199 284.645 351.52 284.594V284.547C351.242 284.484 350.998 284.361 350.787 284.178C350.58 283.994 350.418 283.77 350.301 283.504C350.184 283.238 350.125 282.953 350.125 282.648C350.125 282.223 350.24 281.84 350.471 281.5C350.701 281.156 351.02 280.887 351.426 280.691C351.836 280.496 352.297 280.398 352.809 280.398C353.316 280.398 353.775 280.496 354.186 280.691C354.596 280.887 354.916 281.156 355.146 281.5C355.381 281.84 355.5 282.223 355.504 282.648C355.5 282.953 355.437 283.238 355.316 283.504C355.199 283.77 355.035 283.994 354.824 284.178C354.613 284.361 354.371 284.484 354.098 284.547V284.594C354.414 284.645 354.703 284.771 354.965 284.975C355.23 285.174 355.439 285.43 355.592 285.742C355.748 286.055 355.828 286.391 355.832 286.75C355.828 287.203 355.697 287.609 355.439 287.969C355.186 288.328 354.828 288.609 354.367 288.812C353.91 289.016 353.391 289.117 352.809 289.117ZM352.809 288.191C353.207 288.191 353.555 288.127 353.852 287.998C354.148 287.869 354.377 287.693 354.537 287.471C354.697 287.248 354.777 286.988 354.777 286.691C354.777 286.383 354.693 286.105 354.525 285.859C354.357 285.609 354.123 285.414 353.822 285.273C353.521 285.133 353.184 285.062 352.809 285.062C352.434 285.062 352.098 285.133 351.801 285.273C351.504 285.414 351.27 285.609 351.098 285.859C350.93 286.105 350.848 286.383 350.852 286.691C350.848 286.988 350.924 287.248 351.08 287.471C351.24 287.693 351.467 287.869 351.76 287.998C352.057 288.127 352.406 288.191 352.809 288.191ZM352.809 284.172C353.129 284.172 353.416 284.109 353.67 283.984C353.924 283.859 354.121 283.689 354.262 283.475C354.402 283.26 354.473 283.012 354.473 282.73C354.473 282.449 354.404 282.201 354.268 281.986C354.131 281.771 353.936 281.605 353.682 281.488C353.428 281.371 353.137 281.312 352.809 281.312C352.477 281.312 352.186 281.371 351.936 281.488C351.689 281.605 351.496 281.771 351.355 281.986C351.215 282.201 351.145 282.449 351.145 282.73C351.145 283.012 351.217 283.26 351.361 283.475C351.506 283.689 351.703 283.859 351.953 283.984C352.203 284.109 352.488 284.172 352.809 284.172ZM364.949 281.992H361.879V281.23H364.949V281.992ZM364.961 284.066H361.879V283.293H364.961V284.066ZM365.512 285.707H364.586V279.531H365.512V285.707ZM362.148 284.957H357.367V280.328H362.148V284.957ZM358.281 284.207H361.246V281.078H358.281V284.207ZM362.055 286.012C362.773 286.012 363.395 286.088 363.918 286.24C364.441 286.393 364.844 286.617 365.125 286.914C365.406 287.211 365.547 287.566 365.547 287.98C365.547 288.391 365.406 288.74 365.125 289.029C364.844 289.322 364.441 289.545 363.918 289.697C363.395 289.85 362.773 289.926 362.055 289.926C361.332 289.926 360.709 289.85 360.186 289.697C359.666 289.545 359.266 289.322 358.984 289.029C358.703 288.74 358.562 288.391 358.562 287.98C358.562 287.566 358.703 287.211 358.984 286.914C359.266 286.617 359.666 286.393 360.186 286.24C360.709 286.088 361.332 286.012 362.055 286.012ZM362.055 286.727C361.523 286.73 361.064 286.783 360.678 286.885C360.291 286.982 359.994 287.125 359.787 287.312C359.58 287.5 359.477 287.723 359.477 287.98C359.477 288.23 359.58 288.447 359.787 288.631C359.994 288.814 360.291 288.955 360.678 289.053C361.064 289.15 361.523 289.199 362.055 289.199C362.582 289.199 363.039 289.15 363.426 289.053C363.816 288.955 364.115 288.814 364.322 288.631C364.529 288.447 364.633 288.23 364.633 287.98C364.633 287.723 364.529 287.5 364.322 287.312C364.115 287.125 363.818 286.982 363.432 286.885C363.045 286.783 362.586 286.73 362.055 286.727Z" fill="#B2B1B6"/> +<mask id="mask3_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="375" y="279" width="8" height="12"> +<path d="M383 283C383 280.791 381.209 279 379 279C376.791 279 375 280.791 375 283V287C375 289.209 376.791 291 379 291C381.209 291 383 289.209 383 287V283Z" fill="white"/> +</mask> +<g mask="url(#mask3_1837_9941)"> +<path d="M377 281L381 285L377 289" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +</g> +<path d="M390 316H40C35.5817 316 32 319.582 32 324V348C32 352.418 35.5817 356 40 356H390C394.418 356 398 352.418 398 348V324C398 319.582 394.418 316 390 316Z" fill="white"/> +<path d="M52.4062 339.633H50.4219V329.234H52.4062V339.633ZM50.7031 334.977H47.875V333.352H50.7031V334.977ZM48.0078 330.273C48.0026 331.539 47.7422 332.693 47.2266 333.734C46.7109 334.771 45.9609 335.669 44.9766 336.43C43.9922 337.185 42.8073 337.779 41.4219 338.211L40.6016 336.617C41.6953 336.273 42.638 335.831 43.4297 335.289C44.2266 334.742 44.8333 334.12 45.25 333.422C45.6719 332.724 45.8854 331.974 45.8906 331.172V330.273H48.0078ZM47.1641 331.906H41.3437V330.273H47.1641V331.906ZM52.7734 343.195H43.0234V341.586H52.7734V343.195ZM45.0469 342.508H43.0234V338.57H45.0469V342.508ZM59.0547 331.258C59.0547 332.227 58.9089 333.125 58.6172 333.953C58.3307 334.781 57.8932 335.503 57.3047 336.117C56.7161 336.727 55.987 337.18 55.1172 337.477L54.0469 335.914C54.8073 335.654 55.4401 335.286 55.9453 334.812C56.4505 334.333 56.8229 333.792 57.0625 333.187C57.3021 332.583 57.4245 331.94 57.4297 331.258V329.969H59.0547V331.258ZM59.4297 331.453C59.4297 332.052 59.5469 332.617 59.7812 333.148C60.0208 333.68 60.3828 334.154 60.8672 334.57C61.3568 334.982 61.9635 335.302 62.6875 335.531L61.625 337.078C60.7917 336.802 60.0911 336.388 59.5234 335.836C58.9557 335.279 58.5286 334.628 58.2422 333.883C57.9557 333.138 57.8151 332.328 57.8203 331.453V329.969H59.4297V331.453ZM65.5312 337.648H63.5391V329.203H65.5312V337.648ZM67.4531 334.203H64.9687V332.539H67.4531V334.203ZM60.8672 337.937C61.8464 337.937 62.6953 338.047 63.4141 338.266C64.138 338.479 64.6927 338.794 65.0781 339.211C65.4687 339.622 65.6641 340.112 65.6641 340.68C65.6641 341.258 65.4687 341.753 65.0781 342.164C64.6927 342.576 64.138 342.891 63.4141 343.109C62.6953 343.328 61.8464 343.437 60.8672 343.437C59.8724 343.437 59.0078 343.328 58.2734 343.109C57.5443 342.891 56.9818 342.576 56.5859 342.164C56.1901 341.753 55.9922 341.258 55.9922 340.68C55.9922 340.112 56.1901 339.622 56.5859 339.211C56.9818 338.794 57.5443 338.479 58.2734 338.266C59.0078 338.047 59.8724 337.937 60.8672 337.937ZM60.8672 339.5C60.2474 339.495 59.724 339.539 59.2969 339.633C58.8698 339.721 58.5443 339.854 58.3203 340.031C58.1016 340.208 57.9948 340.424 58 340.68C57.9948 340.945 58.1016 341.167 58.3203 341.344C58.5391 341.521 58.8594 341.654 59.2812 341.742C59.7083 341.831 60.237 341.875 60.8672 341.875C61.487 341.875 62.0078 341.831 62.4297 341.742C62.8516 341.654 63.1693 341.521 63.3828 341.344C63.5964 341.167 63.7031 340.945 63.7031 340.68C63.7031 340.424 63.5937 340.208 63.375 340.031C63.1615 339.849 62.8437 339.714 62.4219 339.625C62 339.536 61.4818 339.495 60.8672 339.5ZM69.7266 345.297H68.0703L68.8437 340.852H71.0781L69.7266 345.297ZM82.9297 331.227C82.9297 332.07 82.7031 332.841 82.25 333.539C81.8021 334.232 81.1484 334.815 80.2891 335.289C79.4297 335.758 78.4115 336.073 77.2344 336.234L76.4922 334.68C77.487 334.56 78.3385 334.323 79.0469 333.969C79.7604 333.609 80.2969 333.193 80.6562 332.719C81.0156 332.24 81.1953 331.742 81.1953 331.227V330.797H82.9297V331.227ZM83.5 331.227C83.5 331.742 83.6771 332.24 84.0312 332.719C84.3906 333.193 84.9245 333.609 85.6328 333.969C86.3464 334.323 87.2083 334.56 88.2187 334.68L87.5 336.234C86.3125 336.073 85.2865 335.758 84.4219 335.289C83.5573 334.815 82.8984 334.232 82.4453 333.539C81.9922 332.841 81.7656 332.07 81.7656 331.227V330.797H83.5V331.227ZM83.2969 343.445H81.3203V338.203H83.2969V343.445ZM88.8359 338.656H75.8672V337.07H88.8359V338.656ZM87.6641 331.523H77.0312V329.969H87.6641V331.523ZM101.062 340.32H99.0547V329.203H101.062V340.32ZM102.883 335.531H100.352V333.891H102.883V335.531ZM101.547 343.195H91.5234V341.586H101.547V343.195ZM93.5391 342.062H91.5234V339.586H93.5391V342.062ZM94.9687 338.125H92.9844V336.039H94.9687V338.125ZM89.5391 337.391C91.1849 337.391 92.7474 337.359 94.2266 337.297C95.7057 337.229 97.0964 337.102 98.3984 336.914L98.5469 338.281C97.2969 338.521 96.0078 338.682 94.6797 338.766C93.3516 338.849 91.8385 338.904 90.1406 338.93C90.0625 338.93 89.9948 338.93 89.9375 338.93C89.8802 338.93 89.8125 338.93 89.7344 338.93L89.5391 337.391ZM98.0391 331.805H89.8984V330.367H98.0391V331.805ZM93.9687 332.195C94.6615 332.195 95.2708 332.284 95.7969 332.461C96.3229 332.633 96.7292 332.888 97.0156 333.227C97.3021 333.56 97.4479 333.958 97.4531 334.422C97.4479 334.859 97.3021 335.242 97.0156 335.57C96.7292 335.893 96.3229 336.146 95.7969 336.328C95.2708 336.505 94.6615 336.594 93.9687 336.594C93.2708 336.594 92.6589 336.505 92.1328 336.328C91.6068 336.151 91.1979 335.901 90.9062 335.578C90.6198 335.25 90.4766 334.865 90.4766 334.422C90.4766 333.958 90.6198 333.56 90.9062 333.227C91.1979 332.888 91.6042 332.633 92.125 332.461C92.651 332.284 93.2656 332.195 93.9687 332.195ZM93.9687 333.531C93.625 333.531 93.3359 333.562 93.1016 333.625C92.8672 333.687 92.6875 333.786 92.5625 333.922C92.4427 334.057 92.3828 334.224 92.3828 334.422C92.3828 334.594 92.4427 334.745 92.5625 334.875C92.6875 335 92.8672 335.096 93.1016 335.164C93.3411 335.227 93.6302 335.258 93.9687 335.258C94.2969 335.258 94.5781 335.227 94.8125 335.164C95.0521 335.096 95.2318 335 95.3516 334.875C95.4766 334.745 95.5391 334.594 95.5391 334.422C95.5391 334.224 95.4792 334.057 95.3594 333.922C95.2396 333.786 95.0599 333.687 94.8203 333.625C94.5859 333.562 94.3021 333.531 93.9687 333.531ZM94.9687 331.008H92.9844V329.164H94.9687V331.008ZM105.164 345.297H103.508L104.281 340.852H106.516L105.164 345.297ZM123.687 332.609H111.852V331.016H123.687V332.609ZM124.305 341.992H111.305V340.383H124.305V341.992ZM118.75 341.008H116.773V338.469H118.75V341.008ZM117.766 333.227C118.745 333.227 119.599 333.336 120.328 333.555C121.062 333.773 121.625 334.094 122.016 334.516C122.411 334.932 122.609 335.424 122.609 335.992C122.609 336.57 122.411 337.07 122.016 337.492C121.625 337.909 121.065 338.232 120.336 338.461C119.607 338.685 118.75 338.799 117.766 338.805C116.766 338.799 115.901 338.685 115.172 338.461C114.443 338.232 113.88 337.909 113.484 337.492C113.094 337.07 112.901 336.57 112.906 335.992C112.901 335.419 113.094 334.924 113.484 334.508C113.88 334.091 114.443 333.773 115.172 333.555C115.906 333.336 116.771 333.227 117.766 333.227ZM117.766 334.781C117.141 334.786 116.62 334.833 116.203 334.922C115.792 335.005 115.479 335.138 115.266 335.32C115.052 335.497 114.948 335.721 114.953 335.992C114.948 336.263 115.052 336.49 115.266 336.672C115.479 336.849 115.792 336.984 116.203 337.078C116.62 337.167 117.141 337.211 117.766 337.211C118.375 337.211 118.885 337.167 119.297 337.078C119.713 336.984 120.029 336.849 120.242 336.672C120.456 336.49 120.562 336.263 120.562 335.992C120.562 335.721 120.456 335.497 120.242 335.32C120.029 335.138 119.713 335.005 119.297 334.922C118.885 334.833 118.375 334.786 117.766 334.781ZM118.75 332.008H116.773V329.359H118.75V332.008ZM137.109 339.633H135.125V329.234H137.109V339.633ZM135.406 334.977H132.578V333.352H135.406V334.977ZM132.711 330.273C132.706 331.539 132.445 332.693 131.93 333.734C131.414 334.771 130.664 335.669 129.68 336.43C128.695 337.185 127.51 337.779 126.125 338.211L125.305 336.617C126.398 336.273 127.341 335.831 128.133 335.289C128.93 334.742 129.536 334.12 129.953 333.422C130.375 332.724 130.589 331.974 130.594 331.172V330.273H132.711ZM131.867 331.906H126.047V330.273H131.867V331.906ZM137.477 343.195H127.727V341.586H137.477V343.195ZM129.75 342.508H127.727V338.57H129.75V342.508ZM140.602 345.297H138.945L139.719 340.852H141.953L140.602 345.297ZM153.805 331.227C153.805 332.07 153.578 332.841 153.125 333.539C152.677 334.232 152.023 334.815 151.164 335.289C150.305 335.758 149.286 336.073 148.109 336.234L147.367 334.68C148.362 334.56 149.214 334.323 149.922 333.969C150.635 333.609 151.172 333.193 151.531 332.719C151.891 332.24 152.07 331.742 152.07 331.227V330.797H153.805V331.227ZM154.375 331.227C154.375 331.742 154.552 332.24 154.906 332.719C155.266 333.193 155.799 333.609 156.508 333.969C157.221 334.323 158.083 334.56 159.094 334.68L158.375 336.234C157.187 336.073 156.161 335.758 155.297 335.289C154.432 334.815 153.773 334.232 153.32 333.539C152.867 332.841 152.641 332.07 152.641 331.227V330.797H154.375V331.227ZM154.172 343.445H152.195V338.203H154.172V343.445ZM159.711 338.656H146.742V337.07H159.711V338.656ZM158.539 331.523H147.906V329.969H158.539V331.523ZM171.781 343.437H169.812V329.203H171.781V343.437ZM173.891 336.422H171.344V334.789H173.891V336.422ZM168.844 332.937H160.492V331.336H168.844V332.937ZM164.703 333.727C165.385 333.727 166.003 333.872 166.555 334.164C167.112 334.451 167.547 334.852 167.859 335.367C168.177 335.883 168.339 336.466 168.344 337.117C168.339 337.773 168.177 338.359 167.859 338.875C167.547 339.385 167.112 339.786 166.555 340.078C166.003 340.365 165.385 340.508 164.703 340.508C164.01 340.508 163.388 340.365 162.836 340.078C162.284 339.786 161.852 339.385 161.539 338.875C161.227 338.359 161.07 337.773 161.07 337.117C161.07 336.466 161.227 335.883 161.539 335.367C161.852 334.852 162.284 334.451 162.836 334.164C163.388 333.872 164.01 333.727 164.703 333.727ZM164.703 335.352C164.37 335.357 164.073 335.43 163.812 335.57C163.552 335.711 163.346 335.917 163.195 336.187C163.049 336.453 162.977 336.763 162.977 337.117C162.977 337.482 163.049 337.797 163.195 338.062C163.346 338.323 163.552 338.523 163.812 338.664C164.073 338.805 164.37 338.878 164.703 338.883C165.036 338.878 165.333 338.805 165.594 338.664C165.859 338.523 166.062 338.323 166.203 338.062C166.349 337.797 166.422 337.482 166.422 337.117C166.422 336.763 166.349 336.453 166.203 336.187C166.062 335.917 165.859 335.711 165.594 335.57C165.333 335.43 165.036 335.357 164.703 335.352ZM165.695 331.945H163.711V329.43H165.695V331.945ZM191.094 336.336H178.102V334.773H191.094V336.336ZM189.539 333.984H179.711V332.414H189.539V333.984ZM189.437 331.086H181.703V333.75H179.711V329.508H189.437V331.086ZM189.484 340.883H181.562V342.164H179.602V339.469H187.516V338.672H179.594V337.172H189.484V340.883ZM189.859 343.32H179.602V341.773H189.859V343.32ZM195.844 330.211C196.552 330.211 197.185 330.419 197.742 330.836C198.305 331.247 198.742 331.839 199.055 332.609C199.367 333.375 199.523 334.266 199.523 335.281C199.523 336.302 199.367 337.198 199.055 337.969C198.742 338.734 198.305 339.323 197.742 339.734C197.185 340.146 196.552 340.352 195.844 340.352C195.125 340.352 194.487 340.146 193.93 339.734C193.372 339.323 192.935 338.734 192.617 337.969C192.299 337.198 192.141 336.302 192.141 335.281C192.141 334.266 192.299 333.375 192.617 332.609C192.935 331.839 193.372 331.247 193.93 330.836C194.487 330.419 195.125 330.211 195.844 330.211ZM195.844 332.016C195.484 332.01 195.172 332.135 194.906 332.391C194.641 332.646 194.432 333.018 194.281 333.508C194.13 333.997 194.057 334.589 194.062 335.281C194.057 335.974 194.13 336.565 194.281 337.055C194.432 337.544 194.641 337.917 194.906 338.172C195.172 338.422 195.484 338.547 195.844 338.547C196.203 338.547 196.518 338.422 196.789 338.172C197.06 337.917 197.268 337.544 197.414 337.055C197.56 336.565 197.633 335.974 197.633 335.281C197.633 334.589 197.56 333.997 197.414 333.508C197.268 333.013 197.06 332.641 196.789 332.391C196.518 332.135 196.203 332.01 195.844 332.016ZM203.922 343.477H201.945V329.203H203.922V343.477ZM202.797 335.953H198.93V334.352H202.797V335.953ZM213.187 336.516H211.227V334.398H213.187V336.516ZM212.234 329.422C213.281 329.422 214.193 329.534 214.969 329.758C215.75 329.977 216.349 330.294 216.766 330.711C217.187 331.128 217.398 331.617 217.398 332.18C217.398 332.742 217.187 333.232 216.766 333.648C216.349 334.065 215.753 334.385 214.977 334.609C214.201 334.828 213.286 334.935 212.234 334.93C211.187 334.935 210.273 334.828 209.492 334.609C208.711 334.385 208.107 334.065 207.68 333.648C207.258 333.232 207.047 332.742 207.047 332.18C207.047 331.617 207.26 331.128 207.687 330.711C208.115 330.294 208.716 329.977 209.492 329.758C210.273 329.534 211.187 329.422 212.234 329.422ZM212.234 330.953C211.573 330.953 211.008 331 210.539 331.094C210.076 331.182 209.721 331.32 209.477 331.508C209.237 331.69 209.117 331.914 209.117 332.18C209.117 332.456 209.237 332.687 209.477 332.875C209.721 333.057 210.073 333.195 210.531 333.289C210.995 333.378 211.562 333.422 212.234 333.422C212.896 333.422 213.458 333.378 213.922 333.289C214.391 333.195 214.745 333.057 214.984 332.875C215.224 332.687 215.344 332.456 215.344 332.18C215.344 331.914 215.221 331.69 214.977 331.508C214.732 331.32 214.378 331.182 213.914 331.094C213.451 331 212.891 330.953 212.234 330.953ZM217.172 343.281H207.258V338.43H217.172V343.281ZM209.219 341.68H215.219V340.008H209.219V341.68ZM218.727 337.492H205.758V335.914H218.727V337.492Z" fill="#56555A"/> +<path d="M386 364H44C37.3726 364 32 369.373 32 376V508C32 514.627 37.3726 520 44 520H386C392.627 520 398 514.627 398 508V376C398 369.373 392.627 364 386 364Z" fill="white"/> +<path d="M52.3184 385H50.5488V378.191H50.502L48.5625 379.422V377.852L50.6602 376.516H52.3184V385ZM57.4922 378.76C57.4883 379.525 57.375 380.262 57.1523 380.969C56.9297 381.676 56.5977 382.307 56.1562 382.861C55.7187 383.412 55.1875 383.824 54.5625 384.098L53.7422 382.937C54.2969 382.695 54.7676 382.35 55.1543 381.9C55.5449 381.447 55.8359 380.949 56.0273 380.406C56.2187 379.863 56.3145 379.314 56.3145 378.76V378.15H57.4922V378.76ZM57.7969 378.76C57.793 379.283 57.8828 379.803 58.0664 380.318C58.2539 380.83 58.5332 381.305 58.9043 381.742C59.2754 382.176 59.7324 382.521 60.2754 382.779L59.4492 383.916C58.8437 383.643 58.3301 383.238 57.9082 382.703C57.4863 382.164 57.168 381.555 56.9531 380.875C56.7383 380.191 56.6328 379.486 56.6367 378.76V378.15H57.7969V378.76ZM59.9766 378.344H54.1055V377.154H59.9766V378.344ZM57.8086 377.775H56.3086V375.648H57.8086V377.775ZM62.3555 386.078H60.8555V375.402H62.3555V386.078ZM63.9375 380.805H62.0273V379.551H63.9375V380.805Z" fill="#56555A"/> +<path d="M364.586 382.398L368.406 376.516H369.039V377.852H368.594L365.723 382.27V382.34H370.891V383.266H364.586V382.398ZM368.699 383.008V382.598V376.516H369.707V385H368.699V383.008ZM379.984 377.992H376.914V377.23H379.984V377.992ZM379.996 380.066H376.914V379.293H379.996V380.066ZM380.547 381.707H379.621V375.531H380.547V381.707ZM377.184 380.957H372.402V376.328H377.184V380.957ZM373.316 380.207H376.281V377.078H373.316V380.207ZM377.09 382.012C377.809 382.012 378.43 382.088 378.953 382.24C379.477 382.393 379.879 382.617 380.16 382.914C380.441 383.211 380.582 383.566 380.582 383.98C380.582 384.391 380.441 384.74 380.16 385.029C379.879 385.322 379.477 385.545 378.953 385.697C378.43 385.85 377.809 385.926 377.09 385.926C376.367 385.926 375.744 385.85 375.221 385.697C374.701 385.545 374.301 385.322 374.02 385.029C373.738 384.74 373.598 384.391 373.598 383.98C373.598 383.566 373.738 383.211 374.02 382.914C374.301 382.617 374.701 382.393 375.221 382.24C375.744 382.088 376.367 382.012 377.09 382.012ZM377.09 382.727C376.559 382.73 376.1 382.783 375.713 382.885C375.326 382.982 375.029 383.125 374.822 383.312C374.615 383.5 374.512 383.723 374.512 383.98C374.512 384.23 374.615 384.447 374.822 384.631C375.029 384.814 375.326 384.955 375.713 385.053C376.1 385.15 376.559 385.199 377.09 385.199C377.617 385.199 378.074 385.15 378.461 385.053C378.852 384.955 379.15 384.814 379.357 384.631C379.564 384.447 379.668 384.23 379.668 383.98C379.668 383.723 379.564 383.5 379.357 383.312C379.15 383.125 378.854 382.982 378.467 382.885C378.08 382.783 377.621 382.73 377.09 382.727Z" fill="#B2B1B6"/> +<path d="M364 386.916H381.859V387.73H364V386.916Z" fill="#B2B1B6"/> +<path d="M382 398H48C43.5817 398 40 401.582 40 406V430C40 434.418 43.5817 438 48 438H382C386.418 438 390 434.418 390 430V406C390 401.582 386.418 398 382 398Z" fill="#F9F8FD"/> +<path d="M51.3203 412.82H52.6406V411.625H54.4844V417.078H49.4375V411.625H51.3203V412.82ZM52.6406 415.477V414.328H51.3203V415.477H52.6406ZM57.2109 412.82H58.4766V411.625H60.375V417.078H55.3125V411.625H57.2109V412.82ZM58.4766 415.477V414.328H57.2109V415.477H58.4766ZM61.3984 419.719H48.4297V418.125H61.3984V419.719ZM55.8906 418.703H53.8828V416.641H55.8906V418.703ZM54.8906 420.414C55.9167 420.414 56.7995 420.513 57.5391 420.711C58.2839 420.909 58.8542 421.195 59.25 421.57C59.6458 421.945 59.8464 422.396 59.8516 422.922C59.8464 423.458 59.6458 423.914 59.25 424.289C58.8594 424.669 58.2917 424.956 57.5469 425.148C56.8021 425.346 55.9167 425.443 54.8906 425.437C53.849 425.437 52.9557 425.341 52.2109 425.148C51.4714 424.956 50.9036 424.672 50.5078 424.297C50.1172 423.922 49.9219 423.464 49.9219 422.922C49.9219 422.396 50.1172 421.945 50.5078 421.57C50.9036 421.195 51.4714 420.909 52.2109 420.711C52.9557 420.513 53.849 420.414 54.8906 420.414ZM54.8906 421.898C54.2187 421.898 53.6615 421.937 53.2187 422.016C52.7812 422.089 52.4531 422.203 52.2344 422.359C52.0208 422.51 51.9167 422.698 51.9219 422.922C51.9167 423.151 52.0234 423.341 52.2422 423.492C52.4661 423.643 52.7943 423.758 53.2266 423.836C53.6641 423.914 54.2187 423.953 54.8906 423.953C55.5417 423.953 56.0833 423.914 56.5156 423.836C56.9531 423.758 57.2812 423.643 57.5 423.492C57.7187 423.341 57.8281 423.151 57.8281 422.922C57.8281 422.698 57.7187 422.51 57.5 422.359C57.2812 422.203 56.9557 422.089 56.5234 422.016C56.0911 421.937 55.5469 421.898 54.8906 421.898ZM66.3594 413.992C66.3542 414.831 66.237 415.615 66.0078 416.344C65.7839 417.073 65.4297 417.719 64.9453 418.281C64.4661 418.844 63.8594 419.271 63.125 419.562L62.0547 418.039C62.6797 417.784 63.1979 417.445 63.6094 417.023C64.0208 416.602 64.3203 416.135 64.5078 415.625C64.7005 415.109 64.7969 414.565 64.7969 413.992V413.07H66.3594V413.992ZM66.7031 413.992C66.7031 414.539 66.7917 415.049 66.9687 415.523C67.1458 415.992 67.4219 416.414 67.7969 416.789C68.1771 417.159 68.6615 417.458 69.25 417.687L68.2109 419.211C67.513 418.935 66.9401 418.542 66.4922 418.031C66.0495 417.516 65.7214 416.917 65.5078 416.234C65.2995 415.552 65.1979 414.805 65.2031 413.992V413.07H66.7031V413.992ZM68.8828 413.859H62.5234V412.273H68.8828V413.859ZM74.4687 419.844H72.5703V411.234H74.4687V419.844ZM73.0937 416.289H70.8125V414.68H73.0937V416.289ZM71.4453 419.406H69.5547V411.477H71.4453V419.406ZM69.6094 420.055C70.6094 420.055 71.4792 420.164 72.2187 420.383C72.9635 420.596 73.5365 420.906 73.9375 421.312C74.3385 421.714 74.5391 422.19 74.5391 422.742C74.5391 423.294 74.3385 423.773 73.9375 424.18C73.5365 424.586 72.9635 424.896 72.2187 425.109C71.474 425.328 70.6042 425.437 69.6094 425.437C68.6094 425.437 67.7396 425.328 67 425.109C66.2604 424.896 65.6901 424.586 65.2891 424.18C64.888 423.773 64.6875 423.294 64.6875 422.742C64.6875 422.19 64.888 421.714 65.2891 421.312C65.6901 420.906 66.2604 420.596 67 420.383C67.7396 420.164 68.6094 420.055 69.6094 420.055ZM69.6094 421.57C68.9896 421.57 68.4609 421.615 68.0234 421.703C67.5911 421.786 67.2578 421.919 67.0234 422.102C66.7943 422.279 66.6823 422.492 66.6875 422.742C66.6823 423.003 66.7943 423.221 67.0234 423.398C67.2526 423.57 67.5833 423.701 68.0156 423.789C68.4479 423.872 68.9792 423.917 69.6094 423.922C70.2396 423.917 70.7708 423.872 71.2031 423.789C71.6354 423.701 71.9635 423.57 72.1875 423.398C72.4167 423.221 72.5339 423.003 72.5391 422.742C72.5339 422.492 72.4167 422.279 72.1875 422.102C71.9635 421.919 71.6302 421.786 71.1875 421.703C70.75 421.615 70.224 421.57 69.6094 421.57ZM87.9844 425.477H85.9609V411.203H87.9844V425.477ZM80.2578 412.211C80.9714 412.211 81.612 412.419 82.1797 412.836C82.7526 413.247 83.1979 413.839 83.5156 414.609C83.8385 415.375 84 416.266 84 417.281C84 418.302 83.8385 419.198 83.5156 419.969C83.1979 420.734 82.7526 421.323 82.1797 421.734C81.612 422.146 80.9714 422.352 80.2578 422.352C79.5339 422.357 78.8854 422.154 78.3125 421.742C77.7448 421.326 77.2995 420.734 76.9766 419.969C76.6536 419.198 76.4922 418.302 76.4922 417.281C76.4922 416.266 76.6536 415.375 76.9766 414.609C77.2995 413.839 77.7448 413.247 78.3125 412.836C78.8854 412.419 79.5339 412.211 80.2578 412.211ZM80.2578 414.016C79.888 414.01 79.5625 414.135 79.2812 414.391C79.0052 414.641 78.7917 415.013 78.6406 415.508C78.4948 415.997 78.4245 416.589 78.4297 417.281C78.4245 417.974 78.4948 418.565 78.6406 419.055C78.7917 419.544 79.0052 419.917 79.2812 420.172C79.5625 420.422 79.888 420.547 80.2578 420.547C80.6172 420.547 80.9349 420.422 81.2109 420.172C81.487 419.917 81.7005 419.544 81.8516 419.055C82.0026 418.565 82.0781 417.974 82.0781 417.281C82.0781 416.589 82.0026 415.997 81.8516 415.508C81.7005 415.018 81.487 414.646 81.2109 414.391C80.9349 414.135 80.6172 414.01 80.2578 414.016ZM100.484 412.898C100.479 413.628 100.26 414.292 99.8281 414.891C99.401 415.49 98.7656 415.99 97.9219 416.391C97.0781 416.792 96.0651 417.052 94.8828 417.172L94.1875 415.609C95.1667 415.516 95.9974 415.328 96.6797 415.047C97.3672 414.766 97.8776 414.437 98.2109 414.062C98.5495 413.687 98.7214 413.299 98.7266 412.898V412.492H100.484V412.898ZM101.453 412.898C101.453 413.305 101.622 413.695 101.961 414.07C102.305 414.445 102.82 414.773 103.508 415.055C104.195 415.331 105.036 415.516 106.031 415.609L105.312 417.172C104.13 417.052 103.115 416.794 102.266 416.398C101.422 415.997 100.779 415.497 100.336 414.898C99.8932 414.294 99.6693 413.628 99.6641 412.898V412.492H101.453V412.898ZM105.414 413.312H94.7891V411.734H105.414V413.312ZM106.586 419.734H93.6172V418.148H106.586V419.734ZM101.062 418.852H99.0859V416.273H101.062V418.852ZM105 425.437H103.016V422.344H95.0469V420.758H105V425.437ZM109.836 413.547H112.75V411.852H114.75V418.062H107.859V411.852H109.836V413.547ZM112.75 416.492V415.039H109.836V416.492H112.75ZM118.719 418.453H116.727V411.203H118.719V418.453ZM120.641 415.602H117.891V413.984H120.641V415.602ZM118.719 422.852H111.273V424.555H109.312V421.422H116.734V420.531H109.289V418.992H118.719V422.852ZM119.133 425.336H109.312V423.773H119.133V425.336Z" fill="#56555A"/> +<path d="M314.078 424H312.656V414.156H312.594L309.844 415.984V414.562L312.656 412.687H314.078V424ZM320.797 424.156C319.964 424.156 319.253 423.93 318.664 423.477C318.076 423.023 317.625 422.362 317.312 421.492C317 420.622 316.844 419.573 316.844 418.344C316.844 417.13 317 416.089 317.312 415.219C317.625 414.344 318.076 413.677 318.664 413.219C319.258 412.76 319.969 412.531 320.797 412.531C321.62 412.531 322.328 412.76 322.922 413.219C323.516 413.677 323.969 414.344 324.281 415.219C324.594 416.089 324.75 417.13 324.75 418.344C324.75 419.573 324.596 420.622 324.289 421.492C323.982 422.362 323.531 423.023 322.937 423.477C322.344 423.93 321.63 424.156 320.797 424.156ZM320.797 422.906C321.339 422.906 321.805 422.729 322.195 422.375C322.586 422.021 322.88 421.503 323.078 420.82C323.276 420.138 323.375 419.312 323.375 418.344C323.375 417.375 323.273 416.547 323.07 415.859C322.867 415.172 322.573 414.648 322.187 414.289C321.802 413.93 321.339 413.75 320.797 413.75C320.255 413.75 319.792 413.93 319.406 414.289C319.021 414.648 318.724 415.172 318.516 415.859C318.307 416.547 318.203 417.375 318.203 418.344C318.203 419.312 318.307 420.138 318.516 420.82C318.724 421.503 319.018 422.021 319.398 422.375C319.784 422.729 320.25 422.906 320.797 422.906ZM330.328 424.156C329.495 424.156 328.784 423.93 328.195 423.477C327.607 423.023 327.156 422.362 326.844 421.492C326.531 420.622 326.375 419.573 326.375 418.344C326.375 417.13 326.531 416.089 326.844 415.219C327.156 414.344 327.607 413.677 328.195 413.219C328.789 412.76 329.5 412.531 330.328 412.531C331.151 412.531 331.859 412.76 332.453 413.219C333.047 413.677 333.5 414.344 333.812 415.219C334.125 416.089 334.281 417.13 334.281 418.344C334.281 419.573 334.128 420.622 333.82 421.492C333.513 422.362 333.062 423.023 332.469 423.477C331.875 423.93 331.161 424.156 330.328 424.156ZM330.328 422.906C330.87 422.906 331.336 422.729 331.727 422.375C332.117 422.021 332.411 421.503 332.609 420.82C332.807 420.138 332.906 419.312 332.906 418.344C332.906 417.375 332.805 416.547 332.602 415.859C332.398 415.172 332.104 414.648 331.719 414.289C331.333 413.93 330.87 413.75 330.328 413.75C329.786 413.75 329.323 413.93 328.937 414.289C328.552 414.648 328.255 415.172 328.047 415.859C327.839 416.547 327.734 417.375 327.734 418.344C327.734 419.312 327.839 420.138 328.047 420.82C328.255 421.503 328.549 422.021 328.93 422.375C329.315 422.729 329.781 422.906 330.328 422.906ZM336.312 427.203H335.156L336.016 422.953H337.531L336.312 427.203ZM343.172 424.156C342.339 424.156 341.628 423.93 341.039 423.477C340.451 423.023 340 422.362 339.687 421.492C339.375 420.622 339.219 419.573 339.219 418.344C339.219 417.13 339.375 416.089 339.687 415.219C340 414.344 340.451 413.677 341.039 413.219C341.633 412.76 342.344 412.531 343.172 412.531C343.995 412.531 344.703 412.76 345.297 413.219C345.891 413.677 346.344 414.344 346.656 415.219C346.969 416.089 347.125 417.13 347.125 418.344C347.125 419.573 346.971 420.622 346.664 421.492C346.357 422.362 345.906 423.023 345.312 423.477C344.719 423.93 344.005 424.156 343.172 424.156ZM343.172 422.906C343.714 422.906 344.18 422.729 344.57 422.375C344.961 422.021 345.255 421.503 345.453 420.82C345.651 420.138 345.75 419.312 345.75 418.344C345.75 417.375 345.648 416.547 345.445 415.859C345.242 415.172 344.948 414.648 344.562 414.289C344.177 413.93 343.714 413.75 343.172 413.75C342.63 413.75 342.167 413.93 341.781 414.289C341.396 414.648 341.099 415.172 340.891 415.859C340.682 416.547 340.578 417.375 340.578 418.344C340.578 419.312 340.682 420.138 340.891 420.82C341.099 421.503 341.393 422.021 341.773 422.375C342.159 422.729 342.625 422.906 343.172 422.906ZM352.703 424.156C351.87 424.156 351.159 423.93 350.57 423.477C349.982 423.023 349.531 422.362 349.219 421.492C348.906 420.622 348.75 419.573 348.75 418.344C348.75 417.13 348.906 416.089 349.219 415.219C349.531 414.344 349.982 413.677 350.57 413.219C351.164 412.76 351.875 412.531 352.703 412.531C353.526 412.531 354.234 412.76 354.828 413.219C355.422 413.677 355.875 414.344 356.187 415.219C356.5 416.089 356.656 417.13 356.656 418.344C356.656 419.573 356.503 420.622 356.195 421.492C355.888 422.362 355.437 423.023 354.844 423.477C354.25 423.93 353.536 424.156 352.703 424.156ZM352.703 422.906C353.245 422.906 353.711 422.729 354.102 422.375C354.492 422.021 354.786 421.503 354.984 420.82C355.182 420.138 355.281 419.312 355.281 418.344C355.281 417.375 355.18 416.547 354.977 415.859C354.773 415.172 354.479 414.648 354.094 414.289C353.708 413.93 353.245 413.75 352.703 413.75C352.161 413.75 351.698 413.93 351.312 414.289C350.927 414.648 350.63 415.172 350.422 415.859C350.214 416.547 350.109 417.375 350.109 418.344C350.109 419.312 350.214 420.138 350.422 420.82C350.63 421.503 350.924 422.021 351.305 422.375C351.69 422.729 352.156 422.906 352.703 422.906ZM362.234 424.156C361.401 424.156 360.69 423.93 360.102 423.477C359.513 423.023 359.062 422.362 358.75 421.492C358.437 420.622 358.281 419.573 358.281 418.344C358.281 417.13 358.437 416.089 358.75 415.219C359.062 414.344 359.513 413.677 360.102 413.219C360.695 412.76 361.406 412.531 362.234 412.531C363.057 412.531 363.766 412.76 364.359 413.219C364.953 413.677 365.406 414.344 365.719 415.219C366.031 416.089 366.187 417.13 366.187 418.344C366.187 419.573 366.034 420.622 365.727 421.492C365.419 422.362 364.969 423.023 364.375 423.477C363.781 423.93 363.068 424.156 362.234 424.156ZM362.234 422.906C362.776 422.906 363.242 422.729 363.633 422.375C364.023 422.021 364.318 421.503 364.516 420.82C364.714 420.138 364.812 419.312 364.812 418.344C364.812 417.375 364.711 416.547 364.508 415.859C364.305 415.172 364.01 414.648 363.625 414.289C363.24 413.93 362.776 413.75 362.234 413.75C361.693 413.75 361.229 413.93 360.844 414.289C360.458 414.648 360.161 415.172 359.953 415.859C359.745 416.547 359.641 417.375 359.641 418.344C359.641 419.312 359.745 420.138 359.953 420.82C360.161 421.503 360.456 422.021 360.836 422.375C361.221 422.729 361.687 422.906 362.234 422.906Z" fill="#56555A"/> +<path d="M375.348 423.09H374.422V420.77H375.348V423.09ZM380.012 423.453H379.086V415.543H380.012V423.453ZM380.27 425.727H372.863V424.953H380.27V425.727ZM373.789 425.176H372.863V422.68H373.789V425.176ZM371.363 420.371C372.758 420.363 373.992 420.342 375.066 420.307C376.141 420.268 377.168 420.187 378.148 420.066L378.207 420.734C377.195 420.895 376.135 421 375.025 421.051C373.916 421.102 372.738 421.125 371.492 421.121L371.363 420.371ZM379.332 422.375H376.93V421.707H379.332V422.375ZM374.785 415.965C375.289 415.965 375.736 416.039 376.127 416.187C376.521 416.336 376.826 416.549 377.041 416.826C377.256 417.104 377.363 417.422 377.363 417.781C377.363 418.148 377.256 418.467 377.041 418.736C376.826 419.006 376.523 419.215 376.133 419.363C375.742 419.512 375.293 419.586 374.785 419.586C374.273 419.586 373.822 419.512 373.432 419.363C373.045 419.215 372.744 419.006 372.529 418.736C372.314 418.467 372.207 418.148 372.207 417.781C372.207 417.422 372.314 417.104 372.529 416.826C372.744 416.549 373.047 416.336 373.437 416.187C373.828 416.039 374.277 415.965 374.785 415.965ZM374.785 416.668C374.449 416.664 374.152 416.709 373.895 416.803C373.637 416.893 373.436 417.023 373.291 417.195C373.15 417.367 373.082 417.562 373.086 417.781C373.082 418.004 373.15 418.201 373.291 418.373C373.436 418.541 373.637 418.672 373.895 418.766C374.152 418.859 374.449 418.906 374.785 418.906C375.113 418.906 375.406 418.859 375.664 418.766C375.922 418.672 376.123 418.541 376.268 418.373C376.412 418.201 376.484 418.004 376.484 417.781C376.484 417.562 376.412 417.367 376.268 417.195C376.123 417.023 375.922 416.893 375.664 416.803C375.406 416.709 375.113 416.664 374.785 416.668Z" fill="#56555A"/> +<path d="M382 446H48C43.5817 446 40 449.582 40 454V478C40 482.418 43.5817 486 48 486H382C386.418 486 390 482.418 390 478V454C390 449.582 386.418 446 382 446Z" fill="#F9F8FD"/> +<path d="M61.4297 471.781H48.4297V470.172H61.4297V471.781ZM55.8828 470.57H53.9219V467.086H55.8828V470.57ZM51.8047 462.336H58V460.117H59.9844V467.531H49.8047V460.117H51.8047V462.336ZM58 465.937V463.914H51.8047V465.937H58ZM73.8359 467.398H63.7891V465.805H73.8359V467.398ZM75.2578 471.711H62.2578V470.07H75.2578V471.711ZM73.7344 462.016H65.7578V466.469H63.7891V460.406H73.7344V462.016ZM88.3984 473.437H86.5234V459.203H88.3984V473.437ZM83.8828 466.281H80.7734V464.695H83.8828V466.281ZM85.375 472.812H83.5V459.539H85.375V472.812ZM82.2969 460.906C82.2917 462.318 82.1224 463.596 81.7891 464.742C81.4609 465.888 80.9089 466.945 80.1328 467.914C79.362 468.878 78.3281 469.732 77.0312 470.477L75.9062 469.078C76.9844 468.437 77.849 467.737 78.5 466.977C79.1562 466.211 79.6302 465.367 79.9219 464.445C80.2135 463.523 80.362 462.479 80.3672 461.312V460.906H82.2969ZM81.0078 462.508H76.6875V460.906H81.0078V462.508ZM101.805 467.266H99.8125V459.234H101.805V467.266ZM101.805 473.281H92.2812V467.906H101.805V473.281ZM94.2422 471.68H99.8516V469.484H94.2422V471.68ZM94.0156 459.875C94.7448 459.875 95.4062 460.021 96 460.312C96.5937 460.599 97.0599 461.005 97.3984 461.531C97.737 462.052 97.9062 462.643 97.9062 463.305C97.9062 463.945 97.737 464.526 97.3984 465.047C97.0599 465.562 96.5937 465.969 96 466.266C95.4062 466.557 94.7448 466.703 94.0156 466.703C93.2812 466.703 92.6172 466.557 92.0234 466.266C91.4349 465.969 90.9714 465.562 90.6328 465.047C90.2943 464.526 90.125 463.945 90.125 463.305C90.125 462.643 90.2943 462.052 90.6328 461.531C90.9714 461.005 91.4349 460.599 92.0234 460.312C92.6172 460.021 93.2812 459.875 94.0156 459.875ZM94.0156 461.555C93.6354 461.555 93.2969 461.622 93 461.758C92.7083 461.893 92.4792 462.094 92.3125 462.359C92.151 462.625 92.0703 462.94 92.0703 463.305C92.0703 463.654 92.151 463.958 92.3125 464.219C92.4792 464.474 92.7083 464.672 93 464.812C93.2969 464.953 93.6354 465.023 94.0156 465.023C94.3854 465.023 94.7135 464.953 95 464.812C95.2917 464.672 95.5182 464.474 95.6797 464.219C95.8464 463.958 95.9297 463.654 95.9297 463.305C95.9297 462.94 95.849 462.625 95.6875 462.359C95.526 462.094 95.2995 461.893 95.0078 461.758C94.7161 461.622 94.3854 461.555 94.0156 461.555Z" fill="#56555A"/> +<path d="M320.5 472.156C319.828 472.156 319.216 472.026 318.664 471.766C318.117 471.505 317.68 471.148 317.352 470.695C317.029 470.242 316.854 469.729 316.828 469.156H318.187C318.219 469.49 318.341 469.789 318.555 470.055C318.768 470.32 319.044 470.531 319.383 470.687C319.727 470.844 320.099 470.922 320.5 470.922C320.984 470.922 321.417 470.812 321.797 470.594C322.182 470.375 322.484 470.076 322.703 469.695C322.922 469.315 323.031 468.891 323.031 468.422C323.031 467.937 322.919 467.503 322.695 467.117C322.471 466.727 322.159 466.419 321.758 466.195C321.357 465.971 320.906 465.859 320.406 465.859C319.911 465.849 319.487 465.927 319.133 466.094C318.779 466.255 318.5 466.516 318.297 466.875H316.937L317.734 460.687H323.859V461.937H318.906L318.484 465.25H318.594C318.854 465.052 319.164 464.893 319.523 464.773C319.888 464.654 320.266 464.594 320.656 464.594C321.365 464.594 322.005 464.755 322.578 465.078C323.151 465.401 323.599 465.854 323.922 466.437C324.245 467.016 324.406 467.667 324.406 468.391C324.406 469.109 324.237 469.755 323.898 470.328C323.56 470.901 323.094 471.349 322.5 471.672C321.911 471.995 321.245 472.156 320.5 472.156ZM326.344 470.969L330.203 466.906C330.708 466.365 331.094 465.927 331.359 465.594C331.63 465.26 331.836 464.943 331.977 464.641C332.117 464.333 332.187 464.01 332.187 463.672C332.187 463.292 332.089 462.958 331.891 462.672C331.693 462.38 331.422 462.154 331.078 461.992C330.74 461.831 330.359 461.75 329.937 461.75C329.495 461.75 329.107 461.839 328.773 462.016C328.445 462.193 328.19 462.443 328.008 462.766C327.826 463.083 327.734 463.453 327.734 463.875H326.406C326.401 463.219 326.552 462.638 326.859 462.133C327.172 461.628 327.602 461.234 328.148 460.953C328.695 460.672 329.307 460.531 329.984 460.531C330.656 460.531 331.258 460.669 331.789 460.945C332.326 461.221 332.745 461.599 333.047 462.078C333.349 462.557 333.5 463.089 333.5 463.672C333.495 464.104 333.414 464.518 333.258 464.914C333.107 465.305 332.846 465.74 332.477 466.219C332.107 466.698 331.583 467.286 330.906 467.984L328.312 470.656V470.75H333.703V472H326.359L326.344 470.969ZM336.312 475.203H335.156L336.016 470.953H337.531L336.312 475.203ZM343.172 472.156C342.339 472.156 341.628 471.93 341.039 471.477C340.451 471.023 340 470.362 339.687 469.492C339.375 468.622 339.219 467.573 339.219 466.344C339.219 465.13 339.375 464.089 339.687 463.219C340 462.344 340.451 461.677 341.039 461.219C341.633 460.76 342.344 460.531 343.172 460.531C343.995 460.531 344.703 460.76 345.297 461.219C345.891 461.677 346.344 462.344 346.656 463.219C346.969 464.089 347.125 465.13 347.125 466.344C347.125 467.573 346.971 468.622 346.664 469.492C346.357 470.362 345.906 471.023 345.312 471.477C344.719 471.93 344.005 472.156 343.172 472.156ZM343.172 470.906C343.714 470.906 344.18 470.729 344.57 470.375C344.961 470.021 345.255 469.503 345.453 468.82C345.651 468.138 345.75 467.312 345.75 466.344C345.75 465.375 345.648 464.547 345.445 463.859C345.242 463.172 344.948 462.648 344.562 462.289C344.177 461.93 343.714 461.75 343.172 461.75C342.63 461.75 342.167 461.93 341.781 462.289C341.396 462.648 341.099 463.172 340.891 463.859C340.682 464.547 340.578 465.375 340.578 466.344C340.578 467.312 340.682 468.138 340.891 468.82C341.099 469.503 341.393 470.021 341.773 470.375C342.159 470.729 342.625 470.906 343.172 470.906ZM352.703 472.156C351.87 472.156 351.159 471.93 350.57 471.477C349.982 471.023 349.531 470.362 349.219 469.492C348.906 468.622 348.75 467.573 348.75 466.344C348.75 465.13 348.906 464.089 349.219 463.219C349.531 462.344 349.982 461.677 350.57 461.219C351.164 460.76 351.875 460.531 352.703 460.531C353.526 460.531 354.234 460.76 354.828 461.219C355.422 461.677 355.875 462.344 356.187 463.219C356.5 464.089 356.656 465.13 356.656 466.344C356.656 467.573 356.503 468.622 356.195 469.492C355.888 470.362 355.437 471.023 354.844 471.477C354.25 471.93 353.536 472.156 352.703 472.156ZM352.703 470.906C353.245 470.906 353.711 470.729 354.102 470.375C354.492 470.021 354.786 469.503 354.984 468.82C355.182 468.138 355.281 467.312 355.281 466.344C355.281 465.375 355.18 464.547 354.977 463.859C354.773 463.172 354.479 462.648 354.094 462.289C353.708 461.93 353.245 461.75 352.703 461.75C352.161 461.75 351.698 461.93 351.312 462.289C350.927 462.648 350.63 463.172 350.422 463.859C350.214 464.547 350.109 465.375 350.109 466.344C350.109 467.312 350.214 468.138 350.422 468.82C350.63 469.503 350.924 470.021 351.305 470.375C351.69 470.729 352.156 470.906 352.703 470.906ZM362.234 472.156C361.401 472.156 360.69 471.93 360.102 471.477C359.513 471.023 359.062 470.362 358.75 469.492C358.437 468.622 358.281 467.573 358.281 466.344C358.281 465.13 358.437 464.089 358.75 463.219C359.062 462.344 359.513 461.677 360.102 461.219C360.695 460.76 361.406 460.531 362.234 460.531C363.057 460.531 363.766 460.76 364.359 461.219C364.953 461.677 365.406 462.344 365.719 463.219C366.031 464.089 366.187 465.13 366.187 466.344C366.187 467.573 366.034 468.622 365.727 469.492C365.419 470.362 364.969 471.023 364.375 471.477C363.781 471.93 363.068 472.156 362.234 472.156ZM362.234 470.906C362.776 470.906 363.242 470.729 363.633 470.375C364.023 470.021 364.318 469.503 364.516 468.82C364.714 468.138 364.812 467.312 364.812 466.344C364.812 465.375 364.711 464.547 364.508 463.859C364.305 463.172 364.01 462.648 363.625 462.289C363.24 461.93 362.776 461.75 362.234 461.75C361.693 461.75 361.229 461.93 360.844 462.289C360.458 462.648 360.161 463.172 359.953 463.859C359.745 464.547 359.641 465.375 359.641 466.344C359.641 467.312 359.745 468.138 359.953 468.82C360.161 469.503 360.456 470.021 360.836 470.375C361.221 470.729 361.687 470.906 362.234 470.906Z" fill="#56555A"/> +<path d="M375.348 471.09H374.422V468.77H375.348V471.09ZM380.012 471.453H379.086V463.543H380.012V471.453ZM380.27 473.727H372.863V472.953H380.27V473.727ZM373.789 473.176H372.863V470.68H373.789V473.176ZM371.363 468.371C372.758 468.363 373.992 468.342 375.066 468.307C376.141 468.268 377.168 468.187 378.148 468.066L378.207 468.734C377.195 468.895 376.135 469 375.025 469.051C373.916 469.102 372.738 469.125 371.492 469.121L371.363 468.371ZM379.332 470.375H376.93V469.707H379.332V470.375ZM374.785 463.965C375.289 463.965 375.736 464.039 376.127 464.187C376.521 464.336 376.826 464.549 377.041 464.826C377.256 465.104 377.363 465.422 377.363 465.781C377.363 466.148 377.256 466.467 377.041 466.736C376.826 467.006 376.523 467.215 376.133 467.363C375.742 467.512 375.293 467.586 374.785 467.586C374.273 467.586 373.822 467.512 373.432 467.363C373.045 467.215 372.744 467.006 372.529 466.736C372.314 466.467 372.207 466.148 372.207 465.781C372.207 465.422 372.314 465.104 372.529 464.826C372.744 464.549 373.047 464.336 373.437 464.187C373.828 464.039 374.277 463.965 374.785 463.965ZM374.785 464.668C374.449 464.664 374.152 464.709 373.895 464.803C373.637 464.893 373.436 465.023 373.291 465.195C373.15 465.367 373.082 465.562 373.086 465.781C373.082 466.004 373.15 466.201 373.291 466.373C373.436 466.541 373.637 466.672 373.895 466.766C374.152 466.859 374.449 466.906 374.785 466.906C375.113 466.906 375.406 466.859 375.664 466.766C375.922 466.672 376.123 466.541 376.268 466.373C376.412 466.201 376.484 466.004 376.484 465.781C376.484 465.562 376.412 465.367 376.268 465.195C376.123 465.023 375.922 464.893 375.664 464.803C375.406 464.709 375.113 464.664 374.785 464.668Z" fill="#56555A"/> +<path d="M58.0488 503.953H48.3223V502.764H58.0488V503.953ZM53.9062 503.314H52.4238V501.732H53.9062V503.314ZM53.9062 499.014H52.4238V497.443H53.9062V499.014ZM53.6426 499.277C53.6426 499.82 53.4687 500.303 53.1211 500.725C52.7773 501.143 52.2715 501.482 51.6035 501.744C50.9355 502.006 50.127 502.17 49.1777 502.236L48.7207 501.111C49.5371 501.057 50.2168 500.939 50.7598 500.76C51.3027 500.576 51.6992 500.357 51.9492 500.104C52.2031 499.85 52.3301 499.574 52.3301 499.277V499.066H53.6426V499.277ZM54.0059 499.277C54.002 499.57 54.127 499.846 54.3809 500.104C54.6348 500.357 55.0312 500.576 55.5703 500.76C56.1133 500.939 56.793 501.057 57.6094 501.111L57.1582 502.236C56.209 502.17 55.4004 502.006 54.7324 501.744C54.0645 501.482 53.5566 501.143 53.209 500.725C52.8613 500.303 52.6895 499.82 52.6934 499.277V499.066H54.0059V499.277ZM57.1055 499.547H49.2539V498.363H57.1055V499.547ZM53.168 504.451C53.9453 504.451 54.6113 504.521 55.166 504.662C55.7207 504.803 56.1445 505.008 56.4375 505.277C56.7305 505.547 56.8789 505.875 56.8828 506.262C56.8789 506.652 56.7305 506.982 56.4375 507.252C56.1445 507.525 55.7207 507.73 55.166 507.867C54.6113 508.008 53.9453 508.078 53.168 508.078C52.3828 508.078 51.7109 508.008 51.1523 507.867C50.5977 507.73 50.1719 507.525 49.875 507.252C49.5781 506.982 49.4297 506.652 49.4297 506.262C49.4297 505.875 49.5781 505.547 49.875 505.277C50.1719 505.008 50.5977 504.803 51.1523 504.662C51.7109 504.521 52.3828 504.451 53.168 504.451ZM53.168 505.559C52.6641 505.555 52.248 505.58 51.9199 505.635C51.5957 505.686 51.3516 505.764 51.1875 505.869C51.0273 505.971 50.9492 506.102 50.9531 506.262C50.9492 506.426 51.0273 506.561 51.1875 506.666C51.3516 506.768 51.5957 506.844 51.9199 506.895C52.248 506.945 52.6641 506.971 53.168 506.971C53.6602 506.971 54.0684 506.945 54.3926 506.895C54.7207 506.844 54.9668 506.768 55.1309 506.666C55.2949 506.561 55.377 506.426 55.377 506.262C55.377 506.102 55.2949 505.971 55.1309 505.869C54.9668 505.764 54.7207 505.686 54.3926 505.635C54.0684 505.58 53.6602 505.555 53.168 505.559ZM61.1836 498.053C61.6523 498.053 62.0742 498.164 62.4492 498.387C62.8242 498.605 63.1172 498.914 63.3281 499.312C63.543 499.707 63.6504 500.156 63.6504 500.66C63.6504 501.168 63.543 501.617 63.3281 502.008C63.1172 502.398 62.8242 502.703 62.4492 502.922C62.0742 503.141 61.6523 503.25 61.1836 503.25C60.7148 503.25 60.2949 503.141 59.9238 502.922C59.5527 502.703 59.2617 502.398 59.0508 502.008C58.8437 501.617 58.7402 501.168 58.7402 500.66C58.7402 500.16 58.8437 499.711 59.0508 499.312C59.2617 498.914 59.5527 498.605 59.9238 498.387C60.2949 498.164 60.7148 498.053 61.1836 498.053ZM61.1836 499.33C60.9648 499.33 60.7715 499.383 60.6035 499.488C60.4355 499.59 60.3047 499.742 60.2109 499.945C60.1172 500.145 60.0723 500.383 60.0762 500.66C60.0723 500.937 60.1172 501.178 60.2109 501.381C60.3047 501.58 60.4355 501.734 60.6035 501.844C60.7715 501.953 60.9648 502.008 61.1836 502.008C61.3984 502.008 61.5898 501.953 61.7578 501.844C61.9297 501.734 62.0605 501.58 62.1504 501.381C62.2441 501.178 62.291 500.937 62.291 500.66C62.291 500.383 62.2441 500.145 62.1504 499.945C62.0605 499.742 61.9316 499.59 61.7637 499.488C61.5957 499.383 61.4023 499.33 61.1836 499.33ZM67.8516 503.795H66.4277V497.426H67.8516V503.795ZM66.832 501.205H65.1035V500.01H66.832V501.205ZM65.5605 503.736H64.166V497.607H65.5605V503.736ZM67.8516 508.078H66.3691V505.453H60.4805V504.264H67.8516V508.078Z" fill="#56555A"/> +<path d="M327.797 507H326.73V499.617H326.684L324.621 500.988V499.922L326.73 498.516H327.797V507ZM332.836 507.117C332.211 507.117 331.678 506.947 331.236 506.607C330.795 506.268 330.457 505.771 330.223 505.119C329.988 504.467 329.871 503.68 329.871 502.758C329.871 501.848 329.988 501.066 330.223 500.414C330.457 499.758 330.795 499.258 331.236 498.914C331.682 498.57 332.215 498.398 332.836 498.398C333.453 498.398 333.984 498.57 334.43 498.914C334.875 499.258 335.215 499.758 335.449 500.414C335.684 501.066 335.801 501.848 335.801 502.758C335.801 503.68 335.686 504.467 335.455 505.119C335.225 505.771 334.887 506.268 334.441 506.607C333.996 506.947 333.461 507.117 332.836 507.117ZM332.836 506.18C333.242 506.18 333.592 506.047 333.885 505.781C334.178 505.516 334.398 505.127 334.547 504.615C334.695 504.104 334.77 503.484 334.77 502.758C334.77 502.031 334.693 501.41 334.541 500.895C334.389 500.379 334.168 499.986 333.879 499.717C333.59 499.447 333.242 499.312 332.836 499.312C332.43 499.312 332.082 499.447 331.793 499.717C331.504 499.986 331.281 500.379 331.125 500.895C330.969 501.41 330.891 502.031 330.891 502.758C330.891 503.484 330.969 504.104 331.125 504.615C331.281 505.127 331.502 505.516 331.787 505.781C332.076 506.047 332.426 506.18 332.836 506.18ZM336.996 504.398L340.816 498.516H341.449V499.852H341.004L338.133 504.27V504.34H343.301V505.266H336.996V504.398ZM341.109 505.008V504.598V498.516H342.117V507H341.109V505.008ZM344.73 509.402H343.863L344.508 506.215H345.645L344.73 509.402ZM349.875 507.117C349.25 507.117 348.717 506.947 348.275 506.607C347.834 506.268 347.496 505.771 347.262 505.119C347.027 504.467 346.91 503.68 346.91 502.758C346.91 501.848 347.027 501.066 347.262 500.414C347.496 499.758 347.834 499.258 348.275 498.914C348.721 498.57 349.254 498.398 349.875 498.398C350.492 498.398 351.023 498.57 351.469 498.914C351.914 499.258 352.254 499.758 352.488 500.414C352.723 501.066 352.84 501.848 352.84 502.758C352.84 503.68 352.725 504.467 352.494 505.119C352.264 505.771 351.926 506.268 351.48 506.607C351.035 506.947 350.5 507.117 349.875 507.117ZM349.875 506.18C350.281 506.18 350.631 506.047 350.924 505.781C351.217 505.516 351.437 505.127 351.586 504.615C351.734 504.104 351.809 503.484 351.809 502.758C351.809 502.031 351.732 501.41 351.58 500.895C351.428 500.379 351.207 499.986 350.918 499.717C350.629 499.447 350.281 499.312 349.875 499.312C349.469 499.312 349.121 499.447 348.832 499.717C348.543 499.986 348.32 500.379 348.164 500.895C348.008 501.41 347.93 502.031 347.93 502.758C347.93 503.484 348.008 504.104 348.164 504.615C348.32 505.127 348.541 505.516 348.826 505.781C349.115 506.047 349.465 506.18 349.875 506.18ZM357.023 507.117C356.398 507.117 355.865 506.947 355.424 506.607C354.982 506.268 354.645 505.771 354.41 505.119C354.176 504.467 354.059 503.68 354.059 502.758C354.059 501.848 354.176 501.066 354.41 500.414C354.645 499.758 354.982 499.258 355.424 498.914C355.869 498.57 356.402 498.398 357.023 498.398C357.641 498.398 358.172 498.57 358.617 498.914C359.062 499.258 359.402 499.758 359.637 500.414C359.871 501.066 359.988 501.848 359.988 502.758C359.988 503.68 359.873 504.467 359.643 505.119C359.412 505.771 359.074 506.268 358.629 506.607C358.184 506.947 357.648 507.117 357.023 507.117ZM357.023 506.18C357.43 506.18 357.779 506.047 358.072 505.781C358.365 505.516 358.586 505.127 358.734 504.615C358.883 504.104 358.957 503.484 358.957 502.758C358.957 502.031 358.881 501.41 358.729 500.895C358.576 500.379 358.355 499.986 358.066 499.717C357.777 499.447 357.43 499.312 357.023 499.312C356.617 499.312 356.27 499.447 355.98 499.717C355.691 499.986 355.469 500.379 355.312 500.895C355.156 501.41 355.078 502.031 355.078 502.758C355.078 503.484 355.156 504.104 355.312 504.615C355.469 505.127 355.689 505.516 355.975 505.781C356.264 506.047 356.613 506.18 357.023 506.18ZM364.172 507.117C363.547 507.117 363.014 506.947 362.572 506.607C362.131 506.268 361.793 505.771 361.559 505.119C361.324 504.467 361.207 503.68 361.207 502.758C361.207 501.848 361.324 501.066 361.559 500.414C361.793 499.758 362.131 499.258 362.572 498.914C363.018 498.57 363.551 498.398 364.172 498.398C364.789 498.398 365.32 498.57 365.766 498.914C366.211 499.258 366.551 499.758 366.785 500.414C367.02 501.066 367.137 501.848 367.137 502.758C367.137 503.68 367.021 504.467 366.791 505.119C366.561 505.771 366.223 506.268 365.777 506.607C365.332 506.947 364.797 507.117 364.172 507.117ZM364.172 506.18C364.578 506.18 364.928 506.047 365.221 505.781C365.514 505.516 365.734 505.127 365.883 504.615C366.031 504.104 366.105 503.484 366.105 502.758C366.105 502.031 366.029 501.41 365.877 500.895C365.725 500.379 365.504 499.986 365.215 499.717C364.926 499.447 364.578 499.312 364.172 499.312C363.766 499.312 363.418 499.447 363.129 499.717C362.84 499.986 362.617 500.379 362.461 500.895C362.305 501.41 362.227 502.031 362.227 502.758C362.227 503.484 362.305 504.104 362.461 504.615C362.617 505.127 362.838 505.516 363.123 505.781C363.412 506.047 363.762 506.18 364.172 506.18ZM375.105 505.09H374.18V502.77H375.105V505.09ZM379.77 505.453H378.844V497.543H379.77V505.453ZM380.027 507.727H372.621V506.953H380.027V507.727ZM373.547 507.176H372.621V504.68H373.547V507.176ZM371.121 502.371C372.516 502.363 373.75 502.342 374.824 502.307C375.898 502.268 376.926 502.187 377.906 502.066L377.965 502.734C376.953 502.895 375.893 503 374.783 503.051C373.674 503.102 372.496 503.125 371.25 503.121L371.121 502.371ZM379.09 504.375H376.687V503.707H379.09V504.375ZM374.543 497.965C375.047 497.965 375.494 498.039 375.885 498.187C376.279 498.336 376.584 498.549 376.799 498.826C377.014 499.104 377.121 499.422 377.121 499.781C377.121 500.148 377.014 500.467 376.799 500.736C376.584 501.006 376.281 501.215 375.891 501.363C375.5 501.512 375.051 501.586 374.543 501.586C374.031 501.586 373.58 501.512 373.189 501.363C372.803 501.215 372.502 501.006 372.287 500.736C372.072 500.467 371.965 500.148 371.965 499.781C371.965 499.422 372.072 499.104 372.287 498.826C372.502 498.549 372.805 498.336 373.195 498.187C373.586 498.039 374.035 497.965 374.543 497.965ZM374.543 498.668C374.207 498.664 373.91 498.709 373.652 498.803C373.395 498.893 373.193 499.023 373.049 499.195C372.908 499.367 372.84 499.562 372.844 499.781C372.84 500.004 372.908 500.201 373.049 500.373C373.193 500.541 373.395 500.672 373.652 500.766C373.91 500.859 374.207 500.906 374.543 500.906C374.871 500.906 375.164 500.859 375.422 500.766C375.68 500.672 375.881 500.541 376.025 500.373C376.17 500.201 376.242 500.004 376.242 499.781C376.242 499.562 376.17 499.367 376.025 499.195C375.881 499.023 375.68 498.893 375.422 498.803C375.164 498.709 374.871 498.664 374.543 498.668Z" fill="#B2B1B6"/> +<path d="M390 528H40C35.5817 528 32 531.582 32 536V560C32 564.418 35.5817 568 40 568H390C394.418 568 398 564.418 398 560V536C398 531.582 394.418 528 390 528Z" fill="white"/> +<path d="M53.4297 553.742H40.4297V552.148H53.4297V553.742ZM47.8437 552.57H45.8594V548.922H47.8437V552.57ZM47.5312 543.047C47.5312 544.062 47.2891 545.01 46.8047 545.891C46.3255 546.766 45.6354 547.51 44.7344 548.125C43.8385 548.74 42.7891 549.159 41.5859 549.383L40.7266 547.719C41.763 547.557 42.6641 547.237 43.4297 546.758C44.1953 546.273 44.776 545.708 45.1719 545.062C45.5729 544.411 45.776 543.74 45.7812 543.047V542.039H47.5312V543.047ZM47.8984 543.047C47.8984 543.745 48.099 544.419 48.5 545.07C48.9062 545.716 49.4922 546.279 50.2578 546.758C51.0286 547.237 51.9375 547.557 52.9844 547.719L52.1328 549.383C50.9245 549.159 49.8698 548.745 48.9687 548.141C48.0677 547.531 47.375 546.789 46.8906 545.914C46.4062 545.034 46.1667 544.078 46.1719 543.047V542.039H47.8984V543.047ZM64.9609 544.82H60.7422V543.219H64.9609V544.82ZM64.9609 548.258H60.7422V546.664H64.9609V548.258ZM66.2344 551.633H64.25V541.234H66.2344V551.633ZM66.5781 555.195H56.7969V553.586H66.5781V555.195ZM58.7969 554.406H56.7969V550.578H58.7969V554.406ZM58.2187 542.055C58.9062 542.055 59.5365 542.214 60.1094 542.531C60.6875 542.849 61.1432 543.289 61.4766 543.852C61.8099 544.414 61.9792 545.047 61.9844 545.75C61.9792 546.443 61.8073 547.068 61.4687 547.625C61.1354 548.182 60.6823 548.622 60.1094 548.945C59.5365 549.263 58.9062 549.422 58.2187 549.422C57.5052 549.422 56.8594 549.263 56.2812 548.945C55.7083 548.622 55.2552 548.182 54.9219 547.625C54.5937 547.068 54.4297 546.443 54.4297 545.75C54.4297 545.047 54.5937 544.414 54.9219 543.852C55.2552 543.289 55.7083 542.849 56.2812 542.531C56.8594 542.214 57.5052 542.055 58.2187 542.055ZM58.2187 543.828C57.849 543.823 57.5208 543.898 57.2344 544.055C56.9479 544.211 56.724 544.435 56.5625 544.727C56.401 545.018 56.3203 545.359 56.3203 545.75C56.3203 546.135 56.401 546.471 56.5625 546.758C56.724 547.044 56.9479 547.266 57.2344 547.422C57.5208 547.573 57.849 547.651 58.2187 547.656C58.5729 547.651 58.8906 547.573 59.1719 547.422C59.4531 547.266 59.6745 547.044 59.8359 546.758C59.9974 546.471 60.0781 546.135 60.0781 545.75C60.0781 545.359 59.9974 545.021 59.8359 544.734C59.6745 544.443 59.4531 544.219 59.1719 544.062C58.8906 543.901 58.5729 543.823 58.2187 543.828ZM69.7266 557.297H68.0703L68.8437 552.852H71.0781L69.7266 557.297ZM83.9297 547.648H81.5078V546.016H83.9297V547.648ZM80.0156 544.891C80.0156 546.005 79.901 547.06 79.6719 548.055C79.4479 549.044 79.0964 549.937 78.6172 550.734C78.1432 551.526 77.5417 552.143 76.8125 552.586L75.5937 551.102C76.2656 550.69 76.8177 550.156 77.25 549.5C77.6823 548.839 77.9948 548.12 78.1875 547.344C78.3854 546.568 78.4844 545.75 78.4844 544.891V542.437H80.0156V544.891ZM80.4141 544.797C80.4141 545.641 80.4974 546.43 80.6641 547.164C80.8307 547.893 81.1068 548.57 81.4922 549.195C81.8776 549.815 82.3802 550.326 83 550.727L81.9219 552.258C81.1979 551.82 80.612 551.216 80.1641 550.445C79.7161 549.674 79.3958 548.818 79.2031 547.875C79.0104 546.927 78.9167 545.901 78.9219 544.797V542.437H80.4141V544.797ZM88.1875 555.437H86.2734V541.203H88.1875V555.437ZM85.2109 554.781H83.3437V541.422H85.2109V554.781ZM101.672 552.062H99.6875V541.234H101.672V552.062ZM100.43 546.375H97.7656V544.766H100.43V546.375ZM100.43 549.383H97.7656V547.797H100.43V549.383ZM97.6172 544.289H89.7187V542.719H97.6172V544.289ZM93.75 544.789C94.3906 544.789 94.9661 544.909 95.4766 545.148C95.9922 545.383 96.3932 545.714 96.6797 546.141C96.9714 546.568 97.1172 547.049 97.1172 547.586C97.1172 548.128 96.9714 548.612 96.6797 549.039C96.3932 549.461 95.9948 549.792 95.4844 550.031C94.974 550.266 94.3958 550.383 93.75 550.383C93.1146 550.383 92.5443 550.266 92.0391 550.031C91.5339 549.792 91.1354 549.461 90.8437 549.039C90.5573 548.612 90.4167 548.128 90.4219 547.586C90.4167 547.049 90.5573 546.57 90.8437 546.148C91.1354 545.721 91.5339 545.388 92.0391 545.148C92.5443 544.909 93.1146 544.789 93.75 544.789ZM93.75 546.344C93.4583 546.349 93.2005 546.401 92.9766 546.5C92.7578 546.594 92.5859 546.734 92.4609 546.922C92.3359 547.109 92.2734 547.331 92.2734 547.586C92.2734 547.857 92.3359 548.086 92.4609 548.273C92.5859 548.461 92.7578 548.604 92.9766 548.703C93.2005 548.802 93.4583 548.852 93.75 548.852C94.0417 548.852 94.2995 548.802 94.5234 548.703C94.7474 548.604 94.9219 548.461 95.0469 548.273C95.1771 548.081 95.2422 547.852 95.2422 547.586C95.2422 547.331 95.1771 547.109 95.0469 546.922C94.9219 546.729 94.7474 546.586 94.5234 546.492C94.2995 546.398 94.0417 546.349 93.75 546.344ZM94.7656 543.687H92.7734V541.195H94.7656V543.687ZM101.977 555.195H92.2031V553.586H101.977V555.195ZM94.2187 554.328H92.2031V551.133H94.2187V554.328ZM105.164 557.297H103.508L104.281 552.852H106.516L105.164 557.297ZM116.477 544.031C116.471 544.937 116.315 545.789 116.008 546.586C115.706 547.378 115.247 548.07 114.633 548.664C114.018 549.258 113.271 549.701 112.391 549.992L111.359 548.43C112.12 548.19 112.758 547.841 113.273 547.383C113.794 546.924 114.18 546.409 114.43 545.836C114.685 545.258 114.812 544.656 114.812 544.031V542.789H116.477V544.031ZM116.836 544.031C116.836 544.62 116.958 545.185 117.203 545.727C117.453 546.268 117.833 546.755 118.344 547.187C118.854 547.615 119.482 547.94 120.227 548.164L119.219 549.734C118.349 549.453 117.615 549.031 117.016 548.469C116.417 547.901 115.963 547.237 115.656 546.477C115.354 545.716 115.206 544.901 115.211 544.031V542.789H116.836V544.031ZM119.703 543.828H111.883V542.234H119.703V543.828ZM123.195 551.508H121.203V541.234H123.195V551.508ZM123.586 555.195H113.672V553.586H123.586V555.195ZM115.687 554.391H113.672V550.57H115.687V554.391ZM137.516 544.609H125.68V543.016H137.516V544.609ZM138.133 553.992H125.133V552.383H138.133V553.992ZM132.578 553.008H130.602V550.469H132.578V553.008ZM131.594 545.227C132.573 545.227 133.427 545.336 134.156 545.555C134.891 545.773 135.453 546.094 135.844 546.516C136.24 546.932 136.437 547.424 136.437 547.992C136.437 548.57 136.24 549.07 135.844 549.492C135.453 549.909 134.893 550.232 134.164 550.461C133.435 550.685 132.578 550.799 131.594 550.805C130.594 550.799 129.729 550.685 129 550.461C128.271 550.232 127.708 549.909 127.312 549.492C126.922 549.07 126.729 548.57 126.734 547.992C126.729 547.419 126.922 546.924 127.312 546.508C127.708 546.091 128.271 545.773 129 545.555C129.734 545.336 130.599 545.227 131.594 545.227ZM131.594 546.781C130.969 546.786 130.448 546.833 130.031 546.922C129.62 547.005 129.307 547.138 129.094 547.32C128.88 547.497 128.776 547.721 128.781 547.992C128.776 548.263 128.88 548.49 129.094 548.672C129.307 548.849 129.62 548.984 130.031 549.078C130.448 549.167 130.969 549.211 131.594 549.211C132.203 549.211 132.714 549.167 133.125 549.078C133.542 548.984 133.857 548.849 134.07 548.672C134.284 548.49 134.391 548.263 134.391 547.992C134.391 547.721 134.284 547.497 134.07 547.32C133.857 547.138 133.542 547.005 133.125 546.922C132.714 546.833 132.203 546.786 131.594 546.781ZM132.578 544.008H130.602V541.359H132.578V544.008ZM140.602 557.297H138.945L139.719 552.852H141.953L140.602 557.297ZM148.211 550.523C149.383 550.518 150.331 550.497 151.055 550.461C151.779 550.424 152.521 550.352 153.281 550.242L153.43 551.875C152.643 552 151.865 552.083 151.094 552.125C150.328 552.167 149.367 552.185 148.211 552.18H147.219V550.523H148.211ZM153.008 544.273H149.117V551.195H147.219V542.711H153.008V544.273ZM152.734 547.961H148.578V546.43H152.734V547.961ZM159.062 555.437H157.148V541.203H159.062V555.437ZM157.781 548.328H155.375V546.727H157.781V548.328ZM155.93 554.781H154.039V541.422H155.93V554.781ZM173.539 550.766H160.57V549.195H173.539V550.766ZM168.211 552.523H166.242V550.344H168.211V552.523ZM172.125 555.195H162.07V553.617H172.125V555.195ZM164.07 554.602H162.07V551.641H164.07V554.602ZM172.852 543.906H161.18V542.414H172.852V543.906ZM167.047 544.297C168.573 544.297 169.75 544.482 170.578 544.852C171.406 545.216 171.82 545.747 171.82 546.445C171.82 546.919 171.635 547.32 171.266 547.648C170.896 547.971 170.352 548.219 169.633 548.391C168.919 548.562 168.057 548.648 167.047 548.648C166.031 548.648 165.167 548.562 164.453 548.391C163.74 548.219 163.195 547.971 162.82 547.648C162.445 547.32 162.258 546.919 162.258 546.445C162.258 545.747 162.672 545.216 163.5 544.852C164.333 544.482 165.516 544.297 167.047 544.297ZM167.047 545.687C166.396 545.682 165.87 545.706 165.469 545.758C165.068 545.81 164.771 545.893 164.578 546.008C164.385 546.122 164.292 546.268 164.297 546.445C164.292 546.633 164.385 546.784 164.578 546.898C164.771 547.008 165.065 547.091 165.461 547.148C165.862 547.201 166.391 547.227 167.047 547.227C167.693 547.227 168.214 547.201 168.609 547.148C169.005 547.091 169.299 547.008 169.492 546.898C169.69 546.784 169.789 546.633 169.789 546.445C169.789 546.268 169.69 546.122 169.492 546.008C169.299 545.893 169.005 545.81 168.609 545.758C168.214 545.706 167.693 545.682 167.047 545.687ZM168.039 543.359H166.039V541.141H168.039V543.359ZM191.094 548.336H178.102V546.773H191.094V548.336ZM189.539 545.984H179.711V544.414H189.539V545.984ZM189.437 543.086H181.703V545.75H179.711V541.508H189.437V543.086ZM189.484 552.883H181.562V554.164H179.602V551.469H187.516V550.672H179.594V549.172H189.484V552.883ZM189.859 555.32H179.602V553.773H189.859V555.32ZM195.844 542.211C196.552 542.211 197.185 542.419 197.742 542.836C198.305 543.247 198.742 543.839 199.055 544.609C199.367 545.375 199.523 546.266 199.523 547.281C199.523 548.302 199.367 549.198 199.055 549.969C198.742 550.734 198.305 551.323 197.742 551.734C197.185 552.146 196.552 552.352 195.844 552.352C195.125 552.352 194.487 552.146 193.93 551.734C193.372 551.323 192.935 550.734 192.617 549.969C192.299 549.198 192.141 548.302 192.141 547.281C192.141 546.266 192.299 545.375 192.617 544.609C192.935 543.839 193.372 543.247 193.93 542.836C194.487 542.419 195.125 542.211 195.844 542.211ZM195.844 544.016C195.484 544.01 195.172 544.135 194.906 544.391C194.641 544.646 194.432 545.018 194.281 545.508C194.13 545.997 194.057 546.589 194.062 547.281C194.057 547.974 194.13 548.565 194.281 549.055C194.432 549.544 194.641 549.917 194.906 550.172C195.172 550.422 195.484 550.547 195.844 550.547C196.203 550.547 196.518 550.422 196.789 550.172C197.06 549.917 197.268 549.544 197.414 549.055C197.56 548.565 197.633 547.974 197.633 547.281C197.633 546.589 197.56 545.997 197.414 545.508C197.268 545.013 197.06 544.641 196.789 544.391C196.518 544.135 196.203 544.01 195.844 544.016ZM203.922 555.477H201.945V541.203H203.922V555.477ZM202.797 547.953H198.93V546.352H202.797V547.953ZM213.187 548.516H211.227V546.398H213.187V548.516ZM212.234 541.422C213.281 541.422 214.193 541.534 214.969 541.758C215.75 541.977 216.349 542.294 216.766 542.711C217.187 543.128 217.398 543.617 217.398 544.18C217.398 544.742 217.187 545.232 216.766 545.648C216.349 546.065 215.753 546.385 214.977 546.609C214.201 546.828 213.286 546.935 212.234 546.93C211.187 546.935 210.273 546.828 209.492 546.609C208.711 546.385 208.107 546.065 207.68 545.648C207.258 545.232 207.047 544.742 207.047 544.18C207.047 543.617 207.26 543.128 207.687 542.711C208.115 542.294 208.716 541.977 209.492 541.758C210.273 541.534 211.187 541.422 212.234 541.422ZM212.234 542.953C211.573 542.953 211.008 543 210.539 543.094C210.076 543.182 209.721 543.32 209.477 543.508C209.237 543.69 209.117 543.914 209.117 544.18C209.117 544.456 209.237 544.687 209.477 544.875C209.721 545.057 210.073 545.195 210.531 545.289C210.995 545.378 211.562 545.422 212.234 545.422C212.896 545.422 213.458 545.378 213.922 545.289C214.391 545.195 214.745 545.057 214.984 544.875C215.224 544.687 215.344 544.456 215.344 544.18C215.344 543.914 215.221 543.69 214.977 543.508C214.732 543.32 214.378 543.182 213.914 543.094C213.451 543 212.891 542.953 212.234 542.953ZM217.172 555.281H207.258V550.43H217.172V555.281ZM209.219 553.68H215.219V552.008H209.219V553.68ZM218.727 549.492H205.758V547.914H218.727V549.492Z" fill="#56555A"/> +<path d="M386 576H44C37.3726 576 32 581.373 32 588V720C32 726.627 37.3726 732 44 732H386C392.627 732 398 726.627 398 720V588C398 581.373 392.627 576 386 576Z" fill="white"/> +<path d="M48.6562 595.729L51.709 592.922C52.0059 592.633 52.2383 592.393 52.4062 592.201C52.5742 592.01 52.7031 591.818 52.793 591.627C52.8828 591.436 52.9277 591.23 52.9277 591.012C52.9277 590.77 52.8691 590.557 52.752 590.373C52.6348 590.189 52.4746 590.049 52.2715 589.951C52.0684 589.85 51.8379 589.799 51.5801 589.799C51.3145 589.799 51.082 589.852 50.8828 589.957C50.6875 590.062 50.5352 590.215 50.4258 590.414C50.3164 590.613 50.2617 590.848 50.2617 591.117H48.5859C48.5859 590.57 48.7109 590.092 48.9609 589.682C49.2109 589.271 49.5645 588.955 50.0215 588.732C50.4785 588.51 51.0039 588.398 51.5977 588.398C52.1953 588.398 52.7227 588.504 53.1797 588.715C53.6406 588.926 53.9961 589.221 54.2461 589.6C54.4961 589.979 54.6211 590.412 54.6211 590.9C54.6211 591.236 54.5566 591.559 54.4277 591.867C54.3027 592.172 54.0801 592.514 53.7598 592.893C53.4395 593.268 52.9883 593.719 52.4062 594.246L51.1113 595.494V595.553H54.7441V597H48.6621L48.6562 595.729ZM59.1914 590.76C59.1875 591.525 59.0742 592.262 58.8516 592.969C58.6289 593.676 58.2969 594.307 57.8555 594.861C57.418 595.412 56.8867 595.824 56.2617 596.098L55.4414 594.937C55.9961 594.695 56.4668 594.35 56.8535 593.9C57.2441 593.447 57.5352 592.949 57.7266 592.406C57.918 591.863 58.0137 591.314 58.0137 590.76V590.15H59.1914V590.76ZM59.4961 590.76C59.4922 591.283 59.582 591.803 59.7656 592.318C59.9531 592.83 60.2324 593.305 60.6035 593.742C60.9746 594.176 61.4316 594.521 61.9746 594.779L61.1484 595.916C60.543 595.643 60.0293 595.238 59.6074 594.703C59.1855 594.164 58.8672 593.555 58.6523 592.875C58.4375 592.191 58.332 591.486 58.3359 590.76V590.15H59.4961V590.76ZM61.6758 590.344H55.8047V589.154H61.6758V590.344ZM59.5078 589.775H58.0078V587.648H59.5078V589.775ZM64.0547 598.078H62.5547V587.402H64.0547V598.078ZM65.6367 592.805H63.7266V591.551H65.6367V592.805Z" fill="#56555A"/> +<path d="M367.633 597.117C367.047 597.117 366.525 597.016 366.068 596.812C365.611 596.609 365.256 596.328 365.002 595.969C364.748 595.609 364.621 595.203 364.621 594.75C364.621 594.391 364.697 594.055 364.85 593.742C365.002 593.43 365.209 593.174 365.471 592.975C365.732 592.771 366.023 592.645 366.344 592.594V592.547C366.066 592.484 365.822 592.361 365.611 592.178C365.404 591.994 365.242 591.77 365.125 591.504C365.008 591.238 364.949 590.953 364.949 590.648C364.949 590.223 365.064 589.84 365.295 589.5C365.525 589.156 365.844 588.887 366.25 588.691C366.66 588.496 367.121 588.398 367.633 588.398C368.141 588.398 368.6 588.496 369.01 588.691C369.42 588.887 369.74 589.156 369.971 589.5C370.205 589.84 370.324 590.223 370.328 590.648C370.324 590.953 370.262 591.238 370.141 591.504C370.023 591.77 369.859 591.994 369.648 592.178C369.437 592.361 369.195 592.484 368.922 592.547V592.594C369.238 592.645 369.527 592.771 369.789 592.975C370.055 593.174 370.264 593.43 370.416 593.742C370.572 594.055 370.652 594.391 370.656 594.75C370.652 595.203 370.521 595.609 370.264 595.969C370.01 596.328 369.652 596.609 369.191 596.812C368.734 597.016 368.215 597.117 367.633 597.117ZM367.633 596.191C368.031 596.191 368.379 596.127 368.676 595.998C368.973 595.869 369.201 595.693 369.361 595.471C369.521 595.248 369.602 594.988 369.602 594.691C369.602 594.383 369.518 594.105 369.35 593.859C369.182 593.609 368.947 593.414 368.646 593.273C368.346 593.133 368.008 593.062 367.633 593.062C367.258 593.062 366.922 593.133 366.625 593.273C366.328 593.414 366.094 593.609 365.922 593.859C365.754 594.105 365.672 594.383 365.676 594.691C365.672 594.988 365.748 595.248 365.904 595.471C366.064 595.693 366.291 595.869 366.584 595.998C366.881 596.127 367.23 596.191 367.633 596.191ZM367.633 592.172C367.953 592.172 368.24 592.109 368.494 591.984C368.748 591.859 368.945 591.689 369.086 591.475C369.227 591.26 369.297 591.012 369.297 590.73C369.297 590.449 369.229 590.201 369.092 589.986C368.955 589.771 368.76 589.605 368.506 589.488C368.252 589.371 367.961 589.312 367.633 589.312C367.301 589.312 367.01 589.371 366.76 589.488C366.514 589.605 366.32 589.771 366.18 589.986C366.039 590.201 365.969 590.449 365.969 590.73C365.969 591.012 366.041 591.26 366.186 591.475C366.33 591.689 366.527 591.859 366.777 591.984C367.027 592.109 367.312 592.172 367.633 592.172ZM379.773 589.992H376.703V589.23H379.773V589.992ZM379.785 592.066H376.703V591.293H379.785V592.066ZM380.336 593.707H379.41V587.531H380.336V593.707ZM376.973 592.957H372.191V588.328H376.973V592.957ZM373.105 592.207H376.07V589.078H373.105V592.207ZM376.879 594.012C377.598 594.012 378.219 594.088 378.742 594.24C379.266 594.393 379.668 594.617 379.949 594.914C380.23 595.211 380.371 595.566 380.371 595.98C380.371 596.391 380.23 596.74 379.949 597.029C379.668 597.322 379.266 597.545 378.742 597.697C378.219 597.85 377.598 597.926 376.879 597.926C376.156 597.926 375.533 597.85 375.01 597.697C374.49 597.545 374.09 597.322 373.809 597.029C373.527 596.74 373.387 596.391 373.387 595.98C373.387 595.566 373.527 595.211 373.809 594.914C374.09 594.617 374.49 594.393 375.01 594.24C375.533 594.088 376.156 594.012 376.879 594.012ZM376.879 594.727C376.348 594.73 375.889 594.783 375.502 594.885C375.115 594.982 374.818 595.125 374.611 595.312C374.404 595.5 374.301 595.723 374.301 595.98C374.301 596.23 374.404 596.447 374.611 596.631C374.818 596.814 375.115 596.955 375.502 597.053C375.889 597.15 376.348 597.199 376.879 597.199C377.406 597.199 377.863 597.15 378.25 597.053C378.641 596.955 378.939 596.814 379.146 596.631C379.354 596.447 379.457 596.23 379.457 595.98C379.457 595.723 379.354 595.5 379.146 595.312C378.939 595.125 378.643 594.982 378.256 594.885C377.869 594.783 377.41 594.73 376.879 594.727Z" fill="#B2B1B6"/> +<path d="M364 598.916H381.648V599.73H364V598.916Z" fill="#B2B1B6"/> +<path d="M382 610H48C43.5817 610 40 613.582 40 618V642C40 646.418 43.5817 650 48 650H382C386.418 650 390 646.418 390 642V618C390 613.582 386.418 610 382 610Z" fill="#F9F8FD"/> +<path d="M60.0156 630.953H49.875V629.352H60.0156V630.953ZM61.4297 635.812H48.4297V634.219H61.4297V635.812ZM55.9141 634.664H53.9219V630.281H55.9141V634.664ZM51.9141 630.031H49.875V624.305H51.9141V630.031ZM63.6406 632.625C64.6823 632.625 65.5755 632.607 66.3203 632.57C67.0703 632.534 67.8516 632.453 68.6641 632.328L68.8047 633.914C67.9349 634.06 67.1016 634.159 66.3047 634.211C65.513 634.263 64.625 634.286 63.6406 634.281H62.6484V632.625H63.6406ZM68.0469 630.078H64.5703V633.234H62.6484V628.484H66.125V626.211H62.6328V624.602H68.0469V630.078ZM74.5391 637.437H72.6641V623.203H74.5391V637.437ZM73.1172 630.203H70.7031V628.602H73.1172V630.203ZM71.2891 636.75H69.4609V623.461H71.2891V636.75ZM82.6953 631.93C83.6797 631.93 84.5312 632.036 85.25 632.25C85.974 632.464 86.5286 632.779 86.9141 633.195C87.2995 633.607 87.4922 634.099 87.4922 634.672C87.4922 635.25 87.2995 635.747 86.9141 636.164C86.5286 636.581 85.974 636.898 85.25 637.117C84.5312 637.341 83.6797 637.456 82.6953 637.461C81.6953 637.456 80.8281 637.341 80.0937 637.117C79.3646 636.898 78.8021 636.581 78.4062 636.164C78.0156 635.747 77.8203 635.25 77.8203 634.672C77.8203 634.099 78.0156 633.607 78.4062 633.195C78.8021 632.779 79.3646 632.464 80.0937 632.25C80.8281 632.036 81.6953 631.93 82.6953 631.93ZM82.6953 633.469C82.0703 633.469 81.5443 633.513 81.1172 633.602C80.6901 633.69 80.3672 633.823 80.1484 634C79.9297 634.177 79.8229 634.401 79.8281 634.672C79.8229 634.943 79.9297 635.169 80.1484 635.352C80.3724 635.529 80.6979 635.667 81.125 635.766C81.5521 635.859 82.0755 635.906 82.6953 635.906C83.3151 635.906 83.8333 635.859 84.25 635.766C84.6719 635.667 84.9896 635.529 85.2031 635.352C85.4219 635.169 85.5312 634.943 85.5312 634.672C85.5312 634.401 85.4219 634.177 85.2031 634C84.9896 633.823 84.6719 633.69 84.25 633.602C83.8333 633.513 83.3151 633.469 82.6953 633.469ZM87.3594 631.602H85.3672V623.203H87.3594V631.602ZM89.2812 628.187H86.7969V626.523H89.2812V628.187ZM78.4766 625.914H81.3906V624.117H83.3906V630.789H76.5V624.117H78.4766V625.914ZM81.3906 629.227V627.453H78.4766V629.227H81.3906Z" fill="#56555A"/> +<path d="M323.078 626.016V625.937H317.094V624.687H324.531V626L319.359 636H317.891L323.078 626.016ZM326.344 634.969L330.203 630.906C330.708 630.365 331.094 629.927 331.359 629.594C331.63 629.26 331.836 628.943 331.977 628.641C332.117 628.333 332.187 628.01 332.187 627.672C332.187 627.292 332.089 626.958 331.891 626.672C331.693 626.38 331.422 626.154 331.078 625.992C330.74 625.831 330.359 625.75 329.937 625.75C329.495 625.75 329.107 625.839 328.773 626.016C328.445 626.193 328.19 626.443 328.008 626.766C327.826 627.083 327.734 627.453 327.734 627.875H326.406C326.401 627.219 326.552 626.638 326.859 626.133C327.172 625.628 327.602 625.234 328.148 624.953C328.695 624.672 329.307 624.531 329.984 624.531C330.656 624.531 331.258 624.669 331.789 624.945C332.326 625.221 332.745 625.599 333.047 626.078C333.349 626.557 333.5 627.089 333.5 627.672C333.495 628.104 333.414 628.518 333.258 628.914C333.107 629.305 332.846 629.74 332.477 630.219C332.107 630.698 331.583 631.286 330.906 631.984L328.312 634.656V634.75H333.703V636H326.359L326.344 634.969ZM336.312 639.203H335.156L336.016 634.953H337.531L336.312 639.203ZM343.172 636.156C342.339 636.156 341.628 635.93 341.039 635.477C340.451 635.023 340 634.362 339.687 633.492C339.375 632.622 339.219 631.573 339.219 630.344C339.219 629.13 339.375 628.089 339.687 627.219C340 626.344 340.451 625.677 341.039 625.219C341.633 624.76 342.344 624.531 343.172 624.531C343.995 624.531 344.703 624.76 345.297 625.219C345.891 625.677 346.344 626.344 346.656 627.219C346.969 628.089 347.125 629.13 347.125 630.344C347.125 631.573 346.971 632.622 346.664 633.492C346.357 634.362 345.906 635.023 345.312 635.477C344.719 635.93 344.005 636.156 343.172 636.156ZM343.172 634.906C343.714 634.906 344.18 634.729 344.57 634.375C344.961 634.021 345.255 633.503 345.453 632.82C345.651 632.138 345.75 631.312 345.75 630.344C345.75 629.375 345.648 628.547 345.445 627.859C345.242 627.172 344.948 626.648 344.562 626.289C344.177 625.93 343.714 625.75 343.172 625.75C342.63 625.75 342.167 625.93 341.781 626.289C341.396 626.648 341.099 627.172 340.891 627.859C340.682 628.547 340.578 629.375 340.578 630.344C340.578 631.312 340.682 632.138 340.891 632.82C341.099 633.503 341.393 634.021 341.773 634.375C342.159 634.729 342.625 634.906 343.172 634.906ZM352.703 636.156C351.87 636.156 351.159 635.93 350.57 635.477C349.982 635.023 349.531 634.362 349.219 633.492C348.906 632.622 348.75 631.573 348.75 630.344C348.75 629.13 348.906 628.089 349.219 627.219C349.531 626.344 349.982 625.677 350.57 625.219C351.164 624.76 351.875 624.531 352.703 624.531C353.526 624.531 354.234 624.76 354.828 625.219C355.422 625.677 355.875 626.344 356.187 627.219C356.5 628.089 356.656 629.13 356.656 630.344C356.656 631.573 356.503 632.622 356.195 633.492C355.888 634.362 355.437 635.023 354.844 635.477C354.25 635.93 353.536 636.156 352.703 636.156ZM352.703 634.906C353.245 634.906 353.711 634.729 354.102 634.375C354.492 634.021 354.786 633.503 354.984 632.82C355.182 632.138 355.281 631.312 355.281 630.344C355.281 629.375 355.18 628.547 354.977 627.859C354.773 627.172 354.479 626.648 354.094 626.289C353.708 625.93 353.245 625.75 352.703 625.75C352.161 625.75 351.698 625.93 351.312 626.289C350.927 626.648 350.63 627.172 350.422 627.859C350.214 628.547 350.109 629.375 350.109 630.344C350.109 631.312 350.214 632.138 350.422 632.82C350.63 633.503 350.924 634.021 351.305 634.375C351.69 634.729 352.156 634.906 352.703 634.906ZM362.234 636.156C361.401 636.156 360.69 635.93 360.102 635.477C359.513 635.023 359.062 634.362 358.75 633.492C358.437 632.622 358.281 631.573 358.281 630.344C358.281 629.13 358.437 628.089 358.75 627.219C359.062 626.344 359.513 625.677 360.102 625.219C360.695 624.76 361.406 624.531 362.234 624.531C363.057 624.531 363.766 624.76 364.359 625.219C364.953 625.677 365.406 626.344 365.719 627.219C366.031 628.089 366.187 629.13 366.187 630.344C366.187 631.573 366.034 632.622 365.727 633.492C365.419 634.362 364.969 635.023 364.375 635.477C363.781 635.93 363.068 636.156 362.234 636.156ZM362.234 634.906C362.776 634.906 363.242 634.729 363.633 634.375C364.023 634.021 364.318 633.503 364.516 632.82C364.714 632.138 364.812 631.312 364.812 630.344C364.812 629.375 364.711 628.547 364.508 627.859C364.305 627.172 364.01 626.648 363.625 626.289C363.24 625.93 362.776 625.75 362.234 625.75C361.693 625.75 361.229 625.93 360.844 626.289C360.458 626.648 360.161 627.172 359.953 627.859C359.745 628.547 359.641 629.375 359.641 630.344C359.641 631.312 359.745 632.138 359.953 632.82C360.161 633.503 360.456 634.021 360.836 634.375C361.221 634.729 361.687 634.906 362.234 634.906Z" fill="#56555A"/> +<path d="M375.348 635.09H374.422V632.77H375.348V635.09ZM380.012 635.453H379.086V627.543H380.012V635.453ZM380.27 637.727H372.863V636.953H380.27V637.727ZM373.789 637.176H372.863V634.68H373.789V637.176ZM371.363 632.371C372.758 632.363 373.992 632.342 375.066 632.307C376.141 632.268 377.168 632.187 378.148 632.066L378.207 632.734C377.195 632.895 376.135 633 375.025 633.051C373.916 633.102 372.738 633.125 371.492 633.121L371.363 632.371ZM379.332 634.375H376.93V633.707H379.332V634.375ZM374.785 627.965C375.289 627.965 375.736 628.039 376.127 628.187C376.521 628.336 376.826 628.549 377.041 628.826C377.256 629.104 377.363 629.422 377.363 629.781C377.363 630.148 377.256 630.467 377.041 630.736C376.826 631.006 376.523 631.215 376.133 631.363C375.742 631.512 375.293 631.586 374.785 631.586C374.273 631.586 373.822 631.512 373.432 631.363C373.045 631.215 372.744 631.006 372.529 630.736C372.314 630.467 372.207 630.148 372.207 629.781C372.207 629.422 372.314 629.104 372.529 628.826C372.744 628.549 373.047 628.336 373.437 628.187C373.828 628.039 374.277 627.965 374.785 627.965ZM374.785 628.668C374.449 628.664 374.152 628.709 373.895 628.803C373.637 628.893 373.436 629.023 373.291 629.195C373.15 629.367 373.082 629.562 373.086 629.781C373.082 630.004 373.15 630.201 373.291 630.373C373.436 630.541 373.637 630.672 373.895 630.766C374.152 630.859 374.449 630.906 374.785 630.906C375.113 630.906 375.406 630.859 375.664 630.766C375.922 630.672 376.123 630.541 376.268 630.373C376.412 630.201 376.484 630.004 376.484 629.781C376.484 629.562 376.412 629.367 376.268 629.195C376.123 629.023 375.922 628.893 375.664 628.803C375.406 628.709 375.113 628.664 374.785 628.668Z" fill="#56555A"/> +<path d="M382 658H48C43.5817 658 40 661.582 40 666V690C40 694.418 43.5817 698 48 698H382C386.418 698 390 694.418 390 690V666C390 661.582 386.418 658 382 658Z" fill="#F9F8FD"/> +<path d="M56.5312 674.133H48.6016V672.531H56.5312V674.133ZM48.2422 680.539C49.9349 680.539 51.4948 680.516 52.9219 680.469C54.3542 680.422 55.7005 680.32 56.9609 680.164L57.0547 681.586C55.763 681.815 54.4167 681.969 53.0156 682.047C51.6198 682.12 50.1016 682.161 48.4609 682.172L48.2422 680.539ZM51.7812 680.984H49.8516V673.789H51.7812V680.984ZM55.2578 680.984H53.3437V673.789H55.2578V680.984ZM59.6406 685.437H57.6406V671.203H59.6406V685.437ZM61.75 678.258H59.2031V676.633H61.75V678.258ZM73.2969 676.523H69.9219V674.906H73.2969V676.523ZM74.2344 681.617H72.25V671.234H74.2344V681.617ZM74.5781 685.195H64.7969V683.586H74.5781V685.195ZM66.7969 684.523H64.7969V680.703H66.7969V684.523ZM67.2109 673.992C67.2109 674.914 67.0625 675.776 66.7656 676.578C66.474 677.375 66.026 678.076 65.4219 678.68C64.8229 679.284 64.0833 679.732 63.2031 680.023L62.1719 678.414C62.9271 678.174 63.5599 677.828 64.0703 677.375C64.5807 676.917 64.9583 676.398 65.2031 675.82C65.4531 675.237 65.5807 674.628 65.5859 673.992V673.07H67.2109V673.992ZM67.6172 674.008C67.6172 674.586 67.737 675.146 67.9766 675.687C68.2214 676.224 68.5859 676.711 69.0703 677.148C69.5599 677.586 70.1667 677.922 70.8906 678.156L69.9062 679.734C69.0469 679.453 68.3229 679.023 67.7344 678.445C67.151 677.867 66.7135 677.201 66.4219 676.445C66.1354 675.685 65.9948 674.872 66 674.008V673.07H67.6172V674.008ZM70.4531 673.789H62.7344V672.187H70.4531V673.789ZM87.0312 678.852H80.2031V672.234H87.0312V678.852ZM82.1797 677.273H85.0703V673.805H82.1797V677.273ZM91.0625 679.648H89.0703V671.203H91.0625V679.648ZM92.9844 676.242H90.5V674.625H92.9844V676.242ZM91.0625 685.453H89.0703V681.859H81.4922V680.281H91.0625V685.453ZM105.594 678.344H103.609V671.203H105.594V678.344ZM103.844 675.859H101.039V674.25H103.844V675.859ZM100.883 671.734C100.883 672.969 100.641 674.047 100.156 674.969C99.6719 675.891 98.9531 676.664 98 677.289C97.0469 677.914 95.8672 678.393 94.4609 678.727L93.7891 677.133C94.9193 676.883 95.8542 676.544 96.5937 676.117C97.3385 675.685 97.888 675.187 98.2422 674.625C98.5964 674.057 98.7734 673.435 98.7734 672.758V671.734H100.883ZM100.43 673.336H94.5781V671.734H100.43V673.336ZM105.594 682.781H98.1562V684.578H96.1641V681.305H103.586V680.453H96.1406V678.891H105.594V682.781ZM105.906 685.297H96.1641V683.719H105.906V685.297ZM119.359 685.477H117.367V671.203H119.359V685.477ZM109.477 680.5C110.815 680.51 112.016 680.482 113.078 680.414C114.146 680.341 115.237 680.214 116.352 680.031L116.531 681.641C115.432 681.833 114.336 681.966 113.242 682.039C112.154 682.107 110.898 682.141 109.477 682.141H108.203V680.5H109.477ZM114.945 677.883H110.258V681.125H108.203V676.32H112.914V674.016H108.187V672.406H114.945V677.883Z" fill="#56555A"/> +<path d="M316.156 684H314.734V674.156H314.672L311.922 675.984V674.562L314.734 672.687H316.156V684ZM323.172 684H321.75V674.156H321.687L318.937 675.984V674.562L321.75 672.687H323.172V684ZM329.969 684.156C329.187 684.156 328.492 684.021 327.883 683.75C327.273 683.479 326.799 683.104 326.461 682.625C326.122 682.146 325.953 681.604 325.953 681C325.953 680.521 326.055 680.073 326.258 679.656C326.461 679.24 326.737 678.898 327.086 678.633C327.435 678.362 327.823 678.193 328.25 678.125V678.062C327.88 677.979 327.555 677.815 327.273 677.57C326.997 677.326 326.781 677.026 326.625 676.672C326.469 676.318 326.391 675.937 326.391 675.531C326.391 674.964 326.544 674.453 326.852 674C327.159 673.542 327.583 673.182 328.125 672.922C328.672 672.661 329.286 672.531 329.969 672.531C330.646 672.531 331.258 672.661 331.805 672.922C332.352 673.182 332.779 673.542 333.086 674C333.398 674.453 333.557 674.964 333.562 675.531C333.557 675.937 333.474 676.318 333.312 676.672C333.156 677.026 332.937 677.326 332.656 677.57C332.375 677.815 332.052 677.979 331.687 678.062V678.125C332.109 678.193 332.495 678.362 332.844 678.633C333.198 678.898 333.477 679.24 333.68 679.656C333.888 680.073 333.995 680.521 334 681C333.995 681.604 333.82 682.146 333.477 682.625C333.138 683.104 332.661 683.479 332.047 683.75C331.437 684.021 330.745 684.156 329.969 684.156ZM329.969 682.922C330.5 682.922 330.964 682.836 331.359 682.664C331.755 682.492 332.06 682.258 332.273 681.961C332.487 681.664 332.594 681.318 332.594 680.922C332.594 680.51 332.482 680.141 332.258 679.812C332.034 679.479 331.721 679.219 331.32 679.031C330.919 678.844 330.469 678.75 329.969 678.75C329.469 678.75 329.021 678.844 328.625 679.031C328.229 679.219 327.917 679.479 327.687 679.812C327.464 680.141 327.354 680.51 327.359 680.922C327.354 681.318 327.456 681.664 327.664 681.961C327.878 682.258 328.18 682.492 328.57 682.664C328.966 682.836 329.432 682.922 329.969 682.922ZM329.969 677.562C330.396 677.562 330.779 677.479 331.117 677.312C331.456 677.146 331.719 676.919 331.906 676.633C332.094 676.346 332.187 676.016 332.187 675.641C332.187 675.266 332.096 674.935 331.914 674.648C331.732 674.362 331.471 674.141 331.133 673.984C330.794 673.828 330.406 673.75 329.969 673.75C329.526 673.75 329.138 673.828 328.805 673.984C328.477 674.141 328.219 674.362 328.031 674.648C327.844 674.935 327.75 675.266 327.75 675.641C327.75 676.016 327.846 676.346 328.039 676.633C328.232 676.919 328.495 677.146 328.828 677.312C329.161 677.479 329.542 677.562 329.969 677.562ZM336.094 687.203H334.937L335.797 682.953H337.312L336.094 687.203ZM343.078 684.156C342.297 684.156 341.602 684.021 340.992 683.75C340.383 683.479 339.909 683.104 339.57 682.625C339.232 682.146 339.062 681.604 339.062 681C339.062 680.521 339.164 680.073 339.367 679.656C339.57 679.24 339.846 678.898 340.195 678.633C340.544 678.362 340.932 678.193 341.359 678.125V678.062C340.99 677.979 340.664 677.815 340.383 677.57C340.107 677.326 339.891 677.026 339.734 676.672C339.578 676.318 339.5 675.937 339.5 675.531C339.5 674.964 339.654 674.453 339.961 674C340.268 673.542 340.693 673.182 341.234 672.922C341.781 672.661 342.396 672.531 343.078 672.531C343.755 672.531 344.367 672.661 344.914 672.922C345.461 673.182 345.888 673.542 346.195 674C346.508 674.453 346.667 674.964 346.672 675.531C346.667 675.937 346.583 676.318 346.422 676.672C346.266 677.026 346.047 677.326 345.766 677.57C345.484 677.815 345.161 677.979 344.797 678.062V678.125C345.219 678.193 345.604 678.362 345.953 678.633C346.307 678.898 346.586 679.24 346.789 679.656C346.997 680.073 347.104 680.521 347.109 681C347.104 681.604 346.93 682.146 346.586 682.625C346.247 683.104 345.771 683.479 345.156 683.75C344.547 684.021 343.854 684.156 343.078 684.156ZM343.078 682.922C343.609 682.922 344.073 682.836 344.469 682.664C344.865 682.492 345.169 682.258 345.383 681.961C345.596 681.664 345.703 681.318 345.703 680.922C345.703 680.51 345.591 680.141 345.367 679.812C345.143 679.479 344.831 679.219 344.43 679.031C344.029 678.844 343.578 678.75 343.078 678.75C342.578 678.75 342.13 678.844 341.734 679.031C341.339 679.219 341.026 679.479 340.797 679.812C340.573 680.141 340.464 680.51 340.469 680.922C340.464 681.318 340.565 681.664 340.773 681.961C340.987 682.258 341.289 682.492 341.68 682.664C342.076 682.836 342.542 682.922 343.078 682.922ZM343.078 677.562C343.505 677.562 343.888 677.479 344.227 677.312C344.565 677.146 344.828 676.919 345.016 676.633C345.203 676.346 345.297 676.016 345.297 675.641C345.297 675.266 345.206 674.935 345.023 674.648C344.841 674.362 344.581 674.141 344.242 673.984C343.904 673.828 343.516 673.75 343.078 673.75C342.635 673.75 342.247 673.828 341.914 673.984C341.586 674.141 341.328 674.362 341.141 674.648C340.953 674.935 340.859 675.266 340.859 675.641C340.859 676.016 340.956 676.346 341.148 676.633C341.341 676.919 341.604 677.146 341.937 677.312C342.271 677.479 342.651 677.562 343.078 677.562ZM352.703 684.156C351.87 684.156 351.159 683.93 350.57 683.477C349.982 683.023 349.531 682.362 349.219 681.492C348.906 680.622 348.75 679.573 348.75 678.344C348.75 677.13 348.906 676.089 349.219 675.219C349.531 674.344 349.982 673.677 350.57 673.219C351.164 672.76 351.875 672.531 352.703 672.531C353.526 672.531 354.234 672.76 354.828 673.219C355.422 673.677 355.875 674.344 356.187 675.219C356.5 676.089 356.656 677.13 356.656 678.344C356.656 679.573 356.503 680.622 356.195 681.492C355.888 682.362 355.437 683.023 354.844 683.477C354.25 683.93 353.536 684.156 352.703 684.156ZM352.703 682.906C353.245 682.906 353.711 682.729 354.102 682.375C354.492 682.021 354.786 681.503 354.984 680.82C355.182 680.138 355.281 679.312 355.281 678.344C355.281 677.375 355.18 676.547 354.977 675.859C354.773 675.172 354.479 674.648 354.094 674.289C353.708 673.93 353.245 673.75 352.703 673.75C352.161 673.75 351.698 673.93 351.312 674.289C350.927 674.648 350.63 675.172 350.422 675.859C350.214 676.547 350.109 677.375 350.109 678.344C350.109 679.312 350.214 680.138 350.422 680.82C350.63 681.503 350.924 682.021 351.305 682.375C351.69 682.729 352.156 682.906 352.703 682.906ZM362.234 684.156C361.401 684.156 360.69 683.93 360.102 683.477C359.513 683.023 359.062 682.362 358.75 681.492C358.437 680.622 358.281 679.573 358.281 678.344C358.281 677.13 358.437 676.089 358.75 675.219C359.062 674.344 359.513 673.677 360.102 673.219C360.695 672.76 361.406 672.531 362.234 672.531C363.057 672.531 363.766 672.76 364.359 673.219C364.953 673.677 365.406 674.344 365.719 675.219C366.031 676.089 366.187 677.13 366.187 678.344C366.187 679.573 366.034 680.622 365.727 681.492C365.419 682.362 364.969 683.023 364.375 683.477C363.781 683.93 363.068 684.156 362.234 684.156ZM362.234 682.906C362.776 682.906 363.242 682.729 363.633 682.375C364.023 682.021 364.318 681.503 364.516 680.82C364.714 680.138 364.812 679.312 364.812 678.344C364.812 677.375 364.711 676.547 364.508 675.859C364.305 675.172 364.01 674.648 363.625 674.289C363.24 673.93 362.776 673.75 362.234 673.75C361.693 673.75 361.229 673.93 360.844 674.289C360.458 674.648 360.161 675.172 359.953 675.859C359.745 676.547 359.641 677.375 359.641 678.344C359.641 679.312 359.745 680.138 359.953 680.82C360.161 681.503 360.456 682.021 360.836 682.375C361.221 682.729 361.687 682.906 362.234 682.906Z" fill="#56555A"/> +<path d="M375.348 683.09H374.422V680.77H375.348V683.09ZM380.012 683.453H379.086V675.543H380.012V683.453ZM380.27 685.727H372.863V684.953H380.27V685.727ZM373.789 685.176H372.863V682.68H373.789V685.176ZM371.363 680.371C372.758 680.363 373.992 680.342 375.066 680.307C376.141 680.268 377.168 680.187 378.148 680.066L378.207 680.734C377.195 680.895 376.135 681 375.025 681.051C373.916 681.102 372.738 681.125 371.492 681.121L371.363 680.371ZM379.332 682.375H376.93V681.707H379.332V682.375ZM374.785 675.965C375.289 675.965 375.736 676.039 376.127 676.187C376.521 676.336 376.826 676.549 377.041 676.826C377.256 677.104 377.363 677.422 377.363 677.781C377.363 678.148 377.256 678.467 377.041 678.736C376.826 679.006 376.523 679.215 376.133 679.363C375.742 679.512 375.293 679.586 374.785 679.586C374.273 679.586 373.822 679.512 373.432 679.363C373.045 679.215 372.744 679.006 372.529 678.736C372.314 678.467 372.207 678.148 372.207 677.781C372.207 677.422 372.314 677.104 372.529 676.826C372.744 676.549 373.047 676.336 373.437 676.187C373.828 676.039 374.277 675.965 374.785 675.965ZM374.785 676.668C374.449 676.664 374.152 676.709 373.895 676.803C373.637 676.893 373.436 677.023 373.291 677.195C373.15 677.367 373.082 677.562 373.086 677.781C373.082 678.004 373.15 678.201 373.291 678.373C373.436 678.541 373.637 678.672 373.895 678.766C374.152 678.859 374.449 678.906 374.785 678.906C375.113 678.906 375.406 678.859 375.664 678.766C375.922 678.672 376.123 678.541 376.268 678.373C376.412 678.201 376.484 678.004 376.484 677.781C376.484 677.562 376.412 677.367 376.268 677.195C376.123 677.023 375.922 676.893 375.664 676.803C375.406 676.709 375.113 676.664 374.785 676.668Z" fill="#56555A"/> +<path d="M58.0488 715.953H48.3223V714.764H58.0488V715.953ZM53.9062 715.314H52.4238V713.732H53.9062V715.314ZM53.9062 711.014H52.4238V709.443H53.9062V711.014ZM53.6426 711.277C53.6426 711.82 53.4687 712.303 53.1211 712.725C52.7773 713.143 52.2715 713.482 51.6035 713.744C50.9355 714.006 50.127 714.17 49.1777 714.236L48.7207 713.111C49.5371 713.057 50.2168 712.939 50.7598 712.76C51.3027 712.576 51.6992 712.357 51.9492 712.104C52.2031 711.85 52.3301 711.574 52.3301 711.277V711.066H53.6426V711.277ZM54.0059 711.277C54.002 711.57 54.127 711.846 54.3809 712.104C54.6348 712.357 55.0312 712.576 55.5703 712.76C56.1133 712.939 56.793 713.057 57.6094 713.111L57.1582 714.236C56.209 714.17 55.4004 714.006 54.7324 713.744C54.0645 713.482 53.5566 713.143 53.209 712.725C52.8613 712.303 52.6895 711.82 52.6934 711.277V711.066H54.0059V711.277ZM57.1055 711.547H49.2539V710.363H57.1055V711.547ZM53.168 716.451C53.9453 716.451 54.6113 716.521 55.166 716.662C55.7207 716.803 56.1445 717.008 56.4375 717.277C56.7305 717.547 56.8789 717.875 56.8828 718.262C56.8789 718.652 56.7305 718.982 56.4375 719.252C56.1445 719.525 55.7207 719.73 55.166 719.867C54.6113 720.008 53.9453 720.078 53.168 720.078C52.3828 720.078 51.7109 720.008 51.1523 719.867C50.5977 719.73 50.1719 719.525 49.875 719.252C49.5781 718.982 49.4297 718.652 49.4297 718.262C49.4297 717.875 49.5781 717.547 49.875 717.277C50.1719 717.008 50.5977 716.803 51.1523 716.662C51.7109 716.521 52.3828 716.451 53.168 716.451ZM53.168 717.559C52.6641 717.555 52.248 717.58 51.9199 717.635C51.5957 717.686 51.3516 717.764 51.1875 717.869C51.0273 717.971 50.9492 718.102 50.9531 718.262C50.9492 718.426 51.0273 718.561 51.1875 718.666C51.3516 718.768 51.5957 718.844 51.9199 718.895C52.248 718.945 52.6641 718.971 53.168 718.971C53.6602 718.971 54.0684 718.945 54.3926 718.895C54.7207 718.844 54.9668 718.768 55.1309 718.666C55.2949 718.561 55.377 718.426 55.377 718.262C55.377 718.102 55.2949 717.971 55.1309 717.869C54.9668 717.764 54.7207 717.686 54.3926 717.635C54.0684 717.58 53.6602 717.555 53.168 717.559ZM61.1836 710.053C61.6523 710.053 62.0742 710.164 62.4492 710.387C62.8242 710.605 63.1172 710.914 63.3281 711.312C63.543 711.707 63.6504 712.156 63.6504 712.66C63.6504 713.168 63.543 713.617 63.3281 714.008C63.1172 714.398 62.8242 714.703 62.4492 714.922C62.0742 715.141 61.6523 715.25 61.1836 715.25C60.7148 715.25 60.2949 715.141 59.9238 714.922C59.5527 714.703 59.2617 714.398 59.0508 714.008C58.8437 713.617 58.7402 713.168 58.7402 712.66C58.7402 712.16 58.8437 711.711 59.0508 711.312C59.2617 710.914 59.5527 710.605 59.9238 710.387C60.2949 710.164 60.7148 710.053 61.1836 710.053ZM61.1836 711.33C60.9648 711.33 60.7715 711.383 60.6035 711.488C60.4355 711.59 60.3047 711.742 60.2109 711.945C60.1172 712.145 60.0723 712.383 60.0762 712.66C60.0723 712.937 60.1172 713.178 60.2109 713.381C60.3047 713.58 60.4355 713.734 60.6035 713.844C60.7715 713.953 60.9648 714.008 61.1836 714.008C61.3984 714.008 61.5898 713.953 61.7578 713.844C61.9297 713.734 62.0605 713.58 62.1504 713.381C62.2441 713.178 62.291 712.937 62.291 712.66C62.291 712.383 62.2441 712.145 62.1504 711.945C62.0605 711.742 61.9316 711.59 61.7637 711.488C61.5957 711.383 61.4023 711.33 61.1836 711.33ZM67.8516 715.795H66.4277V709.426H67.8516V715.795ZM66.832 713.205H65.1035V712.01H66.832V713.205ZM65.5605 715.736H64.166V709.607H65.5605V715.736ZM67.8516 720.078H66.3691V717.453H60.4805V716.264H67.8516V720.078Z" fill="#56555A"/> +<path d="M341.797 719H340.73V711.617H340.684L338.621 712.988V711.922L340.73 710.516H341.797V719ZM346.883 710.398C347.422 710.406 347.924 710.535 348.389 710.785C348.854 711.035 349.232 711.459 349.525 712.057C349.818 712.65 349.965 713.438 349.965 714.419C349.965 715.411 349.836 716.258 349.578 716.961C349.32 717.664 348.949 718.199 348.465 718.566C347.98 718.934 347.406 719.117 346.742 719.117C346.25 719.117 345.809 719.021 345.418 718.83C345.027 718.639 344.709 718.375 344.463 718.039C344.217 717.699 344.059 717.305 343.988 716.855H345.031C345.094 717.117 345.201 717.348 345.354 717.547C345.506 717.742 345.699 717.896 345.934 718.01C346.168 718.123 346.437 718.18 346.742 718.18C347.203 718.18 347.602 718.052 347.937 717.794C348.273 717.536 348.529 717.164 348.705 716.68C348.885 716.191 348.977 715.605 348.98 714.922H348.863C348.699 715.156 348.506 715.358 348.283 715.526C348.061 715.694 347.814 715.822 347.545 715.912C347.275 716.002 346.992 716.047 346.695 716.047C346.191 716.047 345.727 715.927 345.301 715.685C344.879 715.442 344.543 715.107 344.293 714.682C344.043 714.256 343.918 713.777 343.918 713.246C343.918 712.719 344.041 712.238 344.287 711.805C344.533 711.367 344.881 711.023 345.33 710.773C345.779 710.52 346.297 710.395 346.883 710.398ZM346.883 711.324C346.52 711.324 346.189 711.41 345.893 711.582C345.6 711.754 345.367 711.986 345.195 712.279C345.027 712.572 344.945 712.891 344.949 713.234C344.949 713.582 345.031 713.901 345.195 714.19C345.359 714.476 345.584 714.701 345.869 714.869C346.158 715.037 346.484 715.121 346.848 715.121C347.207 715.121 347.537 715.031 347.838 714.852C348.139 714.672 348.377 714.436 348.553 714.143C348.729 713.85 348.816 713.539 348.816 713.211C348.816 712.887 348.732 712.58 348.564 712.291C348.396 711.998 348.164 711.764 347.867 711.588C347.574 711.412 347.246 711.324 346.883 711.324ZM354.195 719.117C353.57 719.117 353.037 718.947 352.596 718.607C352.154 718.268 351.816 717.771 351.582 717.119C351.348 716.467 351.23 715.68 351.23 714.758C351.23 713.848 351.348 713.066 351.582 712.414C351.816 711.758 352.154 711.258 352.596 710.914C353.041 710.57 353.574 710.398 354.195 710.398C354.812 710.398 355.344 710.57 355.789 710.914C356.234 711.258 356.574 711.758 356.809 712.414C357.043 713.066 357.16 713.848 357.16 714.758C357.16 715.68 357.045 716.467 356.814 717.119C356.584 717.771 356.246 718.268 355.801 718.607C355.355 718.947 354.82 719.117 354.195 719.117ZM354.195 718.18C354.602 718.18 354.951 718.047 355.244 717.781C355.537 717.516 355.758 717.127 355.906 716.615C356.055 716.104 356.129 715.484 356.129 714.758C356.129 714.031 356.053 713.41 355.9 712.895C355.748 712.379 355.527 711.986 355.238 711.717C354.949 711.447 354.602 711.312 354.195 711.312C353.789 711.312 353.441 711.447 353.152 711.717C352.863 711.986 352.641 712.379 352.484 712.895C352.328 713.41 352.25 714.031 352.25 714.758C352.25 715.484 352.328 716.104 352.484 716.615C352.641 717.127 352.861 717.516 353.146 717.781C353.436 718.047 353.785 718.18 354.195 718.18ZM358.684 721.402H357.816L358.461 718.216H359.598L358.684 721.402ZM363.922 719.117C363.336 719.117 362.814 719.016 362.357 718.812C361.9 718.609 361.545 718.328 361.291 717.969C361.037 717.609 360.91 717.203 360.91 716.75C360.91 716.391 360.986 716.055 361.139 715.742C361.291 715.43 361.498 715.174 361.76 714.975C362.021 714.771 362.312 714.645 362.633 714.594V714.547C362.355 714.484 362.111 714.361 361.9 714.178C361.693 713.994 361.531 713.771 361.414 713.505C361.297 713.239 361.238 712.953 361.238 712.648C361.238 712.223 361.354 711.84 361.584 711.5C361.814 711.156 362.133 710.887 362.539 710.691C362.949 710.496 363.41 710.398 363.922 710.398C364.43 710.398 364.889 710.496 365.299 710.691C365.709 710.887 366.029 711.156 366.26 711.5C366.494 711.84 366.613 712.223 366.617 712.648C366.613 712.953 366.551 713.239 366.43 713.505C366.312 713.771 366.148 713.994 365.937 714.178C365.727 714.361 365.484 714.484 365.211 714.547V714.594C365.527 714.645 365.816 714.771 366.078 714.975C366.344 715.174 366.553 715.43 366.705 715.742C366.861 716.055 366.941 716.391 366.945 716.75C366.941 717.203 366.811 717.609 366.553 717.969C366.299 718.328 365.941 718.609 365.48 718.812C365.023 719.016 364.504 719.117 363.922 719.117ZM363.922 718.191C364.32 718.191 364.668 718.127 364.965 717.998C365.262 717.869 365.49 717.693 365.65 717.471C365.811 717.248 365.891 716.988 365.891 716.691C365.891 716.383 365.807 716.105 365.639 715.859C365.471 715.609 365.236 715.414 364.936 715.273C364.635 715.133 364.297 715.062 363.922 715.062C363.547 715.062 363.211 715.133 362.914 715.273C362.617 715.414 362.383 715.609 362.211 715.859C362.043 716.105 361.961 716.383 361.965 716.691C361.961 716.988 362.037 717.248 362.193 717.471C362.354 717.693 362.58 717.869 362.873 717.998C363.17 718.127 363.52 718.191 363.922 718.191ZM363.922 714.172C364.242 714.172 364.529 714.109 364.783 713.984C365.037 713.859 365.234 713.689 365.375 713.475C365.516 713.26 365.586 713.012 365.586 712.73C365.586 712.449 365.518 712.202 365.381 711.987C365.244 711.772 365.049 711.605 364.795 711.488C364.541 711.371 364.25 711.312 363.922 711.312C363.59 711.312 363.299 711.371 363.049 711.488C362.803 711.605 362.609 711.772 362.469 711.987C362.328 712.202 362.258 712.449 362.258 712.73C362.258 713.012 362.33 713.26 362.475 713.475C362.619 713.689 362.816 713.859 363.066 713.984C363.316 714.109 363.602 714.172 363.922 714.172ZM371.141 719.117C370.516 719.117 369.982 718.947 369.541 718.607C369.1 718.268 368.762 717.771 368.527 717.119C368.293 716.467 368.176 715.68 368.176 714.758C368.176 713.848 368.293 713.066 368.527 712.414C368.762 711.758 369.1 711.258 369.541 710.914C369.986 710.57 370.52 710.398 371.141 710.398C371.758 710.398 372.289 710.57 372.734 710.914C373.18 711.258 373.52 711.758 373.754 712.414C373.988 713.066 374.105 713.848 374.105 714.758C374.105 715.68 373.99 716.467 373.76 717.119C373.529 717.771 373.191 718.268 372.746 718.607C372.301 718.947 371.766 719.117 371.141 719.117ZM371.141 718.18C371.547 718.18 371.896 718.047 372.189 717.781C372.482 717.516 372.703 717.127 372.852 716.615C373 716.104 373.074 715.484 373.074 714.758C373.074 714.031 372.998 713.41 372.846 712.895C372.693 712.379 372.473 711.986 372.184 711.717C371.895 711.447 371.547 711.312 371.141 711.312C370.734 711.312 370.387 711.447 370.098 711.717C369.809 711.986 369.586 712.379 369.43 712.895C369.273 713.41 369.195 714.031 369.195 714.758C369.195 715.484 369.273 716.104 369.43 716.615C369.586 717.127 369.807 717.516 370.092 717.781C370.381 718.047 370.73 718.18 371.141 718.18ZM378.289 719.117C377.664 719.117 377.131 718.947 376.689 718.607C376.248 718.268 375.91 717.771 375.676 717.119C375.441 716.467 375.324 715.68 375.324 714.758C375.324 713.848 375.441 713.066 375.676 712.414C375.91 711.758 376.248 711.258 376.689 710.914C377.135 710.57 377.668 710.398 378.289 710.398C378.906 710.398 379.437 710.57 379.883 710.914C380.328 711.258 380.668 711.758 380.902 712.414C381.137 713.066 381.254 713.848 381.254 714.758C381.254 715.68 381.139 716.467 380.908 717.119C380.678 717.771 380.34 718.268 379.895 718.607C379.449 718.947 378.914 719.117 378.289 719.117ZM378.289 718.18C378.695 718.18 379.045 718.047 379.338 717.781C379.631 717.516 379.852 717.127 380 716.615C380.148 716.104 380.223 715.484 380.223 714.758C380.223 714.031 380.146 713.41 379.994 712.895C379.842 712.379 379.621 711.986 379.332 711.717C379.043 711.447 378.695 711.312 378.289 711.312C377.883 711.312 377.535 711.447 377.246 711.717C376.957 711.986 376.734 712.379 376.578 712.895C376.422 713.41 376.344 714.031 376.344 714.758C376.344 715.484 376.422 716.104 376.578 716.615C376.734 717.127 376.955 717.516 377.24 717.781C377.529 718.047 377.879 718.18 378.289 718.18Z" fill="#B2B1B6"/> +<path d="M199 748H44C37.3726 748 32 753.373 32 760V776C32 782.627 37.3726 788 44 788H199C205.627 788 211 782.627 211 776V760C211 753.373 205.627 748 199 748Z" fill="#E7E6EB"/> +<path d="M88.6328 771.453H86.6406V761.234H88.6328V771.453ZM89.0234 775.195H79.1094V773.586H89.0234V775.195ZM81.125 774.242H79.1094V770.43H81.125V774.242ZM80.8437 762.133C81.5625 762.133 82.2187 762.286 82.8125 762.594C83.4115 762.901 83.8802 763.328 84.2187 763.875C84.5625 764.422 84.7344 765.034 84.7344 765.711C84.7344 766.404 84.5625 767.026 84.2187 767.578C83.8802 768.125 83.4141 768.555 82.8203 768.867C82.2266 769.174 81.5677 769.328 80.8437 769.328C80.1198 769.328 79.4609 769.174 78.8672 768.867C78.2786 768.555 77.8125 768.125 77.4687 767.578C77.125 767.026 76.9531 766.404 76.9531 765.711C76.9531 765.034 77.125 764.422 77.4687 763.875C77.8125 763.328 78.2786 762.901 78.8672 762.594C79.4609 762.286 80.1198 762.133 80.8437 762.133ZM80.8437 763.867C80.474 763.867 80.1406 763.943 79.8437 764.094C79.5521 764.24 79.3203 764.453 79.1484 764.734C78.9818 765.01 78.8984 765.336 78.8984 765.711C78.8984 766.102 78.9818 766.437 79.1484 766.719C79.3203 767 79.5521 767.216 79.8437 767.367C80.1406 767.518 80.474 767.591 80.8437 767.586C81.2083 767.591 81.5339 767.518 81.8203 767.367C82.112 767.216 82.3411 767 82.5078 766.719C82.6745 766.437 82.7578 766.102 82.7578 765.711C82.7578 765.336 82.6745 765.01 82.5078 764.734C82.3411 764.453 82.112 764.24 81.8203 764.094C81.5286 763.943 81.2031 763.867 80.8437 763.867ZM96.3203 771.633H94.3125V768.492H96.3203V771.633ZM102.609 771.977H100.609V761.234H102.609V771.977ZM102.922 775.195H92.3125V773.586H102.922V775.195ZM94.3203 774.016H92.3125V770.945H94.3203V774.016ZM90.5078 767.539C92.4036 767.523 94.0703 767.49 95.5078 767.437C96.9453 767.38 98.3255 767.268 99.6484 767.102L99.75 768.531C98.375 768.76 96.9349 768.917 95.4297 769C93.9297 769.078 92.3672 769.115 90.7422 769.109L90.5078 767.539ZM101.063 770.844H97.8906V769.484H101.063V770.844ZM95.1328 761.711C95.8151 761.711 96.4271 761.818 96.9687 762.031C97.5104 762.245 97.9323 762.547 98.2344 762.937C98.5365 763.323 98.6875 763.763 98.6875 764.258C98.6875 764.763 98.5365 765.203 98.2344 765.578C97.9323 765.953 97.5104 766.247 96.9687 766.461C96.4323 766.669 95.8203 766.773 95.1328 766.773C94.4349 766.773 93.8151 766.669 93.2734 766.461C92.737 766.247 92.3177 765.953 92.0156 765.578C91.7135 765.203 91.5625 764.763 91.5625 764.258C91.5625 763.763 91.7135 763.32 92.0156 762.93C92.3177 762.539 92.7396 762.24 93.2812 762.031C93.8229 761.818 94.4401 761.711 95.1328 761.711ZM95.1328 763.172C94.7943 763.172 94.5 763.214 94.25 763.297C94 763.38 93.8021 763.505 93.6562 763.672C93.5156 763.833 93.4479 764.029 93.4531 764.258C93.4479 764.487 93.5156 764.682 93.6562 764.844C93.8021 765.005 94 765.128 94.25 765.211C94.5 765.294 94.7943 765.336 95.1328 765.336C95.4609 765.336 95.7474 765.294 95.9922 765.211C96.2422 765.128 96.4375 765.005 96.5781 764.844C96.7187 764.682 96.7891 764.487 96.7891 764.258C96.7891 764.034 96.7187 763.839 96.5781 763.672C96.4375 763.505 96.2422 763.38 95.9922 763.297C95.7474 763.214 95.4609 763.172 95.1328 763.172ZM118.789 765.219H115.125V763.602H118.789V765.219ZM118.859 768.25H115.125V766.648H118.859V768.25ZM120.078 771.719H118.094V761.234H120.078V771.719ZM120.383 775.195H110.609V773.586H120.383V775.195ZM112.625 774.5H110.609V770.672H112.625V774.5ZM110.703 764.336H113.5V762.164H115.477V769.477H108.695V762.164H110.703V764.336ZM113.5 767.898V765.859H110.703V767.898H113.5ZM134.922 769.508H121.93V767.93H134.922V769.508ZM129.398 768.555H127.445V765.789H129.398V768.555ZM133.437 766.711H123.5V765.148H133.437V766.711ZM133.359 763.398H125.477V766.172H123.5V761.844H133.359V763.398ZM128.391 770.211C129.417 770.211 130.299 770.315 131.039 770.523C131.779 770.727 132.346 771.026 132.742 771.422C133.138 771.812 133.339 772.286 133.344 772.844C133.339 773.396 133.138 773.865 132.742 774.25C132.352 774.641 131.784 774.937 131.039 775.141C130.299 775.349 129.417 775.456 128.391 775.461C127.354 775.456 126.464 775.349 125.719 775.141C124.974 774.937 124.401 774.641 124 774.25C123.604 773.859 123.406 773.391 123.406 772.844C123.406 772.286 123.604 771.812 124 771.422C124.401 771.026 124.974 770.727 125.719 770.523C126.464 770.315 127.354 770.211 128.391 770.211ZM128.391 771.734C127.729 771.734 127.18 771.776 126.742 771.859C126.31 771.937 125.982 772.06 125.758 772.227C125.539 772.393 125.432 772.599 125.437 772.844C125.432 773.094 125.539 773.299 125.758 773.461C125.982 773.622 126.31 773.742 126.742 773.82C127.18 773.898 127.729 773.937 128.391 773.937C129.042 773.937 129.583 773.898 130.016 773.82C130.453 773.742 130.781 773.622 131 773.461C131.224 773.299 131.336 773.094 131.336 772.844C131.336 772.604 131.224 772.401 131 772.234C130.781 772.062 130.453 771.937 130.016 771.859C129.578 771.776 129.036 771.734 128.391 771.734ZM146.906 775.453H144.93V770.297H146.906V775.453ZM152.43 771.359H139.461V769.727H152.43V771.359ZM146.68 764.109C146.68 764.917 146.448 765.664 145.984 766.352C145.526 767.034 144.854 767.607 143.969 768.07C143.089 768.534 142.044 768.836 140.836 768.977L140.109 767.422C141.125 767.297 141.997 767.06 142.727 766.711C143.456 766.362 144.005 765.958 144.375 765.5C144.745 765.042 144.93 764.578 144.93 764.109V763.75H146.68V764.109ZM146.93 764.109C146.93 764.568 147.112 765.026 147.477 765.484C147.846 765.943 148.393 766.349 149.117 766.703C149.846 767.057 150.716 767.297 151.727 767.422L151.008 768.977C149.805 768.836 148.76 768.529 147.875 768.055C146.995 767.576 146.323 766.995 145.859 766.312C145.401 765.625 145.172 764.891 145.172 764.109V763.75H146.93V764.109ZM151.234 764.422H140.633V762.852H151.234V764.422ZM146.906 763.391H144.93V761.234H146.906V763.391ZM164.5 775.414H162.5V761.203H164.5V775.414ZM166.508 768.312H163.984V766.672H166.508V768.312ZM160.703 762.672C160.698 764.151 160.484 765.518 160.062 766.773C159.646 768.029 158.961 769.182 158.008 770.234C157.055 771.286 155.805 772.193 154.258 772.953L153.133 771.43C154.404 770.789 155.453 770.062 156.281 769.25C157.109 768.432 157.727 767.513 158.133 766.492C158.539 765.466 158.745 764.312 158.75 763.031V762.672H160.703ZM159.75 764.305H153.93V762.672H159.75V764.305Z" fill="#56555A"/> +<path d="M386 748H231C224.373 748 219 753.373 219 760V776C219 782.627 224.373 788 231 788H386C392.627 788 398 782.627 398 776V760C398 753.373 392.627 748 386 748Z" fill="#B575FF"/> +<path d="M268.828 765.086C268.823 766.206 268.664 767.273 268.352 768.289C268.039 769.305 267.578 770.206 266.969 770.992C266.359 771.773 265.625 772.365 264.766 772.766L263.625 771.195C264.391 770.852 265.042 770.357 265.578 769.711C266.12 769.06 266.526 768.336 266.797 767.539C267.073 766.737 267.211 765.919 267.211 765.086V763.43H268.828V765.086ZM269.242 765.086C269.242 765.883 269.378 766.659 269.648 767.414C269.919 768.164 270.32 768.844 270.852 769.453C271.388 770.057 272.042 770.518 272.812 770.836L271.734 772.398C270.854 772.029 270.109 771.474 269.5 770.734C268.891 769.99 268.432 769.133 268.125 768.164C267.818 767.195 267.667 766.169 267.672 765.086V763.43H269.242V765.086ZM272.227 764.219H264.195V762.594H272.227V764.219ZM275.641 775.437H273.617V761.203H275.641V775.437ZM285.023 770.5H283.062V768.43H285.023V770.5ZM290.508 768.727H277.594V767.273H290.508V768.727ZM285.016 762.922H283.039V761.203H285.016V762.922ZM284.664 763.289C284.664 763.977 284.435 764.578 283.977 765.094C283.518 765.609 282.836 766.023 281.93 766.336C281.029 766.643 279.932 766.831 278.641 766.898L278.102 765.43C279.195 765.378 280.102 765.25 280.82 765.047C281.544 764.839 282.073 764.583 282.406 764.281C282.745 763.979 282.914 763.648 282.914 763.289V763H284.664V763.289ZM285.148 763.289C285.143 763.648 285.31 763.979 285.648 764.281C285.987 764.583 286.518 764.839 287.242 765.047C287.966 765.25 288.88 765.378 289.984 765.43L289.406 766.898C288.12 766.831 287.026 766.641 286.125 766.328C285.229 766.016 284.549 765.604 284.086 765.094C283.622 764.578 283.393 763.977 283.398 763.289V763H285.148V763.289ZM289.281 763.805H278.812V762.328H289.281V763.805ZM288.953 773.086H281.031V774.469H279.07V771.75H286.984V771.055H279.062V769.625H288.953V773.086ZM289.328 775.336H279.07V773.875H289.328V775.336ZM307.359 775.437H305.437V761.203H307.359V775.437ZM305.961 768.328H303.547V766.711H305.961V768.328ZM304.109 774.75H302.242V761.461H304.109V774.75ZM297.664 771.008H295.672V762.797H297.664V771.008ZM296.625 770.242C297.448 770.242 298.247 770.214 299.023 770.156C299.805 770.099 300.607 769.99 301.43 769.828L301.641 771.547C300.74 771.703 299.878 771.815 299.055 771.883C298.237 771.945 297.427 771.974 296.625 771.969H295.672V770.242H296.625ZM319.523 764.734H315.289V763.125H319.523V764.734ZM319.523 767.82H315.289V766.227H319.523V767.82ZM320.906 775.437H318.922V771.836H311.141V770.258H320.906V775.437ZM320.906 769.625H318.922V761.203H320.906V769.625ZM312.891 761.977C313.589 761.977 314.224 762.125 314.797 762.422C315.375 762.719 315.828 763.135 316.156 763.672C316.484 764.203 316.651 764.799 316.656 765.461C316.651 766.138 316.484 766.745 316.156 767.281C315.828 767.818 315.378 768.237 314.805 768.539C314.232 768.841 313.594 768.992 312.891 768.992C312.177 768.992 311.531 768.841 310.953 768.539C310.38 768.237 309.927 767.818 309.594 767.281C309.266 766.74 309.102 766.133 309.102 765.461C309.102 764.799 309.266 764.203 309.594 763.672C309.927 763.135 310.38 762.719 310.953 762.422C311.531 762.125 312.177 761.977 312.891 761.977ZM312.891 763.664C312.521 763.664 312.193 763.734 311.906 763.875C311.62 764.016 311.396 764.224 311.234 764.5C311.073 764.776 310.992 765.096 310.992 765.461C310.992 765.836 311.073 766.161 311.234 766.437C311.396 766.714 311.62 766.927 311.906 767.078C312.193 767.229 312.521 767.305 312.891 767.305C313.245 767.305 313.562 767.229 313.844 767.078C314.125 766.927 314.346 766.714 314.508 766.437C314.669 766.161 314.75 765.836 314.75 765.461C314.75 765.096 314.669 764.776 314.508 764.5C314.346 764.224 314.122 764.016 313.836 763.875C313.555 763.734 313.24 763.664 312.891 763.664ZM333.906 775.453H331.93V770.297H333.906V775.453ZM339.43 771.359H326.461V769.727H339.43V771.359ZM333.68 764.109C333.68 764.917 333.448 765.664 332.984 766.352C332.526 767.034 331.854 767.607 330.969 768.07C330.089 768.534 329.044 768.836 327.836 768.977L327.109 767.422C328.125 767.297 328.997 767.06 329.727 766.711C330.456 766.362 331.005 765.958 331.375 765.5C331.745 765.042 331.93 764.578 331.93 764.109V763.75H333.68V764.109ZM333.93 764.109C333.93 764.568 334.112 765.026 334.477 765.484C334.846 765.943 335.393 766.349 336.117 766.703C336.846 767.057 337.716 767.297 338.727 767.422L338.008 768.977C336.805 768.836 335.76 768.529 334.875 768.055C333.995 767.576 333.323 766.995 332.859 766.312C332.401 765.625 332.172 764.891 332.172 764.109V763.75H333.93V764.109ZM338.234 764.422H327.633V762.852H338.234V764.422ZM333.906 763.391H331.93V761.234H333.906V763.391ZM351.5 775.414H349.5V761.203H351.5V775.414ZM353.508 768.312H350.984V766.672H353.508V768.312ZM347.703 762.672C347.698 764.151 347.484 765.518 347.062 766.773C346.646 768.029 345.961 769.182 345.008 770.234C344.055 771.286 342.805 772.193 341.258 772.953L340.133 771.43C341.404 770.789 342.453 770.062 343.281 769.25C344.109 768.432 344.727 767.513 345.133 766.492C345.539 765.466 345.745 764.312 345.75 763.031V762.672H347.703ZM346.75 764.305H340.93V762.672H346.75V764.305Z" fill="white"/> +<path d="M80.2334 43.1544C81.0801 43.1599 81.8548 43.3508 82.5576 43.7272C83.2604 44.1035 83.8276 44.7232 84.2593 45.5865C84.6965 46.4498 84.915 47.5759 84.915 48.9649C84.915 50.3263 84.7214 51.4994 84.334 52.4845C83.9466 53.464 83.3877 54.2138 82.6572 54.734C81.9323 55.2486 81.0801 55.506 80.1006 55.506C79.3369 55.506 78.6535 55.3593 78.0503 55.066C77.4526 54.7672 76.9684 54.3605 76.5977 53.8458C76.2324 53.3312 76.0055 52.7418 75.917 52.0777H78.042C78.1195 52.3932 78.2523 52.6671 78.4404 52.8995C78.6286 53.1319 78.861 53.3118 79.1377 53.4391C79.4199 53.5663 79.7409 53.63 80.1006 53.63C80.6761 53.63 81.1659 53.4667 81.5698 53.1402C81.9793 52.8137 82.2892 52.3434 82.4995 51.7291C82.7098 51.1148 82.8177 50.3788 82.8232 49.5211H82.6987C82.4995 49.8642 82.2422 50.1603 81.9268 50.4093C81.6169 50.6528 81.2627 50.8409 80.8643 50.9737C80.4714 51.1065 80.0563 51.173 79.6191 51.173C78.9053 51.173 78.2578 51.0069 77.6768 50.6749C77.1012 50.3373 76.6447 49.8725 76.3071 49.2804C75.9696 48.6883 75.8008 48.0214 75.8008 47.2799C75.8008 46.4941 75.9834 45.7885 76.3486 45.1632C76.7194 44.5323 77.2396 44.0398 77.9092 43.6856C78.5843 43.3259 79.359 43.1489 80.2334 43.1544ZM80.2334 44.8976C79.7962 44.8976 79.3978 45.0027 79.0381 45.213C78.6839 45.4177 78.4045 45.7 78.1997 46.0597C77.995 46.4138 77.8953 46.8012 77.9009 47.2218C77.9009 47.6479 78.0005 48.038 78.1997 48.3922C78.3989 48.7408 78.6729 49.0175 79.0215 49.2223C79.3701 49.427 79.7658 49.5294 80.2085 49.5294C80.6401 49.5294 81.0358 49.4215 81.3955 49.2057C81.7607 48.9898 82.0485 48.7049 82.2588 48.3507C82.4691 47.9965 82.5742 47.6147 82.5742 47.2052C82.5742 46.7957 82.4718 46.4138 82.2671 46.0597C82.0623 45.7055 81.7829 45.4233 81.4287 45.213C81.0745 45.0027 80.6761 44.8976 80.2334 44.8976ZM88.0444 53.8375C87.8065 53.8375 87.5879 53.7794 87.3887 53.6632C87.195 53.547 87.04 53.3893 86.9238 53.19C86.8076 52.9908 86.7523 52.775 86.7578 52.5426C86.7523 52.3157 86.8076 52.1054 86.9238 51.9117C87.04 51.7125 87.195 51.5576 87.3887 51.4469C87.5879 51.3307 87.8065 51.2726 88.0444 51.2726C88.2713 51.2726 88.4816 51.3307 88.6753 51.4469C88.8745 51.5576 89.0322 51.7125 89.1484 51.9117C89.2646 52.1054 89.3228 52.3157 89.3228 52.5426C89.3228 52.775 89.2646 52.9908 89.1484 53.19C89.0322 53.3893 88.8745 53.547 88.6753 53.6632C88.4816 53.7794 88.2713 53.8375 88.0444 53.8375ZM88.0444 47.3961C87.8065 47.3961 87.5879 47.338 87.3887 47.2218C87.195 47.1056 87.04 46.9479 86.9238 46.7486C86.8076 46.5494 86.7523 46.3336 86.7578 46.1012C86.7523 45.8743 86.8076 45.664 86.9238 45.4703C87.04 45.2711 87.195 45.1161 87.3887 45.0055C87.5879 44.8893 87.8065 44.8312 88.0444 44.8312C88.2713 44.8312 88.4816 44.8893 88.6753 45.0055C88.8745 45.1161 89.0322 45.2711 89.1484 45.4703C89.2646 45.664 89.3228 45.8743 89.3228 46.1012C89.3228 46.3336 89.2646 46.5494 89.1484 46.7486C89.0322 46.9479 88.8745 47.1056 88.6753 47.2218C88.4816 47.338 88.2713 47.3961 88.0444 47.3961ZM91.124 51.3805L96.3203 43.3204H97.748V45.7774H96.8599L93.3403 51.2311V51.3307H100.595V53.0987H91.124V51.3805ZM96.9595 52.5841L96.9844 51.8038V43.3204H99.0264V55.3399H96.9595V52.5841ZM107.053 55.3399H104.878V45.4288H104.812L101.998 47.2301V45.2462L104.978 43.3204H107.053V55.3399Z" fill="black"/> +<path opacity="0.35" d="M369.133 43.5H352.733C350.634 43.5 348.933 45.2013 348.933 47.3V51.7C348.933 53.7987 350.634 55.5 352.733 55.5H369.133C371.232 55.5 372.933 53.7987 372.933 51.7V47.3C372.933 45.2013 371.232 43.5 369.133 43.5Z" stroke="black"/> +<path opacity="0.4" d="M374.433 47.7812V51.8568C375.237 51.5117 375.761 50.7086 375.761 49.819C375.761 48.9294 375.237 48.1265 374.433 47.7812Z" fill="black"/> +<path d="M368.933 45H352.933C351.552 45 350.433 46.1193 350.433 47.5V51.5C350.433 52.8807 351.552 54 352.933 54H368.933C370.314 54 371.433 52.8807 371.433 51.5V47.5C371.433 46.1193 370.314 45 368.933 45Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M332.703 46.104C335.19 46.1041 337.582 47.0262 339.385 48.6796C339.52 48.8073 339.737 48.8057 339.871 48.676L341.169 47.4126C341.236 47.3468 341.274 47.2577 341.273 47.165C341.273 47.0724 341.234 46.9837 341.166 46.9187C336.435 42.544 328.971 42.544 324.24 46.9187C324.171 46.9837 324.132 47.0723 324.132 47.165C324.131 47.2577 324.169 47.3468 324.237 47.4126L325.534 48.676C325.668 48.8059 325.885 48.8075 326.021 48.6796C327.824 47.0261 330.216 46.104 332.703 46.104ZM332.7 50.3243C334.057 50.3242 335.366 50.8359 336.372 51.76C336.508 51.8912 336.723 51.8883 336.855 51.7536L338.142 50.4343C338.21 50.3651 338.248 50.2712 338.247 50.1737C338.246 50.0761 338.206 49.9831 338.137 49.9153C335.073 47.0244 330.329 47.0244 327.265 49.9153C327.196 49.9831 327.156 50.0762 327.155 50.1738C327.154 50.2713 327.192 50.3652 327.26 50.4343L328.547 51.7536C328.68 51.8883 328.894 51.8912 329.03 51.76C330.036 50.8365 331.343 50.3248 332.7 50.3243ZM335.224 53.1178C335.226 53.2232 335.189 53.3247 335.122 53.3985L332.945 55.8533C332.881 55.9254 332.794 55.966 332.704 55.966C332.613 55.966 332.526 55.9254 332.462 55.8533L330.285 53.3985C330.218 53.3247 330.181 53.2231 330.183 53.1177C330.185 53.0124 330.225 52.9126 330.295 52.842C331.686 51.5281 333.721 51.5281 335.112 52.842C335.182 52.9127 335.222 53.0125 335.224 53.1178Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M316.633 44.6819C316.633 44.0488 316.155 43.5356 315.566 43.5356H314.499C313.91 43.5356 313.433 44.0488 313.433 44.6819V54.6158C313.433 55.2489 313.91 55.7621 314.499 55.7621H315.566C316.155 55.7621 316.633 55.2489 316.633 54.6158V44.6819ZM309.199 45.9809H310.265C310.854 45.9809 311.332 46.5064 311.332 47.1547V54.5883C311.332 55.2366 310.854 55.7621 310.265 55.7621H309.199C308.609 55.7621 308.132 55.2366 308.132 54.5883V47.1547C308.132 46.5064 308.609 45.9809 309.199 45.9809ZM304.867 48.63H303.8C303.211 48.63 302.733 49.1622 302.733 49.8187V54.5734C302.733 55.2299 303.211 55.762 303.8 55.762H304.867C305.456 55.762 305.933 55.2299 305.933 54.5734V49.8187C305.933 49.1622 305.456 48.63 304.867 48.63ZM299.566 51.0753H298.499C297.91 51.0753 297.433 51.5999 297.433 52.247V54.5904C297.433 55.2375 297.91 55.7621 298.499 55.7621H299.566C300.155 55.7621 300.633 55.2375 300.633 54.5904V52.247C300.633 51.5999 300.155 51.0753 299.566 51.0753Z" fill="black"/> +</g> +</g> +</g> +<mask id="mask4_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="426" y="221" width="3" height="105"> +<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="white"/> +</mask> +<g mask="url(#mask4_1837_9941)"> +<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="url(#paint0_linear_1837_9941)"/> +</g> +<mask id="mask5_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="428" y="221" width="2" height="105"> +<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="white"/> +</mask> +<g mask="url(#mask5_1837_9941)"> +<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="url(#paint1_linear_1837_9941)"/> +</g> +<mask id="mask6_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="3" height="67"> +<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="white"/> +</mask> +<g mask="url(#mask6_1837_9941)"> +<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="url(#paint2_linear_1837_9941)"/> +</g> +<mask id="mask7_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="1" height="67"> +<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.354 0 200.307L0.706443 199.448V265.633V265.637Z" fill="white"/> +</mask> +<g mask="url(#mask7_1837_9941)"> +<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.354 0 200.307L0.706443 199.448V265.633V265.637Z" fill="url(#paint3_linear_1837_9941)"/> +</g> +<mask id="mask8_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="199" width="2" height="67"> +<path d="M2.11914 265.653H3.63295V199.447H2.11914V265.653Z" fill="white"/> +</mask> +<g mask="url(#mask8_1837_9941)"> +<path d="M2.11914 265.653H3.63295V199.447H2.11914V265.653Z" fill="url(#paint4_linear_1837_9941)"/> +</g> +<mask id="mask9_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="3" height="67"> +<path d="M2.11943 348.924H0.706543V282.72H2.11943V348.924Z" fill="white"/> +</mask> +<g mask="url(#mask9_1837_9941)"> +<path d="M2.11943 348.924H0.706543V282.72H2.11943V348.924Z" fill="url(#paint5_linear_1837_9941)"/> +</g> +<mask id="mask10_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="1" height="67"> +<path d="M0.706443 348.928L0 348.068C0.333038 341.036 0.357259 290.645 0 283.598L0.706443 282.738V348.924V348.928Z" fill="white"/> +</mask> +<g mask="url(#mask10_1837_9941)"> +<path d="M0.706443 348.928L0 348.068C0.333038 341.036 0.357259 290.645 0 283.598L0.706443 282.738V348.924V348.928Z" fill="url(#paint6_linear_1837_9941)"/> +</g> +<mask id="mask11_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="282" width="2" height="67"> +<path d="M2.11914 348.944H3.63295V282.738H2.11914V348.944Z" fill="white"/> +</mask> +<g mask="url(#mask11_1837_9941)"> +<path d="M2.11914 348.944H3.63295V282.738H2.11914V348.944Z" fill="url(#paint7_linear_1837_9941)"/> +</g> +<mask id="mask12_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="3" height="35"> +<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="white"/> +</mask> +<g mask="url(#mask12_1837_9941)"> +<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="url(#paint8_linear_1837_9941)"/> +</g> +<mask id="mask13_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="1" height="35"> +<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="white"/> +</mask> +<g mask="url(#mask13_1837_9941)"> +<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="url(#paint9_linear_1837_9941)"/> +</g> +<mask id="mask14_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="136" width="2" height="35"> +<path d="M2.11914 170.878H3.63295V136.895H2.11914V170.878Z" fill="white"/> +</mask> +<g mask="url(#mask14_1837_9941)"> +<path d="M2.11914 170.878H3.63295V136.895H2.11914V170.878Z" fill="url(#paint10_linear_1837_9941)"/> +</g> +<path d="M246.886 60.5405H179.37C171.773 60.5405 165.615 54.3824 165.615 46.7851C165.615 39.1878 171.773 33.0295 179.37 33.0295H246.886C254.483 33.0295 260.641 39.1878 260.641 46.7851C260.641 54.3824 254.483 60.5405 246.886 60.5405ZM243.083 40.7803C239.767 40.7803 237.079 43.4688 237.079 46.7851C237.079 50.1033 239.767 52.7899 243.083 52.7899C246.4 52.7899 249.088 50.1033 249.088 46.7851C249.088 43.4688 246.4 40.7803 243.083 40.7803Z" fill="#1D1D1B"/> +<mask id="mask15_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="40" width="13" height="13"> +<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="white"/> +</mask> +<g mask="url(#mask15_1837_9941)"> +<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="url(#paint11_linear_1837_9941)"/> +</g> +<mask id="mask16_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="41" width="12" height="12"> +<path d="M243.063 52.3916C242.504 52.3916 241.943 52.3089 241.4 52.1373C240.526 51.8628 239.747 51.3804 239.117 50.7526C238.473 50.1067 238.011 49.3216 237.746 48.4779C237.294 47.0347 237.419 45.422 238.182 44.0535C238.437 43.5994 238.75 43.1836 239.115 42.8203C239.745 42.1886 240.524 41.7082 241.398 41.4317C241.941 41.2621 242.502 41.1794 243.061 41.1794C243.715 41.1794 244.367 41.2924 244.982 41.5124C245.751 41.7889 246.464 42.2289 247.053 42.8203C247.419 43.1836 247.734 43.5994 247.986 44.0535C248.749 45.422 248.874 47.0347 248.42 48.4779C248.155 49.3216 247.697 50.1067 247.051 50.7526C246.462 51.342 245.749 51.782 244.98 52.0565C244.367 52.2765 243.717 52.3916 243.063 52.3916ZM243.083 43.3532C241.19 43.3532 239.654 44.8892 239.654 46.7845C239.654 48.6798 241.19 50.2158 243.083 50.2158C244.978 50.2158 246.516 48.6798 246.516 46.7845C246.516 44.8892 244.978 43.3532 243.083 43.3532Z" fill="white"/> +</mask> +<g mask="url(#mask16_1837_9941)"> +<rect x="235.513" y="39.4111" width="14.7748" height="14.7748" fill="url(#pattern0_1837_9941)"/> +</g> +<mask id="mask17_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="239" y="43" width="8" height="8"> +<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="white"/> +</mask> +<g mask="url(#mask17_1837_9941)"> +<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="url(#paint12_linear_1837_9941)"/> +</g> +<mask id="mask18_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="240" y="43" width="7" height="7"> +<path d="M243.081 49.7905C241.416 49.7905 240.08 48.4463 240.08 46.7892C240.08 45.124 241.416 43.7838 243.081 43.7838C244.74 43.7838 246.084 45.124 246.084 46.7892C246.084 47.2636 245.973 47.7156 245.778 48.1153C245.669 47.6369 245.241 47.2817 244.732 47.2817C244.139 47.2817 243.66 47.7621 243.66 48.3535C243.66 48.8823 244.042 49.3223 244.546 49.4091C244.112 49.6513 243.612 49.7905 243.081 49.7905Z" fill="white"/> +</mask> +<g mask="url(#mask18_1837_9941)"> +<rect x="238.337" y="42.2378" width="8.92141" height="8.92141" fill="url(#pattern1_1837_9941)"/> +</g> +<mask id="mask19_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="244" y="48" width="2" height="2"> +<path d="M244.732 49.4263C244.668 49.4263 244.607 49.4182 244.546 49.4081C245.077 49.1114 245.507 48.6593 245.778 48.1143C245.794 48.189 245.804 48.2698 245.804 48.3525C245.804 48.9439 245.324 49.4263 244.732 49.4263Z" fill="white"/> +</mask> +<g mask="url(#mask19_1837_9941)"> +<rect x="243.182" y="46.2739" width="4.07723" height="4.88459" fill="url(#pattern2_1837_9941)"/> +</g> +<mask id="mask20_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="243" y="47" width="3" height="3"> +<path d="M244.547 49.4082C244.042 49.3214 243.661 48.8814 243.661 48.3526C243.661 47.7612 244.139 47.2808 244.732 47.2808C245.241 47.2808 245.669 47.636 245.778 48.1144C245.507 48.6593 245.078 49.1115 244.547 49.4082Z" fill="white"/> +</mask> +<g mask="url(#mask20_1837_9941)"> +<rect x="242.173" y="46.2739" width="5.08643" height="4.88459" fill="url(#pattern3_1837_9941)"/> +</g> +<defs> +<pattern id="pattern0_1837_9941" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_1837_9941" transform="scale(0.0666667)"/> +</pattern> +<pattern id="pattern1_1837_9941" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image1_1837_9941" transform="scale(0.111111)"/> +</pattern> +<pattern id="pattern2_1837_9941" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image2_1837_9941" transform="scale(0.25 0.2)"/> +</pattern> +<pattern id="pattern3_1837_9941" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image3_1837_9941" transform="scale(0.2)"/> +</pattern> +<linearGradient id="paint0_linear_1837_9941" x1="427.525" y1="221.428" x2="427.525" y2="325.938" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2B1D2A"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2B1D2A"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint1_linear_1837_9941" x1="429.38" y1="221.455" x2="429.38" y2="325.943" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint2_linear_1837_9941" x1="1.41299" y1="199.429" x2="1.41299" y2="265.633" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint3_linear_1837_9941" x1="0.353221" y1="199.448" x2="0.353221" y2="265.637" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint4_linear_1837_9941" x1="2.87604" y1="265.653" x2="2.87604" y2="199.446" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint5_linear_1837_9941" x1="1.41299" y1="282.72" x2="1.41299" y2="348.924" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint6_linear_1837_9941" x1="0.353221" y1="282.738" x2="0.353221" y2="348.928" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint7_linear_1837_9941" x1="2.87604" y1="348.944" x2="2.87604" y2="282.737" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint8_linear_1837_9941" x1="1.41299" y1="136.878" x2="1.41299" y2="170.859" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint9_linear_1837_9941" x1="0.353222" y1="136.895" x2="0.353222" y2="170.862" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint10_linear_1837_9941" x1="2.87604" y1="170.878" x2="2.87604" y2="136.895" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint11_linear_1837_9941" x1="243.083" y1="52.4197" x2="243.083" y2="40.5892" gradientUnits="userSpaceOnUse"> +<stop stop-color="#666666"/> +<stop offset="1" stop-color="#010104"/> +</linearGradient> +<linearGradient id="paint12_linear_1837_9941" x1="243.083" y1="43.5652" x2="243.083" y2="50.325" gradientUnits="userSpaceOnUse"> +<stop stop-color="#0B131C"/> +<stop offset="1" stop-color="#354039"/> +</linearGradient> +<clipPath id="clip0_1837_9941"> +<rect width="382" height="827" fill="white" transform="translate(24 20)"/> +</clipPath> +<image id="image0_1837_9941" width="15" height="15" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAUBJREFUKJGFks1S3TAMhT/JshPndl8ehIH3X8LQ9m1uAP+IhXMbAs1U2nhkHR0dSfLz7s45sTRNRItYtEP8slz48/sXegb8n90/PGJnnxoCACKCqo4O7Jh+Cr6ZM1SJCuEL+LTtoIFoEdm81kop70dms/iNxbtz87C1b2aEYOAOIiOmYSd3902vYmbkJRMtEmMkpUQpdVBseSZbFWBLKExpIsaIiCIiXC4/iDHy+rrSWuO9lAFeluUvuJRCnjPIkJBzZkoJVSGEwDxn1vW6a/7K/Pk9pYSZMc8ZC4E3d1R3mWZhH7/70KOq4OCAqtJ756011nXluq47eJrnw/i9d2qt4yB8FCy1YMEIQdGt0+7+/UhEFdUxqNYq12uh9T628EkinFzY7ZJqa4d4v61ShJfnJwTw+4fHf9U4tZfnJwA+AH+jc5A39zmDAAAAAElFTkSuQmCC"/> +<image id="image1_1837_9941" width="9" height="9" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAABHNCSVQICAgIfAhkiAAAAMRJREFUGJWF0LFKA1EQheH/3GxW4qIkogSCjUGstLDQKnUqKx9CH0vs8kYhxNJCElJkCSy6985YhDUoQqb+ivmP2lnm/HOWF6SDI5Rqwj4g+4sUiJcPpPELGoyQ1SjF36i+fcavn2D9hp9c4Wc3yCJZA+LgHoaPaPqKVlP88BRvd8DSFlle4P07WM+hWsJXCXIgIjfCz5OzCVQLyAu808Ptk1C+A47onXtTIbWw7gXEDWHzQajKbY+O+95UyCJYQm7Abr5vonZV760IjhkAAAAASUVORK5CYII="/> +<image id="image2_1837_9941" width="4" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAFCAYAAABirU3bAAAABHNCSVQICAgIfAhkiAAAAEVJREFUCJljlFHV+M+ABFjY2FkYUAXYWBg8XFwZPnz8yHDi9CkGRj1Lk/+srKwMf//+Zfj37x9EBQPDfwYWFiYGBgYmBgAtwhBN2erPwAAAAABJRU5ErkJggg=="/> +<image id="image3_1837_9941" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABHNCSVQICAgIfAhkiAAAAGJJREFUCJk1wbEKglAAheH/yE0rp8A18A1samxpa+4BfNMew7EHEBPkgiBeT5PfJzWtNXT4XGES4fshMPewTCADK/JGRl7i04X368HzVgNGut7NGjkuPxxHUkooHArLG2B2f3kOIpEJnXBlAAAAAElFTkSuQmCC"/> +</defs> +</svg> diff --git a/client/src/assets/image/chevronDownLarge.svg b/client/src/assets/image/chevronDownLarge.svg new file mode 100644 index 000000000..11a631f88 --- /dev/null +++ b/client/src/assets/image/chevronDownLarge.svg @@ -0,0 +1,3 @@ +<svg width="46" height="16" viewBox="0 0 46 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M44 2L23 14L2 2" stroke="#B2B1B6" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/client/src/assets/image/memberReportMockup.svg b/client/src/assets/image/memberReportMockup.svg new file mode 100644 index 000000000..efbaf3c1c --- /dev/null +++ b/client/src/assets/image/memberReportMockup.svg @@ -0,0 +1,311 @@ +<svg width="100%" height="100%" viewBox="0 0 430 867" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<path d="M358.532 867H71.3893C33.968 867 3.6333 836.665 3.6333 799.244V348.944V282.739V265.653V199.447V170.878V136.894V67.6347C3.6333 30.2134 33.968 -0.12131 71.3893 -0.12131H358.532C395.954 -0.12131 426.288 30.2134 426.288 67.6347V799.244C426.288 836.665 395.954 867 358.532 867ZM71.9202 1.8971C35.3203 1.8971 5.65171 31.5657 5.65171 68.1655V798.713C5.65171 835.312 35.3203 864.982 71.9202 864.982H358.001C394.601 864.982 424.27 835.312 424.27 798.713V68.1655C424.27 31.5657 394.601 1.8971 358.001 1.8971H71.9202ZM357.471 862.963H72.451C36.6727 862.963 7.67012 833.96 7.67012 798.182V68.6964C7.67012 32.9181 36.6727 3.91551 72.451 3.91551H357.471C393.247 3.91551 422.251 32.9181 422.251 68.6964V798.182C422.251 833.96 393.247 862.963 357.471 862.963ZM73.0908 6.49706C38.683 6.49706 10.7906 34.3895 10.7906 68.7973V798.081C10.7906 832.489 38.683 860.381 73.0908 860.381H356.831C391.239 860.381 419.131 832.489 419.131 798.081V68.7973C419.131 34.3895 391.239 6.49706 356.831 6.49706H73.0908Z" fill="#5E465D"/> +<path d="M358.001 864.981H71.9193C35.3195 864.981 5.65088 835.312 5.65088 798.713V68.1653C5.65088 31.5655 35.3195 1.89689 71.9193 1.89689H358.001C394.6 1.89689 424.269 31.5655 424.269 68.1653V798.713C424.269 835.312 394.6 864.981 358.001 864.981ZM72.4502 3.9153C36.6718 3.9153 7.66929 32.9179 7.66929 68.6962V798.181C7.66929 833.96 36.6718 862.963 72.4502 862.963H357.47C393.246 862.963 422.251 833.96 422.251 798.181V68.6962C422.251 32.9179 393.246 3.9153 357.47 3.9153H72.4502Z" fill="#A597A4"/> +<path d="M356.831 860.381H73.0908C38.6829 860.381 10.7905 832.489 10.7905 798.08V68.7972C10.7905 34.3893 38.6829 6.49689 73.0908 6.49689H356.831C391.239 6.49689 419.131 34.3893 419.131 68.7972V798.08C419.131 832.489 391.239 860.381 356.831 860.381ZM72.7739 20.3169C45.9593 20.3169 24.223 42.0552 24.223 68.8698V798.008C24.223 824.823 45.9593 846.561 72.7759 846.561H357.146C383.962 846.561 405.698 824.823 405.698 798.008V68.8698C405.698 42.0552 383.962 20.3169 357.146 20.3169H324.147H105.383C94.1145 20.3169 83.421 20.3169 72.7739 20.3169Z" fill="#1D1D1B"/> +<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> +<mask id="mask0_1837_11068" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> +<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> +</mask> +<g mask="url(#mask0_1837_11068)"> +<g clip-path="url(#clip0_1837_11068)"> +<path d="M406 20H24V847H406V20Z" fill="#F1F0F5"/> +<path d="M80.2334 43.1544C81.0801 43.1599 81.8548 43.3508 82.5576 43.7272C83.2604 44.1035 83.8276 44.7232 84.2593 45.5865C84.6965 46.4498 84.915 47.5759 84.915 48.9649C84.915 50.3263 84.7214 51.4994 84.334 52.4845C83.9466 53.464 83.3877 54.2138 82.6572 54.734C81.9323 55.2486 81.0801 55.506 80.1006 55.506C79.3369 55.506 78.6535 55.3593 78.0503 55.066C77.4526 54.7672 76.9684 54.3605 76.5977 53.8458C76.2324 53.3312 76.0055 52.7418 75.917 52.0777H78.042C78.1195 52.3932 78.2523 52.6671 78.4404 52.8995C78.6286 53.1319 78.861 53.3118 79.1377 53.4391C79.4199 53.5663 79.7409 53.63 80.1006 53.63C80.6761 53.63 81.1659 53.4667 81.5698 53.1402C81.9793 52.8137 82.2892 52.3434 82.4995 51.7291C82.7098 51.1148 82.8177 50.3788 82.8232 49.5211H82.6987C82.4995 49.8642 82.2422 50.1603 81.9268 50.4093C81.6169 50.6528 81.2627 50.8409 80.8643 50.9737C80.4714 51.1065 80.0563 51.173 79.6191 51.173C78.9053 51.173 78.2578 51.0069 77.6768 50.6749C77.1012 50.3373 76.6447 49.8725 76.3071 49.2804C75.9696 48.6883 75.8008 48.0214 75.8008 47.2799C75.8008 46.4941 75.9834 45.7885 76.3486 45.1632C76.7194 44.5323 77.2396 44.0398 77.9092 43.6856C78.5843 43.3259 79.359 43.1489 80.2334 43.1544ZM80.2334 44.8976C79.7962 44.8976 79.3978 45.0027 79.0381 45.213C78.6839 45.4177 78.4045 45.7 78.1997 46.0597C77.995 46.4138 77.8953 46.8012 77.9009 47.2218C77.9009 47.6479 78.0005 48.038 78.1997 48.3922C78.3989 48.7408 78.6729 49.0175 79.0215 49.2223C79.3701 49.427 79.7658 49.5294 80.2085 49.5294C80.6401 49.5294 81.0358 49.4215 81.3955 49.2057C81.7607 48.9898 82.0485 48.7049 82.2588 48.3507C82.4691 47.9965 82.5742 47.6147 82.5742 47.2052C82.5742 46.7957 82.4718 46.4138 82.2671 46.0597C82.0623 45.7055 81.7829 45.4233 81.4287 45.213C81.0745 45.0027 80.6761 44.8976 80.2334 44.8976ZM88.0444 53.8375C87.8065 53.8375 87.5879 53.7794 87.3887 53.6632C87.195 53.547 87.04 53.3893 86.9238 53.19C86.8076 52.9908 86.7523 52.775 86.7578 52.5426C86.7523 52.3157 86.8076 52.1054 86.9238 51.9117C87.04 51.7125 87.195 51.5576 87.3887 51.4469C87.5879 51.3307 87.8065 51.2726 88.0444 51.2726C88.2713 51.2726 88.4816 51.3307 88.6753 51.4469C88.8745 51.5576 89.0322 51.7125 89.1484 51.9117C89.2646 52.1054 89.3228 52.3157 89.3228 52.5426C89.3228 52.775 89.2646 52.9908 89.1484 53.19C89.0322 53.3893 88.8745 53.547 88.6753 53.6632C88.4816 53.7794 88.2713 53.8375 88.0444 53.8375ZM88.0444 47.3961C87.8065 47.3961 87.5879 47.338 87.3887 47.2218C87.195 47.1056 87.04 46.9479 86.9238 46.7486C86.8076 46.5494 86.7523 46.3336 86.7578 46.1012C86.7523 45.8743 86.8076 45.664 86.9238 45.4703C87.04 45.2711 87.195 45.1161 87.3887 45.0055C87.5879 44.8893 87.8065 44.8312 88.0444 44.8312C88.2713 44.8312 88.4816 44.8893 88.6753 45.0055C88.8745 45.1161 89.0322 45.2711 89.1484 45.4703C89.2646 45.664 89.3228 45.8743 89.3228 46.1012C89.3228 46.3336 89.2646 46.5494 89.1484 46.7486C89.0322 46.9479 88.8745 47.1056 88.6753 47.2218C88.4816 47.338 88.2713 47.3961 88.0444 47.3961ZM91.124 51.3805L96.3203 43.3204H97.748V45.7774H96.8599L93.3403 51.2311V51.3307H100.595V53.0987H91.124V51.3805ZM96.9595 52.5841L96.9844 51.8038V43.3204H99.0264V55.3399H96.9595V52.5841ZM107.053 55.3399H104.878V45.4288H104.812L101.998 47.2301V45.2462L104.978 43.3204H107.053V55.3399Z" fill="black"/> +<path opacity="0.35" d="M369.133 43.5H352.733C350.634 43.5 348.933 45.2013 348.933 47.3V51.7C348.933 53.7987 350.634 55.5 352.733 55.5H369.133C371.232 55.5 372.933 53.7987 372.933 51.7V47.3C372.933 45.2013 371.232 43.5 369.133 43.5Z" stroke="black"/> +<path opacity="0.4" d="M374.433 47.7812V51.8568C375.237 51.5117 375.761 50.7086 375.761 49.819C375.761 48.9294 375.237 48.1265 374.433 47.7812Z" fill="black"/> +<path d="M368.933 45H352.933C351.552 45 350.433 46.1193 350.433 47.5V51.5C350.433 52.8807 351.552 54 352.933 54H368.933C370.314 54 371.433 52.8807 371.433 51.5V47.5C371.433 46.1193 370.314 45 368.933 45Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M332.703 46.104C335.19 46.1041 337.582 47.0262 339.385 48.6796C339.521 48.8073 339.737 48.8057 339.871 48.676L341.169 47.4126C341.236 47.3468 341.274 47.2577 341.273 47.165C341.273 47.0724 341.234 46.9837 341.166 46.9187C336.435 42.544 328.971 42.544 324.24 46.9187C324.171 46.9837 324.132 47.0723 324.132 47.165C324.131 47.2577 324.169 47.3468 324.237 47.4126L325.534 48.676C325.668 48.8059 325.885 48.8075 326.021 48.6796C327.824 47.0261 330.216 46.104 332.703 46.104ZM332.7 50.3243C334.057 50.3242 335.366 50.8359 336.372 51.76C336.508 51.8912 336.723 51.8883 336.855 51.7536L338.142 50.4343C338.21 50.3651 338.248 50.2712 338.247 50.1737C338.246 50.0761 338.206 49.9831 338.137 49.9153C335.073 47.0244 330.329 47.0244 327.265 49.9153C327.196 49.9831 327.156 50.0762 327.155 50.1738C327.154 50.2714 327.192 50.3652 327.26 50.4343L328.547 51.7536C328.68 51.8883 328.894 51.8912 329.03 51.76C330.036 50.8365 331.343 50.3248 332.7 50.3243ZM335.224 53.1178C335.226 53.2232 335.189 53.3247 335.122 53.3985L332.945 55.8533C332.881 55.9254 332.794 55.966 332.704 55.966C332.613 55.966 332.526 55.9254 332.462 55.8533L330.285 53.3985C330.218 53.3247 330.181 53.2231 330.183 53.1177C330.185 53.0124 330.225 52.9126 330.295 52.842C331.686 51.5281 333.722 51.5281 335.112 52.842C335.182 52.9127 335.222 53.0125 335.224 53.1178Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M316.633 44.6824C316.633 44.0493 316.155 43.5361 315.566 43.5361H314.499C313.91 43.5361 313.433 44.0493 313.433 44.6824V54.6163C313.433 55.2494 313.91 55.7625 314.499 55.7625H315.566C316.155 55.7625 316.633 55.2494 316.633 54.6163V44.6824ZM309.199 45.9814H310.265C310.854 45.9814 311.332 46.5069 311.332 47.1552V54.5888C311.332 55.237 310.854 55.7625 310.265 55.7625H309.199C308.609 55.7625 308.132 55.237 308.132 54.5888V47.1552C308.132 46.5069 308.609 45.9814 309.199 45.9814ZM304.867 48.6305H303.8C303.211 48.6305 302.733 49.1627 302.733 49.8191V54.5739C302.733 55.2303 303.211 55.7625 303.8 55.7625H304.867C305.456 55.7625 305.933 55.2303 305.933 54.5739V49.8191C305.933 49.1627 305.456 48.6305 304.867 48.6305ZM299.566 51.0758H298.499C297.91 51.0758 297.433 51.6003 297.433 52.2475V54.5909C297.433 55.238 297.91 55.7625 298.499 55.7625H299.566C300.155 55.7625 300.633 55.238 300.633 54.5909V52.2475C300.633 51.6003 300.155 51.0758 299.566 51.0758Z" fill="black"/> +<path d="M51.8438 93.2811H41.9297V89.1093H51.8438V93.2811ZM43.8906 91.7891H49.8906V90.5938H43.8906V91.7891ZM52.7109 81.7266H41.0391V80.2344H52.7109V81.7266ZM46.9062 82.1016C48.4583 82.1016 49.6406 82.2733 50.4531 82.6171C51.2708 82.9556 51.6797 83.4583 51.6797 84.125C51.6797 84.7917 51.2708 85.2969 50.4531 85.6406C49.6406 85.9844 48.4583 86.1561 46.9062 86.1561C45.3594 86.1561 44.1745 85.9844 43.3516 85.6406C42.5286 85.2969 42.1172 84.7917 42.1172 84.125C42.1172 83.4583 42.5286 82.9556 43.3516 82.6171C44.1745 82.2733 45.3594 82.1016 46.9062 82.1016ZM46.9062 83.4375C46.2708 83.4375 45.7656 83.4609 45.3906 83.5078C45.0156 83.5547 44.7318 83.6276 44.5391 83.7266C44.3464 83.8255 44.25 83.9583 44.25 84.125C44.25 84.2865 44.3464 84.4167 44.5391 84.5156C44.7318 84.6146 45.0208 84.6901 45.4062 84.7422C45.7917 84.7943 46.2917 84.8202 46.9062 84.8202C47.5312 84.8202 48.0339 84.7943 48.4141 84.7422C48.7995 84.6901 49.0859 84.6146 49.2734 84.5156C49.4609 84.4167 49.5547 84.2865 49.5547 84.125C49.5547 83.9583 49.4609 83.8255 49.2734 83.7266C49.0859 83.6276 48.8047 83.5547 48.4297 83.5078C48.0547 83.4609 47.5469 83.4375 46.9062 83.4375ZM47.8984 81.3046H45.8984V79.0938H47.8984V81.3046ZM53.3984 88.3906H40.4297V86.8358H53.3984V88.3906ZM47.8984 87.6797H45.8984V85.6483H47.8984V87.6797Z" fill="#56555A"/> +<path d="M73.2188 81.875H67.0781V80.25H73.2188V81.875ZM70.8594 87.1094H68.875V83.5312H70.8594V87.1094ZM74.3984 81.2344C74.3932 81.9688 74.3724 82.6458 74.3359 83.2656C74.2995 83.8854 74.2135 84.5651 74.0781 85.3047L72.1094 85.1328C72.25 84.388 72.3385 83.737 72.375 83.1797C72.4167 82.6224 72.4427 81.9818 72.4531 81.2578V81.1328V80.25H74.3984V81.1328V81.2344ZM77.875 89.8516H75.8281V79.2031H77.875V89.8516ZM79.6016 85.2188H77.0703V83.5547H79.6016V85.2188ZM78.3203 93.1953H68.3281V91.5859H78.3203V93.1953ZM70.3281 92.0938H68.3281V88.9062H70.3281V92.0938ZM66.2344 86.3438C67.9375 86.3438 69.513 86.3151 70.9609 86.2578C72.4141 86.2005 73.7839 86.0781 75.0703 85.8906L75.1641 87.3281C73.8464 87.5729 72.4635 87.7344 71.0156 87.8125C69.5677 87.8906 68.0312 87.9297 66.4062 87.9297L66.2344 86.3438ZM92.1719 93.4766H90.1797V79.2031H92.1719V93.4766ZM82.2891 88.5C83.6276 88.5104 84.8281 88.4818 85.8906 88.4141C86.9583 88.3411 88.0495 88.2135 89.1641 88.0312L89.3438 89.6406C88.2448 89.8333 87.1484 89.9661 86.0547 90.0391C84.9661 90.1068 83.7109 90.1406 82.2891 90.1406H81.0156V88.5H82.2891ZM87.7578 85.8828H83.0703V89.125H81.0156V84.3203H85.7266V82.0156H81V80.4062H87.7578V85.8828Z" fill="#B2B1B6"/> +<path d="M406 114H24V214H406V114Z" fill="white"/> +<path d="M60.9609 151.188H58.1133V137.805H60.9609V151.188ZM58.875 145.551H55.3828V143.113H58.875V145.551ZM56.4141 150.496H53.625V138.215H56.4141V150.496ZM52.9922 142.34H42.5273V140.008H52.9922V142.34ZM47.7891 143.066C48.6875 143.066 49.4883 143.219 50.1914 143.523C50.9023 143.828 51.457 144.266 51.8555 144.836C52.2539 145.398 52.4531 146.051 52.4531 146.793C52.4531 147.512 52.2539 148.152 51.8555 148.715C51.457 149.27 50.9023 149.703 50.1914 150.016C49.4883 150.32 48.6875 150.473 47.7891 150.473C46.9062 150.473 46.1133 150.32 45.4102 150.016C44.7148 149.703 44.168 149.27 43.7695 148.715C43.3711 148.152 43.1719 147.512 43.1719 146.793C43.1719 146.051 43.3711 145.398 43.7695 144.836C44.168 144.266 44.7148 143.828 45.4102 143.523C46.1133 143.219 46.9062 143.066 47.7891 143.066ZM47.7891 145.211C47.4062 145.203 47.0664 145.262 46.7695 145.387C46.4805 145.512 46.2539 145.695 46.0898 145.938C45.9258 146.18 45.8438 146.465 45.8438 146.793C45.8438 147.113 45.9219 147.391 46.0781 147.625C46.2422 147.859 46.4688 148.043 46.7578 148.176C47.0547 148.301 47.3984 148.363 47.7891 148.363C48.1797 148.363 48.5234 148.301 48.8203 148.176C49.1172 148.043 49.3477 147.859 49.5117 147.625C49.6758 147.391 49.7578 147.113 49.7578 146.793C49.7578 146.465 49.6758 146.18 49.5117 145.938C49.3477 145.695 49.1172 145.512 48.8203 145.387C48.5234 145.262 48.1797 145.203 47.7891 145.211ZM49.2656 141.625H46.2773V138.016H49.2656V141.625ZM53.6719 151.41C55.2031 151.41 56.5234 151.562 57.6328 151.867C58.7422 152.164 59.5898 152.605 60.1758 153.191C60.7695 153.777 61.0664 154.477 61.0664 155.289C61.0664 156.109 60.7695 156.805 60.1758 157.375C59.5898 157.953 58.7422 158.395 57.6328 158.699C56.5234 159.004 55.2031 159.156 53.6719 159.156C52.1484 159.156 50.832 159.004 49.7227 158.699C48.6211 158.395 47.7734 157.953 47.1797 157.375C46.5859 156.805 46.2891 156.109 46.2891 155.289C46.2891 154.477 46.5859 153.777 47.1797 153.191C47.7734 152.605 48.6211 152.164 49.7227 151.867C50.832 151.562 52.1484 151.41 53.6719 151.41ZM53.6719 153.648C52.6953 153.641 51.8828 153.695 51.2344 153.812C50.5938 153.93 50.1055 154.113 49.7695 154.363C49.4414 154.613 49.2812 154.922 49.2891 155.289C49.2812 155.641 49.4414 155.938 49.7695 156.18C50.1055 156.414 50.5977 156.594 51.2461 156.719C51.8945 156.844 52.7031 156.906 53.6719 156.906C54.6406 156.906 55.4492 156.844 56.0977 156.719C56.7539 156.594 57.2422 156.414 57.5625 156.18C57.8906 155.945 58.0586 155.648 58.0664 155.289C58.0586 154.914 57.8906 154.605 57.5625 154.363C57.2422 154.113 56.7578 153.93 56.1094 153.812C55.4609 153.695 54.6484 153.641 53.6719 153.648ZM82.875 150.262H63.3867V147.895H82.875V150.262ZM74.5898 148.832H71.6602V144.684H74.5898V148.832ZM80.6484 146.066H65.7422V143.723H80.6484V146.066ZM80.5312 141.098H68.707V145.258H65.7422V138.766H80.5312V141.098ZM73.0781 151.316C74.6172 151.316 75.9414 151.473 77.0508 151.785C78.1602 152.09 79.0117 152.539 79.6055 153.133C80.1992 153.719 80.5 154.43 80.5078 155.266C80.5 156.094 80.1992 156.797 79.6055 157.375C79.0195 157.961 78.168 158.406 77.0508 158.711C75.9414 159.023 74.6172 159.184 73.0781 159.191C71.5234 159.184 70.1875 159.023 69.0703 158.711C67.9531 158.406 67.0938 157.961 66.4922 157.375C65.8984 156.789 65.6016 156.086 65.6016 155.266C65.6016 154.43 65.8984 153.719 66.4922 153.133C67.0938 152.539 67.9531 152.09 69.0703 151.785C70.1875 151.473 71.5234 151.316 73.0781 151.316ZM73.0781 153.602C72.0859 153.602 71.2617 153.664 70.6055 153.789C69.957 153.906 69.4648 154.09 69.1289 154.34C68.8008 154.59 68.6406 154.898 68.6484 155.266C68.6406 155.641 68.8008 155.949 69.1289 156.191C69.4648 156.434 69.957 156.613 70.6055 156.73C71.2617 156.848 72.0859 156.906 73.0781 156.906C74.0547 156.906 74.8672 156.848 75.5156 156.73C76.1719 156.613 76.6641 156.434 76.9922 156.191C77.3281 155.949 77.4961 155.641 77.4961 155.266C77.4961 154.906 77.3281 154.602 76.9922 154.352C76.6641 154.094 76.1719 153.906 75.5156 153.789C74.8594 153.664 74.0469 153.602 73.0781 153.602ZM102.551 159.156H99.7383V137.805H102.551V159.156ZM100.418 148.457H96.7969V146.066H100.418V148.457ZM97.6758 158.125H94.9336V138.191H97.6758V158.125ZM86.2148 151.832C87.7773 151.832 89.1172 151.797 90.2344 151.727C91.3516 151.656 92.5 151.516 93.6797 151.305L93.8906 153.73C92.7031 153.965 91.5352 154.121 90.3867 154.199C89.2461 154.27 87.8555 154.312 86.2148 154.328H84.7148V151.832H86.2148ZM92.6836 142.703H87.7148V153.039H84.7148V140.301H92.6836V142.703ZM112.16 141.59C112.152 142.98 111.926 144.277 111.481 145.48C111.035 146.676 110.352 147.719 109.43 148.609C108.516 149.5 107.391 150.16 106.055 150.59L104.555 148.234C105.695 147.867 106.652 147.34 107.426 146.652C108.199 145.957 108.77 145.176 109.137 144.309C109.512 143.441 109.703 142.535 109.711 141.59V140.195H112.16V141.59ZM112.734 141.578C112.734 142.445 112.91 143.27 113.262 144.051C113.613 144.824 114.156 145.52 114.891 146.137C115.625 146.746 116.543 147.215 117.645 147.543L116.238 149.875C114.926 149.484 113.828 148.879 112.945 148.059C112.063 147.23 111.398 146.266 110.953 145.164C110.516 144.055 110.297 142.859 110.297 141.578V140.195H112.734V141.578ZM116.988 141.637H105.363V139.246H116.988V141.637ZM121.781 150.473H118.793V137.805H121.781V150.473ZM124.664 145.211H120.938V142.773H124.664V145.211ZM114.785 150.895C116.262 150.895 117.539 151.059 118.617 151.387C119.703 151.707 120.535 152.176 121.113 152.793C121.691 153.41 121.981 154.148 121.981 155.008C121.981 155.867 121.691 156.605 121.113 157.223C120.535 157.848 119.703 158.324 118.617 158.652C117.539 158.988 116.262 159.156 114.785 159.156C113.293 159.156 111.996 158.988 110.895 158.652C109.793 158.324 108.945 157.848 108.352 157.223C107.766 156.605 107.473 155.867 107.473 155.008C107.473 154.148 107.766 153.41 108.352 152.793C108.945 152.176 109.789 151.707 110.883 151.387C111.984 151.059 113.285 150.895 114.785 150.895ZM114.785 153.215C113.856 153.215 113.066 153.281 112.418 153.414C111.777 153.547 111.293 153.75 110.965 154.023C110.637 154.289 110.477 154.617 110.484 155.008C110.477 155.414 110.637 155.754 110.965 156.027C111.293 156.293 111.777 156.496 112.418 156.637C113.059 156.77 113.848 156.836 114.785 156.836C115.715 156.836 116.492 156.77 117.117 156.637C117.75 156.496 118.227 156.293 118.547 156.027C118.875 155.754 119.039 155.414 119.039 155.008C119.039 154.609 118.875 154.277 118.547 154.012C118.227 153.746 117.75 153.547 117.117 153.414C116.492 153.281 115.715 153.215 114.785 153.215ZM136.91 139.316C137.988 139.316 138.949 139.629 139.793 140.254C140.645 140.871 141.312 141.758 141.797 142.914C142.281 144.062 142.527 145.398 142.535 146.922C142.527 148.453 142.281 149.797 141.797 150.953C141.312 152.102 140.645 152.984 139.793 153.602C138.949 154.219 137.988 154.527 136.91 154.527C135.816 154.527 134.844 154.219 133.992 153.602C133.141 152.984 132.473 152.102 131.988 150.953C131.512 149.797 131.273 148.453 131.273 146.922C131.273 145.398 131.512 144.062 131.988 142.914C132.473 141.758 133.141 140.871 133.992 140.254C134.844 139.629 135.816 139.316 136.91 139.316ZM136.91 142.023C136.363 142.016 135.883 142.203 135.469 142.586C135.055 142.969 134.73 143.527 134.496 144.262C134.27 144.996 134.156 145.883 134.156 146.922C134.156 147.961 134.27 148.848 134.496 149.582C134.73 150.316 135.055 150.875 135.469 151.258C135.883 151.633 136.363 151.82 136.91 151.82C137.465 151.82 137.949 151.633 138.363 151.258C138.777 150.875 139.094 150.316 139.312 149.582C139.539 148.848 139.652 147.961 139.652 146.922C139.652 145.883 139.539 144.996 139.312 144.262C139.094 143.52 138.777 142.961 138.363 142.586C137.949 142.203 137.465 142.016 136.91 142.023ZM150.996 145.281H147.176V142.785H150.996V145.281ZM150.996 151.504H147.176V149.078H150.996V151.504ZM147.984 159.156H144.984V137.805H147.984V159.156ZM159.41 159.156H156.34V151.27H159.41V159.156ZM166.816 159.156H163.781V151.27H166.816V159.156ZM171.387 152.102H151.887V149.688H171.387V152.102ZM161.578 138.531C163.094 138.531 164.441 138.73 165.621 139.129C166.801 139.527 167.715 140.09 168.363 140.816C169.02 141.543 169.348 142.387 169.348 143.348C169.348 144.293 169.02 145.121 168.363 145.832C167.715 146.535 166.801 147.082 165.621 147.473C164.441 147.863 163.094 148.059 161.578 148.059C160.062 148.059 158.719 147.863 157.547 147.473C156.375 147.082 155.461 146.535 154.805 145.832C154.156 145.121 153.832 144.293 153.832 143.348C153.832 142.387 154.156 141.543 154.805 140.816C155.461 140.09 156.375 139.527 157.547 139.129C158.719 138.73 160.062 138.531 161.578 138.531ZM161.578 140.922C160.617 140.93 159.785 141.027 159.082 141.215C158.387 141.395 157.852 141.668 157.477 142.035C157.102 142.395 156.918 142.832 156.926 143.348C156.918 143.84 157.102 144.262 157.477 144.613C157.852 144.965 158.387 145.234 159.082 145.422C159.785 145.602 160.617 145.691 161.578 145.691C162.539 145.691 163.371 145.602 164.074 145.422C164.777 145.234 165.316 144.969 165.691 144.625C166.074 144.273 166.266 143.848 166.266 143.348C166.266 142.832 166.074 142.395 165.691 142.035C165.316 141.668 164.777 141.395 164.074 141.215C163.379 141.027 162.547 140.93 161.578 140.922ZM181.137 154.258H178.16V150.777H181.137V154.258ZM190.559 159.156H187.594V137.805H190.559V159.156ZM173.578 153.133C176.234 153.117 178.57 153.074 180.586 153.004C182.609 152.926 184.555 152.762 186.422 152.512L186.609 154.727C184.547 155.086 182.426 155.32 180.246 155.43C178.066 155.531 175.695 155.582 173.133 155.582L172.734 153.133H173.578ZM186.117 142.551H173.156V140.207H186.117V142.551ZM179.625 143.395C180.672 143.395 181.602 143.562 182.414 143.898C183.234 144.227 183.867 144.695 184.312 145.305C184.766 145.914 184.992 146.613 184.992 147.402C184.992 148.184 184.766 148.879 184.312 149.488C183.867 150.09 183.234 150.559 182.414 150.895C181.602 151.23 180.672 151.398 179.625 151.398C178.594 151.398 177.676 151.23 176.871 150.895C176.066 150.559 175.438 150.09 174.984 149.488C174.539 148.879 174.316 148.184 174.316 147.402C174.316 146.613 174.539 145.914 174.984 145.305C175.438 144.695 176.066 144.227 176.871 143.898C177.676 143.562 178.594 143.395 179.625 143.395ZM179.625 145.656C179.141 145.656 178.711 145.727 178.336 145.867C177.969 146 177.68 146.199 177.469 146.465C177.258 146.73 177.152 147.043 177.152 147.402C177.152 147.77 177.254 148.082 177.457 148.34C177.668 148.59 177.961 148.785 178.336 148.926C178.711 149.059 179.141 149.125 179.625 149.125C180.125 149.125 180.566 149.059 180.949 148.926C181.332 148.785 181.625 148.59 181.828 148.34C182.031 148.082 182.133 147.77 182.133 147.402C182.133 147.043 182.031 146.73 181.828 146.465C181.625 146.199 181.332 146 180.949 145.867C180.566 145.727 180.125 145.656 179.625 145.656ZM181.16 141.543H178.16V137.91H181.16V141.543Z" fill="#56555A"/> +<path d="M380 174H50C45.5817 174 42 177.582 42 182V190C42 194.418 45.5817 198 50 198H380C384.418 198 388 194.418 388 190V182C388 177.582 384.418 174 380 174Z" fill="white"/> +<path d="M50.6602 187.188H47.9883V186.426H50.6602V187.188ZM51.0585 191.184H50.1327V183.543H51.0585V191.184ZM51.3516 193.727H44.3672V192.953H51.3516V193.727ZM45.2929 193.328H44.3672V190.492H45.2929V193.328ZM45.8789 185.688C45.8789 186.309 45.7559 186.896 45.5098 187.451C45.2637 188.002 44.918 188.486 44.4727 188.904C44.0312 189.318 43.5234 189.633 42.9492 189.848L42.4688 189.098C42.9765 188.918 43.4316 188.654 43.834 188.307C44.2363 187.959 44.5508 187.559 44.7773 187.105C45.0039 186.648 45.1172 186.176 45.1172 185.688V184.832H45.8789V185.688ZM46.0429 185.688C46.0429 186.133 46.1522 186.566 46.371 186.988C46.5897 187.41 46.8926 187.785 47.2793 188.113C47.666 188.441 48.1094 188.691 48.6094 188.863L48.1289 189.602C47.5703 189.398 47.0762 189.1 46.6465 188.705C46.2207 188.311 45.8887 187.854 45.6504 187.334C45.4121 186.814 45.2929 186.266 45.2929 185.688V184.832H46.0429V185.688ZM48.375 185.148H42.7617V184.387H48.375V185.148ZM59.0858 188.43H57.082V187.645H59.0858V188.43ZM55.6875 186.742C55.6836 187.438 55.584 188.117 55.3887 188.781C55.1973 189.445 54.918 190.043 54.5508 190.574C54.1875 191.102 53.7578 191.516 53.2617 191.816L52.7108 191.113C53.1718 190.848 53.5723 190.482 53.9121 190.018C54.252 189.553 54.5117 189.035 54.6914 188.465C54.875 187.895 54.9688 187.32 54.9727 186.742V186.191H55.6875V186.742ZM55.8398 186.742C55.8438 187.305 55.9355 187.855 56.1152 188.395C56.2988 188.934 56.5625 189.424 56.9062 189.865C57.25 190.303 57.6523 190.645 58.1133 190.891L57.5858 191.582C57.0819 191.309 56.6444 190.92 56.2733 190.416C55.9061 189.912 55.6229 189.342 55.4237 188.705C55.2284 188.068 55.1328 187.414 55.1367 186.742V186.191H55.8398V186.742ZM57.7969 186.227H52.9922V185.465H57.7969V186.227ZM55.8516 186.039H54.9727V183.918H55.8516V186.039ZM61.6992 193.949H60.8203V183.531H61.6992V193.949ZM59.5898 193.41H58.7226V183.789H59.5898V193.41ZM69.7383 186.73C69.7383 187.449 69.6015 188.158 69.328 188.857C69.0546 189.557 68.6875 190.178 68.2266 190.721C67.7695 191.264 67.2695 191.672 66.7266 191.945L66.1758 191.219C66.6719 190.98 67.1328 190.621 67.5586 190.141C67.9883 189.656 68.332 189.113 68.5898 188.512C68.8477 187.91 68.9766 187.316 68.9766 186.73V185.008H69.7383V186.73ZM69.9023 186.73C69.9023 187.305 70.0312 187.877 70.2891 188.447C70.5469 189.014 70.8906 189.52 71.3203 189.965C71.75 190.41 72.2188 190.742 72.7266 190.961L72.2108 191.688C71.6444 191.43 71.1289 191.047 70.6641 190.539C70.2031 190.031 69.8359 189.447 69.5625 188.787C69.293 188.123 69.1602 187.438 69.1641 186.73V185.008H69.9023V186.73ZM72.3867 185.371H66.5155V184.609H72.3867V185.371ZM74.7655 193.949H73.8398V183.531H74.7655V193.949ZM81.7383 190.293H80.8358V188.711H81.7383V190.293ZM86.0391 188.887H76.5586V188.172H86.0391V188.887ZM81.7383 184.738H80.8358V183.473H81.7383V184.738ZM81.5976 184.984C81.5976 185.512 81.4061 185.969 81.0233 186.355C80.6405 186.738 80.1269 187.041 79.4823 187.264C78.8417 187.482 78.125 187.625 77.332 187.691L77.0625 186.988C77.75 186.945 78.377 186.838 78.9434 186.666C79.5098 186.49 79.959 186.26 80.291 185.975C80.623 185.686 80.7891 185.355 80.7891 184.984V184.832H81.5976V184.984ZM81.7969 184.984C81.793 185.355 81.957 185.686 82.2891 185.975C82.625 186.26 83.0742 186.49 83.6367 186.666C84.2031 186.838 84.8319 186.945 85.5233 186.988L85.2421 187.691C84.453 187.625 83.7382 187.482 83.0976 187.264C82.4569 187.041 81.9453 186.738 81.5625 186.355C81.1797 185.969 80.9883 185.512 80.9883 184.984V184.832H81.7969V184.984ZM85.078 185.172H77.5312V184.445H85.078V185.172ZM84.8203 192.109H78.6328V193.387H77.7188V191.453H83.9179V190.551H77.6953V189.859H84.8203V192.109ZM85.1367 193.832H77.7188V193.129H85.1367V193.832ZM97.9102 184.855H91.1367V184.094H97.9102V184.855ZM99.4688 188.688H89.9297V187.926H99.4688V188.688ZM98.2147 184.867C98.2147 185.473 98.1952 186.023 98.1561 186.52C98.1171 187.012 98.0234 187.578 97.875 188.219L96.9608 188.16C97.0663 187.73 97.1425 187.326 97.1894 186.947C97.2401 186.568 97.2715 186.236 97.2832 185.951C97.2949 185.662 97.3007 185.324 97.3007 184.938V184.867V184.094H98.2147V184.867ZM98.2617 193.809H91.1016V190.129H98.2617V193.809ZM92.0156 193.059H97.3477V190.855H92.0156V193.059ZM102.797 184.188C103.25 184.188 103.658 184.291 104.021 184.498C104.385 184.705 104.67 184.996 104.877 185.371C105.084 185.746 105.187 186.172 105.187 186.648C105.187 187.125 105.084 187.547 104.877 187.914C104.67 188.281 104.385 188.568 104.021 188.775C103.662 188.982 103.254 189.086 102.797 189.086C102.336 189.086 101.926 188.982 101.566 188.775C101.207 188.568 100.926 188.281 100.723 187.914C100.519 187.547 100.418 187.125 100.418 186.648C100.418 186.172 100.519 185.746 100.723 185.371C100.926 184.996 101.207 184.705 101.566 184.498C101.926 184.291 102.336 184.188 102.797 184.188ZM102.797 184.984C102.5 184.984 102.234 185.055 102 185.195C101.766 185.336 101.58 185.535 101.443 185.793C101.31 186.047 101.246 186.332 101.25 186.648C101.246 186.965 101.31 187.25 101.443 187.504C101.58 187.754 101.766 187.951 102 188.096C102.234 188.24 102.5 188.312 102.797 188.312C103.09 188.312 103.353 188.24 103.588 188.096C103.826 187.951 104.012 187.754 104.144 187.504C104.277 187.25 104.344 186.965 104.344 186.648C104.344 186.332 104.277 186.047 104.144 185.793C104.012 185.535 103.826 185.336 103.588 185.195C103.353 185.055 103.09 184.984 102.797 184.984ZM109.148 189.742H108.269V183.543H109.148V189.742ZM108.551 186.988H106.547V186.227H108.551V186.988ZM106.887 189.672H106.019V183.742H106.887V189.672ZM109.148 193.949H108.246V191.066H102.129V190.328H109.148V193.949Z" fill="#B2B1B6"/> +<path d="M309.047 190.969L312.906 186.906C313.411 186.365 313.797 185.927 314.062 185.594C314.333 185.26 314.539 184.943 314.68 184.641C314.82 184.333 314.891 184.01 314.891 183.672C314.891 183.292 314.792 182.958 314.594 182.672C314.396 182.38 314.125 182.154 313.781 181.992C313.443 181.831 313.062 181.75 312.641 181.75C312.198 181.75 311.81 181.839 311.477 182.016C311.148 182.193 310.893 182.443 310.711 182.766C310.529 183.083 310.438 183.453 310.438 183.875H309.109C309.104 183.219 309.255 182.638 309.562 182.133C309.875 181.628 310.305 181.234 310.852 180.953C311.398 180.672 312.01 180.531 312.688 180.531C313.359 180.531 313.961 180.669 314.492 180.945C315.029 181.221 315.448 181.599 315.75 182.078C316.052 182.557 316.203 183.089 316.203 183.672C316.198 184.104 316.117 184.518 315.961 184.914C315.81 185.305 315.549 185.74 315.18 186.219C314.81 186.698 314.286 187.286 313.609 187.984L311.016 190.656V190.75H316.406V192H309.062L309.047 190.969ZM322.219 180.531C322.938 180.542 323.607 180.714 324.227 181.047C324.846 181.38 325.352 181.945 325.742 182.742C326.133 183.534 326.328 184.583 326.328 185.891C326.328 187.214 326.156 188.344 325.812 189.281C325.469 190.219 324.974 190.932 324.328 191.422C323.682 191.911 322.917 192.156 322.031 192.156C321.375 192.156 320.786 192.029 320.266 191.773C319.745 191.518 319.32 191.167 318.992 190.719C318.664 190.266 318.453 189.74 318.359 189.141H319.75C319.833 189.49 319.977 189.797 320.18 190.062C320.383 190.323 320.641 190.529 320.953 190.68C321.266 190.831 321.625 190.906 322.031 190.906C322.646 190.906 323.177 190.734 323.625 190.391C324.073 190.047 324.414 189.552 324.648 188.906C324.888 188.255 325.01 187.474 325.016 186.562H324.859C324.641 186.875 324.383 187.143 324.086 187.367C323.789 187.591 323.461 187.763 323.102 187.883C322.742 188.003 322.365 188.062 321.969 188.062C321.297 188.062 320.677 187.901 320.109 187.578C319.547 187.255 319.099 186.81 318.766 186.242C318.432 185.674 318.266 185.036 318.266 184.328C318.266 183.625 318.43 182.984 318.758 182.406C319.086 181.823 319.549 181.365 320.148 181.031C320.747 180.693 321.438 180.526 322.219 180.531ZM322.219 181.766C321.734 181.766 321.294 181.88 320.898 182.109C320.508 182.339 320.198 182.648 319.969 183.039C319.745 183.43 319.635 183.854 319.641 184.312C319.641 184.776 319.75 185.201 319.969 185.586C320.188 185.966 320.487 186.268 320.867 186.492C321.253 186.716 321.688 186.828 322.172 186.828C322.651 186.828 323.091 186.708 323.492 186.469C323.893 186.229 324.211 185.914 324.445 185.523C324.68 185.133 324.797 184.719 324.797 184.281C324.797 183.849 324.685 183.44 324.461 183.055C324.237 182.664 323.927 182.352 323.531 182.117C323.141 181.883 322.703 181.766 322.219 181.766ZM327.984 188.531L333.078 180.688H333.922V182.469H333.328L329.5 188.359V188.453H336.391V189.688H327.984V188.531ZM333.469 189.344V188.797V180.688H334.812V192H333.469V189.344ZM338.297 195.203H337.141L338 190.953H339.516L338.297 195.203ZM345.281 192.156C344.5 192.156 343.805 192.021 343.195 191.75C342.586 191.479 342.112 191.104 341.773 190.625C341.435 190.146 341.266 189.604 341.266 189C341.266 188.521 341.367 188.073 341.57 187.656C341.773 187.24 342.049 186.898 342.398 186.633C342.747 186.362 343.135 186.193 343.562 186.125V186.062C343.193 185.979 342.867 185.815 342.586 185.57C342.31 185.326 342.094 185.026 341.938 184.672C341.781 184.318 341.703 183.938 341.703 183.531C341.703 182.964 341.857 182.453 342.164 182C342.471 181.542 342.896 181.182 343.438 180.922C343.984 180.661 344.599 180.531 345.281 180.531C345.958 180.531 346.57 180.661 347.117 180.922C347.664 181.182 348.091 181.542 348.398 182C348.711 182.453 348.87 182.964 348.875 183.531C348.87 183.938 348.786 184.318 348.625 184.672C348.469 185.026 348.25 185.326 347.969 185.57C347.688 185.815 347.365 185.979 347 186.062V186.125C347.422 186.193 347.807 186.362 348.156 186.633C348.51 186.898 348.789 187.24 348.992 187.656C349.201 188.073 349.307 188.521 349.312 189C349.307 189.604 349.133 190.146 348.789 190.625C348.451 191.104 347.974 191.479 347.359 191.75C346.75 192.021 346.057 192.156 345.281 192.156ZM345.281 190.922C345.812 190.922 346.276 190.836 346.672 190.664C347.068 190.492 347.372 190.258 347.586 189.961C347.799 189.664 347.906 189.318 347.906 188.922C347.906 188.51 347.794 188.141 347.57 187.812C347.346 187.479 347.034 187.219 346.633 187.031C346.232 186.844 345.781 186.75 345.281 186.75C344.781 186.75 344.333 186.844 343.938 187.031C343.542 187.219 343.229 187.479 343 187.812C342.776 188.141 342.667 188.51 342.672 188.922C342.667 189.318 342.768 189.664 342.977 189.961C343.19 190.258 343.492 190.492 343.883 190.664C344.279 190.836 344.745 190.922 345.281 190.922ZM345.281 185.562C345.708 185.562 346.091 185.479 346.43 185.312C346.768 185.146 347.031 184.919 347.219 184.633C347.406 184.346 347.5 184.016 347.5 183.641C347.5 183.266 347.409 182.935 347.227 182.648C347.044 182.362 346.784 182.141 346.445 181.984C346.107 181.828 345.719 181.75 345.281 181.75C344.839 181.75 344.451 181.828 344.117 181.984C343.789 182.141 343.531 182.362 343.344 182.648C343.156 182.935 343.062 183.266 343.062 183.641C343.062 184.016 343.159 184.346 343.352 184.633C343.544 184.919 343.807 185.146 344.141 185.312C344.474 185.479 344.854 185.562 345.281 185.562ZM354.906 192.156C354.073 192.156 353.362 191.93 352.773 191.477C352.185 191.023 351.734 190.362 351.422 189.492C351.109 188.622 350.953 187.573 350.953 186.344C350.953 185.13 351.109 184.089 351.422 183.219C351.734 182.344 352.185 181.677 352.773 181.219C353.367 180.76 354.078 180.531 354.906 180.531C355.729 180.531 356.438 180.76 357.031 181.219C357.625 181.677 358.078 182.344 358.391 183.219C358.703 184.089 358.859 185.13 358.859 186.344C358.859 187.573 358.706 188.622 358.398 189.492C358.091 190.362 357.641 191.023 357.047 191.477C356.453 191.93 355.74 192.156 354.906 192.156ZM354.906 190.906C355.448 190.906 355.914 190.729 356.305 190.375C356.695 190.021 356.99 189.503 357.188 188.82C357.385 188.138 357.484 187.312 357.484 186.344C357.484 185.375 357.383 184.547 357.18 183.859C356.977 183.172 356.682 182.648 356.297 182.289C355.911 181.93 355.448 181.75 354.906 181.75C354.365 181.75 353.901 181.93 353.516 182.289C353.13 182.648 352.833 183.172 352.625 183.859C352.417 184.547 352.312 185.375 352.312 186.344C352.312 187.312 352.417 188.138 352.625 188.82C352.833 189.503 353.128 190.021 353.508 190.375C353.893 190.729 354.359 190.906 354.906 190.906ZM364.438 192.156C363.604 192.156 362.893 191.93 362.305 191.477C361.716 191.023 361.266 190.362 360.953 189.492C360.641 188.622 360.484 187.573 360.484 186.344C360.484 185.13 360.641 184.089 360.953 183.219C361.266 182.344 361.716 181.677 362.305 181.219C362.898 180.76 363.609 180.531 364.438 180.531C365.26 180.531 365.969 180.76 366.562 181.219C367.156 181.677 367.609 182.344 367.922 183.219C368.234 184.089 368.391 185.13 368.391 186.344C368.391 187.573 368.237 188.622 367.93 189.492C367.622 190.362 367.172 191.023 366.578 191.477C365.984 191.93 365.271 192.156 364.438 192.156ZM364.438 190.906C364.979 190.906 365.445 190.729 365.836 190.375C366.227 190.021 366.521 189.503 366.719 188.82C366.917 188.138 367.016 187.312 367.016 186.344C367.016 185.375 366.914 184.547 366.711 183.859C366.508 183.172 366.214 182.648 365.828 182.289C365.443 181.93 364.979 181.75 364.438 181.75C363.896 181.75 363.432 181.93 363.047 182.289C362.661 182.648 362.365 183.172 362.156 183.859C361.948 184.547 361.844 185.375 361.844 186.344C361.844 187.312 361.948 188.138 362.156 188.82C362.365 189.503 362.659 190.021 363.039 190.375C363.424 190.729 363.891 190.906 364.438 190.906ZM379.016 189.453H377.781V186.359H379.016V189.453ZM385.234 189.938H384V179.391H385.234V189.938ZM385.578 192.969H375.703V191.938H385.578V192.969ZM376.938 192.234H375.703V188.906H376.938V192.234ZM373.703 185.828C375.562 185.818 377.208 185.789 378.641 185.742C380.073 185.69 381.443 185.583 382.75 185.422L382.828 186.312C381.479 186.526 380.065 186.667 378.586 186.734C377.107 186.802 375.536 186.833 373.875 186.828L373.703 185.828ZM384.328 188.5H381.125V187.609H384.328V188.5ZM378.266 179.953C378.938 179.953 379.534 180.052 380.055 180.25C380.581 180.448 380.987 180.732 381.273 181.102C381.56 181.471 381.703 181.896 381.703 182.375C381.703 182.865 381.56 183.289 381.273 183.648C380.987 184.008 380.583 184.286 380.062 184.484C379.542 184.682 378.943 184.781 378.266 184.781C377.583 184.781 376.982 184.682 376.461 184.484C375.945 184.286 375.544 184.008 375.258 183.648C374.971 183.289 374.828 182.865 374.828 182.375C374.828 181.896 374.971 181.471 375.258 181.102C375.544 180.732 375.948 180.448 376.469 180.25C376.99 180.052 377.589 179.953 378.266 179.953ZM378.266 180.891C377.818 180.885 377.422 180.945 377.078 181.07C376.734 181.19 376.466 181.365 376.273 181.594C376.086 181.823 375.995 182.083 376 182.375C375.995 182.672 376.086 182.935 376.273 183.164C376.466 183.388 376.734 183.562 377.078 183.688C377.422 183.812 377.818 183.875 378.266 183.875C378.703 183.875 379.094 183.812 379.438 183.688C379.781 183.562 380.049 183.388 380.242 183.164C380.435 182.935 380.531 182.672 380.531 182.375C380.531 182.083 380.435 181.823 380.242 181.594C380.049 181.365 379.781 181.19 379.438 181.07C379.094 180.945 378.703 180.885 378.266 180.891Z" fill="#56555A"/> +<path d="M406 214H24V254H406V214Z" fill="white"/> +<mask id="mask1_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="214" width="191" height="40"> +<path d="M24 214H215V254H24V214Z" fill="white"/> +</mask> +<g mask="url(#mask1_1837_11068)"> +<path d="M215 253H24V255H215V253Z" fill="#B2B1B6"/> +</g> +<path d="M85.5469 232.25H81.9844V231.234H85.5469V232.25ZM86.0781 237.578H84.8438V227.391H86.0781V237.578ZM86.4688 240.969H77.1562V239.938H86.4688V240.969ZM78.3906 240.438H77.1562V236.656H78.3906V240.438ZM79.1719 230.25C79.1719 231.078 79.0078 231.862 78.6797 232.602C78.3516 233.336 77.8906 233.982 77.2969 234.539C76.7083 235.091 76.0312 235.51 75.2656 235.797L74.625 234.797C75.3021 234.557 75.9089 234.206 76.4453 233.742C76.9818 233.279 77.401 232.745 77.7031 232.141C78.0052 231.531 78.1562 230.901 78.1562 230.25V229.109H79.1719V230.25ZM79.3906 230.25C79.3906 230.844 79.5365 231.422 79.8281 231.984C80.1198 232.547 80.5234 233.047 81.0391 233.484C81.5547 233.922 82.1458 234.255 82.8125 234.484L82.1719 235.469C81.4271 235.198 80.7682 234.799 80.1953 234.273C79.6276 233.747 79.1849 233.138 78.8672 232.445C78.5495 231.753 78.3906 231.021 78.3906 230.25V229.109H79.3906V230.25ZM82.5 229.531H75.0156V228.516H82.5V229.531ZM96.7812 233.906H94.1094V232.859H96.7812V233.906ZM92.25 231.656C92.2448 232.583 92.112 233.49 91.8516 234.375C91.5964 235.26 91.224 236.057 90.7344 236.766C90.25 237.469 89.6771 238.021 89.0156 238.422L88.2812 237.484C88.8958 237.13 89.4297 236.643 89.8828 236.023C90.3359 235.404 90.6823 234.714 90.9219 233.953C91.1667 233.193 91.2917 232.427 91.2969 231.656V230.922H92.25V231.656ZM92.4531 231.656C92.4583 232.406 92.5807 233.141 92.8203 233.859C93.0651 234.578 93.4167 235.232 93.875 235.82C94.3333 236.404 94.8698 236.859 95.4844 237.188L94.7812 238.109C94.1094 237.745 93.526 237.227 93.0312 236.555C92.5417 235.883 92.1641 235.122 91.8984 234.273C91.638 233.424 91.5104 232.552 91.5156 231.656V230.922H92.4531V231.656ZM95.0625 230.969H88.6562V229.953H95.0625V230.969ZM92.4688 230.719H91.2969V227.891H92.4688V230.719ZM100.266 241.266H99.0938V227.375H100.266V241.266ZM97.4531 240.547H96.2969V227.719H97.4531V240.547ZM110.984 231.641C110.984 232.599 110.802 233.544 110.438 234.477C110.073 235.409 109.583 236.237 108.969 236.961C108.359 237.685 107.693 238.229 106.969 238.594L106.234 237.625C106.896 237.307 107.51 236.828 108.078 236.188C108.651 235.542 109.109 234.818 109.453 234.016C109.797 233.214 109.969 232.422 109.969 231.641V229.344H110.984V231.641ZM111.203 231.641C111.203 232.406 111.375 233.169 111.719 233.93C112.063 234.685 112.521 235.359 113.094 235.953C113.667 236.547 114.292 236.99 114.969 237.281L114.281 238.25C113.526 237.906 112.839 237.396 112.219 236.719C111.604 236.042 111.115 235.263 110.75 234.383C110.391 233.497 110.214 232.583 110.219 231.641V229.344H111.203V231.641ZM114.516 229.828H106.688V228.812H114.516V229.828ZM117.688 241.266H116.453V227.375H117.688V241.266ZM126.984 236.391H125.781V234.281H126.984V236.391ZM132.719 234.516H120.078V233.562H132.719V234.516ZM126.984 228.984H125.781V227.297H126.984V228.984ZM126.797 229.312C126.797 230.016 126.542 230.625 126.031 231.141C125.521 231.651 124.836 232.055 123.977 232.352C123.122 232.643 122.167 232.833 121.109 232.922L120.75 231.984C121.667 231.927 122.503 231.784 123.258 231.555C124.013 231.32 124.612 231.013 125.055 230.633C125.497 230.247 125.719 229.807 125.719 229.312V229.109H126.797V229.312ZM127.062 229.312C127.057 229.807 127.276 230.247 127.719 230.633C128.167 231.013 128.766 231.32 129.516 231.555C130.271 231.784 131.109 231.927 132.031 231.984L131.656 232.922C130.604 232.833 129.651 232.643 128.797 232.352C127.943 232.055 127.26 231.651 126.75 231.141C126.24 230.625 125.984 230.016 125.984 229.312V229.109H127.062V229.312ZM131.438 229.562H121.375V228.594H131.438V229.562ZM131.094 238.812H122.844V240.516H121.625V237.938H129.891V236.734H121.594V235.812H131.094V238.812ZM131.516 241.109H121.625V240.172H131.516V241.109ZM149.766 241.266H148.562V227.375H149.766V241.266ZM148.922 234.078H146.203V233.031H148.922V234.078ZM146.562 240.547H145.406V227.688H146.562V240.547ZM139.828 237.078H138.609V229.078H139.828V237.078ZM139.469 236.578C140.297 236.583 141.107 236.555 141.898 236.492C142.695 236.424 143.521 236.302 144.375 236.125L144.531 237.219C143.615 237.385 142.747 237.503 141.93 237.57C141.117 237.638 140.297 237.672 139.469 237.672H138.609V236.578H139.469ZM162.391 230.438H158.141V229.422H162.391V230.438ZM162.391 233.562H158.141V232.547H162.391V233.562ZM163.25 241.266H162.016V237.312H153.906V236.328H163.25V241.266ZM163.25 235.562H162.016V227.375H163.25V235.562ZM155.562 228.172C156.24 228.172 156.852 228.312 157.398 228.594C157.945 228.875 158.372 229.268 158.68 229.773C158.992 230.279 159.151 230.849 159.156 231.484C159.151 232.135 158.992 232.714 158.68 233.219C158.372 233.719 157.945 234.112 157.398 234.398C156.852 234.68 156.24 234.818 155.562 234.812C154.875 234.818 154.258 234.68 153.711 234.398C153.164 234.112 152.734 233.716 152.422 233.211C152.109 232.706 151.953 232.13 151.953 231.484C151.953 230.849 152.109 230.279 152.422 229.773C152.734 229.268 153.164 228.875 153.711 228.594C154.258 228.312 154.875 228.172 155.562 228.172ZM155.562 229.219C155.094 229.219 154.674 229.315 154.305 229.508C153.935 229.701 153.646 229.971 153.438 230.32C153.229 230.664 153.125 231.052 153.125 231.484C153.125 231.927 153.229 232.323 153.438 232.672C153.646 233.016 153.935 233.286 154.305 233.484C154.674 233.682 155.094 233.781 155.562 233.781C156.016 233.781 156.424 233.682 156.789 233.484C157.159 233.286 157.448 233.016 157.656 232.672C157.865 232.323 157.969 231.927 157.969 231.484C157.969 231.057 157.865 230.669 157.656 230.32C157.448 229.971 157.159 229.701 156.789 229.508C156.419 229.315 156.01 229.219 155.562 229.219Z" fill="#B2B1B6"/> +<mask id="mask2_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="215" y="214" width="191" height="40"> +<path d="M215 214H406V254H215V214Z" fill="white"/> +</mask> +<g mask="url(#mask2_1837_11068)"> +<path d="M406 252H215V256H406V252Z" fill="#8425EC"/> +</g> +<path d="M270.586 230.125C270.586 230.964 270.438 231.74 270.141 232.453C269.844 233.167 269.393 233.786 268.789 234.312C268.185 234.833 267.443 235.216 266.562 235.461L265.617 233.914C266.362 233.716 266.987 233.422 267.492 233.031C268.003 232.635 268.38 232.19 268.625 231.695C268.87 231.201 268.992 230.677 268.992 230.125V229.609H270.586V230.125ZM270.969 230.125C270.969 230.63 271.089 231.115 271.328 231.578C271.573 232.036 271.943 232.451 272.438 232.82C272.938 233.19 273.56 233.474 274.305 233.672L273.391 235.211C272.505 234.977 271.76 234.609 271.156 234.109C270.552 233.604 270.099 233.013 269.797 232.336C269.5 231.654 269.352 230.917 269.352 230.125V229.609H270.969V230.125ZM273.836 230.211H266.125V228.641H273.836V230.211ZM270.992 229.328H268.992V227.156H270.992V229.328ZM277.016 235.547H275.023V227.203H277.016V235.547ZM278.938 232.188H276.453V230.555H278.938V232.188ZM277.016 241.281H267.719V236.141H277.016V241.281ZM269.695 239.68H275.047V237.711H269.695V239.68ZM289.922 231.742H285.961V230.141H289.922V231.742ZM289.922 236.148H285.961V234.547H289.922V236.148ZM283.484 228.211C284.193 228.211 284.826 228.419 285.383 228.836C285.945 229.247 286.383 229.839 286.695 230.609C287.008 231.375 287.164 232.266 287.164 233.281C287.164 234.302 287.008 235.198 286.695 235.969C286.383 236.734 285.945 237.323 285.383 237.734C284.826 238.146 284.193 238.352 283.484 238.352C282.766 238.352 282.128 238.146 281.57 237.734C281.013 237.323 280.576 236.734 280.258 235.969C279.94 235.198 279.781 234.302 279.781 233.281C279.781 232.266 279.94 231.375 280.258 230.609C280.576 229.839 281.013 229.247 281.57 228.836C282.128 228.419 282.766 228.211 283.484 228.211ZM283.484 230.016C283.125 230.01 282.812 230.135 282.547 230.391C282.281 230.646 282.073 231.018 281.922 231.508C281.771 231.997 281.698 232.589 281.703 233.281C281.698 233.974 281.771 234.565 281.922 235.055C282.073 235.544 282.281 235.917 282.547 236.172C282.812 236.422 283.125 236.547 283.484 236.547C283.844 236.547 284.159 236.422 284.43 236.172C284.701 235.917 284.909 235.544 285.055 235.055C285.201 234.565 285.273 233.974 285.273 233.281C285.273 232.589 285.201 231.997 285.055 231.508C284.909 231.013 284.701 230.641 284.43 230.391C284.159 230.135 283.844 230.01 283.484 230.016ZM291.562 241.477H289.586V227.203H291.562V241.477ZM298.219 231.086C298.219 232.18 298.062 233.237 297.75 234.258C297.443 235.273 296.987 236.18 296.383 236.977C295.784 237.773 295.065 238.37 294.227 238.766L293.055 237.195C293.82 236.836 294.471 236.328 295.008 235.672C295.549 235.016 295.956 234.292 296.227 233.5C296.497 232.708 296.635 231.904 296.641 231.086V229.43H298.219V231.086ZM298.641 231.086C298.635 231.841 298.766 232.591 299.031 233.336C299.297 234.081 299.69 234.766 300.211 235.391C300.737 236.01 301.375 236.492 302.125 236.836L301.016 238.398C300.177 238.018 299.461 237.448 298.867 236.688C298.279 235.927 297.831 235.062 297.523 234.094C297.216 233.12 297.062 232.117 297.062 231.086V229.43H298.641V231.086ZM301.508 230.219H293.625V228.594H301.508V230.219ZM304.609 241.438H302.609V227.203H304.609V241.438ZM306.719 234.312H304.172V232.648H306.719V234.312ZM321.383 230.516H317.828V229.031H321.383V230.516ZM321.383 233.109H317.828V231.602H321.383V233.109ZM322.898 234.531H320.922V227.203H322.898V234.531ZM322.898 238.859H315.461V240.703H313.453V237.398H320.922V236.594H313.438V235.062H322.898V238.859ZM323.32 241.281H313.453V239.711H323.32V241.281ZM313.531 229.492H316.328V227.82H318.305V234.133H311.523V227.82H313.531V229.492ZM316.328 232.562V230.992H313.531V232.562H316.328ZM338.969 232.297H336.234V230.68H338.969V232.297ZM340.438 235.664H338.453V227.203H340.438V235.664ZM335.578 235.977C336.589 235.977 337.461 236.086 338.195 236.305C338.93 236.523 339.492 236.839 339.883 237.25C340.279 237.656 340.479 238.146 340.484 238.719C340.479 239.286 340.279 239.773 339.883 240.18C339.492 240.591 338.93 240.906 338.195 241.125C337.461 241.344 336.589 241.456 335.578 241.461C334.573 241.456 333.703 241.344 332.969 241.125C332.24 240.906 331.677 240.591 331.281 240.18C330.891 239.773 330.695 239.286 330.695 238.719C330.695 238.146 330.891 237.656 331.281 237.25C331.677 236.839 332.24 236.523 332.969 236.305C333.703 236.086 334.573 235.977 335.578 235.977ZM335.578 237.492C334.943 237.492 334.411 237.539 333.984 237.633C333.557 237.721 333.232 237.857 333.008 238.039C332.784 238.221 332.672 238.448 332.672 238.719C332.672 238.984 332.784 239.208 333.008 239.391C333.232 239.573 333.557 239.711 333.984 239.805C334.417 239.893 334.948 239.938 335.578 239.938C336.214 239.938 336.747 239.893 337.18 239.805C337.617 239.711 337.945 239.573 338.164 239.391C338.383 239.208 338.492 238.984 338.492 238.719C338.492 238.448 338.383 238.221 338.164 238.039C337.945 237.857 337.617 237.721 337.18 237.633C336.747 237.539 336.214 237.492 335.578 237.492ZM333.414 229.578C333.414 230.5 333.266 231.365 332.969 232.172C332.677 232.979 332.229 233.69 331.625 234.305C331.026 234.914 330.286 235.37 329.406 235.672L328.367 234.086C329.122 233.831 329.755 233.466 330.266 232.992C330.781 232.518 331.161 231.99 331.406 231.406C331.656 230.818 331.784 230.208 331.789 229.578V228.641H333.414V229.578ZM333.82 229.562C333.82 230.146 333.938 230.708 334.172 231.25C334.411 231.786 334.776 232.273 335.266 232.711C335.755 233.148 336.365 233.49 337.094 233.734L336.109 235.297C335.25 235.016 334.526 234.589 333.938 234.016C333.354 233.438 332.917 232.768 332.625 232.008C332.339 231.242 332.198 230.427 332.203 229.562V228.641H333.82V229.562ZM336.656 229.68H328.938V228.07H336.656V229.68ZM347.18 229.641C347.18 230.604 347.029 231.495 346.727 232.312C346.43 233.13 345.979 233.844 345.375 234.453C344.776 235.062 344.036 235.516 343.156 235.812L342.047 234.242C342.828 233.997 343.477 233.638 343.992 233.164C344.513 232.69 344.896 232.154 345.141 231.555C345.391 230.951 345.516 230.312 345.516 229.641V228.094H347.18V229.641ZM347.523 229.656C347.523 230.286 347.643 230.883 347.883 231.445C348.128 232.008 348.497 232.513 348.992 232.961C349.492 233.404 350.115 233.745 350.859 233.984L349.812 235.547C348.953 235.26 348.234 234.826 347.656 234.242C347.078 233.659 346.643 232.979 346.352 232.203C346.065 231.422 345.922 230.573 345.922 229.656V228.094H347.523V229.656ZM353.562 237.641H351.57V227.227H353.562V237.641ZM355.484 233.016H352.984V231.344H355.484V233.016ZM354.094 241.195H344.336V239.586H354.094V241.195ZM346.367 240.438H344.336V236.609H346.367V240.438Z" fill="#56555A"/> +<path d="M382 270H48C39.1634 270 32 277.163 32 286V302C32 310.837 39.1634 318 48 318H382C390.837 318 398 310.837 398 302V286C398 277.163 390.837 270 382 270Z" fill="white"/> +<path d="M60.0156 301.297H58.7812V287.375H60.0156V301.297ZM52.625 288.453C53.3125 288.453 53.9245 288.651 54.4609 289.047C54.9974 289.443 55.4167 290.008 55.7188 290.742C56.0208 291.477 56.1719 292.328 56.1719 293.297C56.1719 294.266 56.0208 295.115 55.7188 295.844C55.4167 296.573 54.9974 297.135 54.4609 297.531C53.9245 297.927 53.3125 298.125 52.625 298.125C51.9375 298.125 51.3255 297.927 50.7891 297.531C50.2526 297.135 49.8333 296.573 49.5312 295.844C49.2292 295.115 49.0781 294.266 49.0781 293.297C49.0781 292.328 49.2292 291.477 49.5312 290.742C49.8333 290.008 50.2526 289.443 50.7891 289.047C51.3255 288.651 51.9375 288.453 52.625 288.453ZM52.625 289.547C52.1667 289.547 51.7578 289.703 51.3984 290.016C51.0391 290.328 50.7604 290.768 50.5625 291.336C50.3646 291.904 50.2656 292.557 50.2656 293.297C50.2656 294.042 50.3646 294.698 50.5625 295.266C50.7604 295.828 51.0391 296.263 51.3984 296.57C51.7578 296.878 52.1667 297.031 52.625 297.031C53.0885 297.031 53.4974 296.878 53.8516 296.57C54.2109 296.263 54.4896 295.828 54.6875 295.266C54.8854 294.698 54.9844 294.042 54.9844 293.297C54.9844 292.552 54.8854 291.898 54.6875 291.336C54.4896 290.768 54.2109 290.328 53.8516 290.016C53.4974 289.703 53.0885 289.547 52.625 289.547ZM75.0938 295.562H62.375V294.547H75.0938V295.562ZM73.4531 291H65.25V292.844H64.0312V290.078H72.2188V288.703H63.9844V287.719H73.4531V291ZM73.75 293.344H64.0312V292.391H73.75V293.344ZM73.4531 301.078H64.1094V296.828H73.4531V301.078ZM65.3125 300.078H72.25V297.828H65.3125V300.078ZM87.4062 288.281C87.4062 289.427 87.1458 290.466 86.625 291.398C86.1042 292.331 85.3568 293.135 84.3828 293.812C83.4089 294.49 82.25 295.021 80.9062 295.406L80.3906 294.438C81.5729 294.104 82.5938 293.661 83.4531 293.109C84.3177 292.557 84.9792 291.917 85.4375 291.188C85.8958 290.458 86.125 289.667 86.125 288.812V288.281H87.4062ZM86.9375 289.297H81.1094V288.281H86.9375V289.297ZM91.75 295.312H90.5156V287.391H91.75V295.312ZM90.75 292H87.4375V290.969H90.75V292ZM91.75 301.078H82.7344V295.906H91.75V301.078ZM83.9219 300.078H90.5312V296.891H83.9219V300.078ZM98.0156 290.094C98.0104 290.792 97.875 291.482 97.6094 292.164C97.349 292.846 96.9714 293.461 96.4766 294.008C95.987 294.555 95.4115 294.974 94.75 295.266L94.0781 294.312C94.6719 294.052 95.1927 293.69 95.6406 293.227C96.0885 292.763 96.4297 292.258 96.6641 291.711C96.9036 291.164 97.026 290.625 97.0312 290.094V288.234H98.0156V290.094ZM98.2031 290.094C98.2083 290.625 98.3229 291.143 98.5469 291.648C98.776 292.154 99.1042 292.612 99.5312 293.023C99.9635 293.43 100.469 293.745 101.047 293.969L100.391 294.922C99.7344 294.656 99.1693 294.276 98.6953 293.781C98.2214 293.281 97.8568 292.716 97.6016 292.086C97.3516 291.451 97.2292 290.786 97.2344 290.094V288.234H98.2031V290.094ZM105.859 295.781H104.688V287.391H105.859V295.781ZM105.063 292.047H102.391V291.016H105.063V292.047ZM102.844 295.703H101.688V287.641H102.844V295.703ZM105.859 301.266H104.656V297.562H96.5V296.547H105.859V301.266Z" fill="#B2B1B6"/> +<path d="M373.977 296.472H373.187L372.907 296.202C373.532 295.476 373.989 294.621 374.245 293.698C374.5 292.775 374.549 291.806 374.387 290.862C373.917 288.082 371.597 285.862 368.797 285.522C367.813 285.398 366.813 285.5 365.874 285.821C364.935 286.143 364.082 286.674 363.381 287.376C362.679 288.078 362.147 288.93 361.826 289.869C361.505 290.808 361.402 291.808 361.527 292.792C361.867 295.592 364.087 297.912 366.867 298.382C367.811 298.544 368.779 298.496 369.703 298.24C370.626 297.984 371.481 297.527 372.207 296.902L372.477 297.182V297.972L376.727 302.222C377.137 302.632 377.807 302.632 378.217 302.222C378.627 301.812 378.627 301.142 378.217 300.732L373.977 296.472ZM367.977 296.472C365.487 296.472 363.477 294.462 363.477 291.972C363.477 289.482 365.487 287.472 367.977 287.472C370.467 287.472 372.477 289.482 372.477 291.972C372.477 294.462 370.467 296.472 367.977 296.472Z" fill="#B2B1B6"/> +<path d="M382 326H48C39.1634 326 32 333.163 32 342V702C32 710.837 39.1634 718 48 718H382C390.837 718 398 710.837 398 702V342C398 333.163 390.837 326 382 326Z" fill="white"/> +<path d="M390 334H40C35.5817 334 32 337.582 32 342V366C32 370.418 35.5817 374 40 374H390C394.418 374 398 370.418 398 366V342C398 337.582 394.418 334 390 334Z" fill="white"/> +<path d="M60.4062 357.633H58.4219V347.234H60.4062V357.633ZM58.7031 352.977H55.875V351.352H58.7031V352.977ZM56.0078 348.273C56.0026 349.539 55.7422 350.693 55.2266 351.734C54.7109 352.771 53.9609 353.669 52.9766 354.43C51.9922 355.185 50.8073 355.779 49.4219 356.211L48.6016 354.617C49.6953 354.273 50.638 353.831 51.4297 353.289C52.2266 352.742 52.8333 352.12 53.25 351.422C53.6719 350.724 53.8854 349.974 53.8906 349.172V348.273H56.0078ZM55.1641 349.906H49.3438V348.273H55.1641V349.906ZM60.7734 361.195H51.0234V359.586H60.7734V361.195ZM53.0469 360.508H51.0234V356.57H53.0469V360.508ZM67.0547 349.258C67.0547 350.227 66.9089 351.125 66.6172 351.953C66.3307 352.781 65.8932 353.503 65.3047 354.117C64.7161 354.727 63.987 355.18 63.1172 355.477L62.0469 353.914C62.8073 353.654 63.4401 353.286 63.9453 352.812C64.4505 352.333 64.8229 351.792 65.0625 351.188C65.3021 350.583 65.4245 349.94 65.4297 349.258V347.969H67.0547V349.258ZM67.4297 349.453C67.4297 350.052 67.5469 350.617 67.7812 351.148C68.0208 351.68 68.3828 352.154 68.8672 352.57C69.3568 352.982 69.9635 353.302 70.6875 353.531L69.625 355.078C68.7917 354.802 68.0911 354.388 67.5234 353.836C66.9557 353.279 66.5286 352.628 66.2422 351.883C65.9557 351.138 65.8151 350.328 65.8203 349.453V347.969H67.4297V349.453ZM73.5312 355.648H71.5391V347.203H73.5312V355.648ZM75.4531 352.203H72.9688V350.539H75.4531V352.203ZM68.8672 355.938C69.8464 355.938 70.6953 356.047 71.4141 356.266C72.138 356.479 72.6927 356.794 73.0781 357.211C73.4688 357.622 73.6641 358.112 73.6641 358.68C73.6641 359.258 73.4688 359.753 73.0781 360.164C72.6927 360.576 72.138 360.891 71.4141 361.109C70.6953 361.328 69.8464 361.438 68.8672 361.438C67.8724 361.438 67.0078 361.328 66.2734 361.109C65.5443 360.891 64.9818 360.576 64.5859 360.164C64.1901 359.753 63.9922 359.258 63.9922 358.68C63.9922 358.112 64.1901 357.622 64.5859 357.211C64.9818 356.794 65.5443 356.479 66.2734 356.266C67.0078 356.047 67.8724 355.938 68.8672 355.938ZM68.8672 357.5C68.2474 357.495 67.724 357.539 67.2969 357.633C66.8698 357.721 66.5443 357.854 66.3203 358.031C66.1016 358.208 65.9948 358.424 66 358.68C65.9948 358.945 66.1016 359.167 66.3203 359.344C66.5391 359.521 66.8594 359.654 67.2812 359.742C67.7083 359.831 68.237 359.875 68.8672 359.875C69.487 359.875 70.0078 359.831 70.4297 359.742C70.8516 359.654 71.1693 359.521 71.3828 359.344C71.5964 359.167 71.7031 358.945 71.7031 358.68C71.7031 358.424 71.5938 358.208 71.375 358.031C71.1615 357.849 70.8438 357.714 70.4219 357.625C70 357.536 69.4818 357.495 68.8672 357.5Z" fill="#56555A"/> +<path d="M288.781 356.531L293.875 348.688H294.719V350.469H294.125L290.297 356.359V356.453H297.188V357.688H288.781V356.531ZM294.266 357.344V356.797V348.688H295.609V360H294.266V357.344ZM302.812 348.531C303.531 348.542 304.201 348.714 304.82 349.047C305.44 349.38 305.945 349.945 306.336 350.742C306.727 351.534 306.922 352.583 306.922 353.891C306.922 355.214 306.75 356.344 306.406 357.281C306.062 358.219 305.568 358.932 304.922 359.422C304.276 359.911 303.51 360.156 302.625 360.156C301.969 360.156 301.38 360.029 300.859 359.773C300.339 359.518 299.914 359.167 299.586 358.719C299.258 358.266 299.047 357.74 298.953 357.141H300.344C300.427 357.49 300.57 357.797 300.773 358.062C300.977 358.323 301.234 358.529 301.547 358.68C301.859 358.831 302.219 358.906 302.625 358.906C303.24 358.906 303.771 358.734 304.219 358.391C304.667 358.047 305.008 357.552 305.242 356.906C305.482 356.255 305.604 355.474 305.609 354.562H305.453C305.234 354.875 304.977 355.143 304.68 355.367C304.383 355.591 304.055 355.763 303.695 355.883C303.336 356.003 302.958 356.062 302.562 356.062C301.891 356.062 301.271 355.901 300.703 355.578C300.141 355.255 299.693 354.81 299.359 354.242C299.026 353.674 298.859 353.036 298.859 352.328C298.859 351.625 299.023 350.984 299.352 350.406C299.68 349.823 300.143 349.365 300.742 349.031C301.341 348.693 302.031 348.526 302.812 348.531ZM302.812 349.766C302.328 349.766 301.888 349.88 301.492 350.109C301.102 350.339 300.792 350.648 300.562 351.039C300.339 351.43 300.229 351.854 300.234 352.312C300.234 352.776 300.344 353.201 300.562 353.586C300.781 353.966 301.081 354.268 301.461 354.492C301.846 354.716 302.281 354.828 302.766 354.828C303.245 354.828 303.685 354.708 304.086 354.469C304.487 354.229 304.805 353.914 305.039 353.523C305.273 353.133 305.391 352.719 305.391 352.281C305.391 351.849 305.279 351.44 305.055 351.055C304.831 350.664 304.521 350.352 304.125 350.117C303.734 349.883 303.297 349.766 302.812 349.766ZM309.016 363.203H307.859L308.719 358.953H310.234L309.016 363.203ZM316 360.156C315.219 360.156 314.523 360.021 313.914 359.75C313.305 359.479 312.831 359.104 312.492 358.625C312.154 358.146 311.984 357.604 311.984 357C311.984 356.521 312.086 356.073 312.289 355.656C312.492 355.24 312.768 354.898 313.117 354.633C313.466 354.362 313.854 354.193 314.281 354.125V354.062C313.911 353.979 313.586 353.815 313.305 353.57C313.029 353.326 312.812 353.026 312.656 352.672C312.5 352.318 312.422 351.938 312.422 351.531C312.422 350.964 312.576 350.453 312.883 350C313.19 349.542 313.615 349.182 314.156 348.922C314.703 348.661 315.318 348.531 316 348.531C316.677 348.531 317.289 348.661 317.836 348.922C318.383 349.182 318.81 349.542 319.117 350C319.43 350.453 319.589 350.964 319.594 351.531C319.589 351.938 319.505 352.318 319.344 352.672C319.188 353.026 318.969 353.326 318.688 353.57C318.406 353.815 318.083 353.979 317.719 354.062V354.125C318.141 354.193 318.526 354.362 318.875 354.633C319.229 354.898 319.508 355.24 319.711 355.656C319.919 356.073 320.026 356.521 320.031 357C320.026 357.604 319.852 358.146 319.508 358.625C319.169 359.104 318.693 359.479 318.078 359.75C317.469 360.021 316.776 360.156 316 360.156ZM316 358.922C316.531 358.922 316.995 358.836 317.391 358.664C317.786 358.492 318.091 358.258 318.305 357.961C318.518 357.664 318.625 357.318 318.625 356.922C318.625 356.51 318.513 356.141 318.289 355.812C318.065 355.479 317.753 355.219 317.352 355.031C316.951 354.844 316.5 354.75 316 354.75C315.5 354.75 315.052 354.844 314.656 355.031C314.26 355.219 313.948 355.479 313.719 355.812C313.495 356.141 313.385 356.51 313.391 356.922C313.385 357.318 313.487 357.664 313.695 357.961C313.909 358.258 314.211 358.492 314.602 358.664C314.997 358.836 315.464 358.922 316 358.922ZM316 353.562C316.427 353.562 316.81 353.479 317.148 353.312C317.487 353.146 317.75 352.919 317.938 352.633C318.125 352.346 318.219 352.016 318.219 351.641C318.219 351.266 318.128 350.935 317.945 350.648C317.763 350.362 317.503 350.141 317.164 349.984C316.826 349.828 316.438 349.75 316 349.75C315.557 349.75 315.169 349.828 314.836 349.984C314.508 350.141 314.25 350.362 314.062 350.648C313.875 350.935 313.781 351.266 313.781 351.641C313.781 352.016 313.878 352.346 314.07 352.633C314.263 352.919 314.526 353.146 314.859 353.312C315.193 353.479 315.573 353.562 316 353.562ZM325.609 360.156C324.938 360.156 324.326 360.026 323.773 359.766C323.227 359.505 322.789 359.148 322.461 358.695C322.138 358.242 321.964 357.729 321.938 357.156H323.297C323.328 357.49 323.451 357.789 323.664 358.055C323.878 358.32 324.154 358.531 324.492 358.688C324.836 358.844 325.208 358.922 325.609 358.922C326.094 358.922 326.526 358.812 326.906 358.594C327.292 358.375 327.594 358.076 327.812 357.695C328.031 357.315 328.141 356.891 328.141 356.422C328.141 355.938 328.029 355.503 327.805 355.117C327.581 354.727 327.268 354.419 326.867 354.195C326.466 353.971 326.016 353.859 325.516 353.859C325.021 353.849 324.596 353.927 324.242 354.094C323.888 354.255 323.609 354.516 323.406 354.875H322.047L322.844 348.688H328.969V349.938H324.016L323.594 353.25H323.703C323.964 353.052 324.273 352.893 324.633 352.773C324.997 352.654 325.375 352.594 325.766 352.594C326.474 352.594 327.115 352.755 327.688 353.078C328.26 353.401 328.708 353.854 329.031 354.438C329.354 355.016 329.516 355.667 329.516 356.391C329.516 357.109 329.346 357.755 329.008 358.328C328.669 358.901 328.203 359.349 327.609 359.672C327.021 359.995 326.354 360.156 325.609 360.156ZM335.172 360.156C334.339 360.156 333.628 359.93 333.039 359.477C332.451 359.023 332 358.362 331.688 357.492C331.375 356.622 331.219 355.573 331.219 354.344C331.219 353.13 331.375 352.089 331.688 351.219C332 350.344 332.451 349.677 333.039 349.219C333.633 348.76 334.344 348.531 335.172 348.531C335.995 348.531 336.703 348.76 337.297 349.219C337.891 349.677 338.344 350.344 338.656 351.219C338.969 352.089 339.125 353.13 339.125 354.344C339.125 355.573 338.971 356.622 338.664 357.492C338.357 358.362 337.906 359.023 337.312 359.477C336.719 359.93 336.005 360.156 335.172 360.156ZM335.172 358.906C335.714 358.906 336.18 358.729 336.57 358.375C336.961 358.021 337.255 357.503 337.453 356.82C337.651 356.138 337.75 355.312 337.75 354.344C337.75 353.375 337.648 352.547 337.445 351.859C337.242 351.172 336.948 350.648 336.562 350.289C336.177 349.93 335.714 349.75 335.172 349.75C334.63 349.75 334.167 349.93 333.781 350.289C333.396 350.648 333.099 351.172 332.891 351.859C332.682 352.547 332.578 353.375 332.578 354.344C332.578 355.312 332.682 356.138 332.891 356.82C333.099 357.503 333.393 358.021 333.773 358.375C334.159 358.729 334.625 358.906 335.172 358.906ZM349.75 357.453H348.516V354.359H349.75V357.453ZM355.969 357.938H354.734V347.391H355.969V357.938ZM356.312 360.969H346.438V359.938H356.312V360.969ZM347.672 360.234H346.438V356.906H347.672V360.234ZM344.438 353.828C346.297 353.818 347.943 353.789 349.375 353.742C350.807 353.69 352.177 353.583 353.484 353.422L353.562 354.312C352.214 354.526 350.799 354.667 349.32 354.734C347.841 354.802 346.271 354.833 344.609 354.828L344.438 353.828ZM355.062 356.5H351.859V355.609H355.062V356.5ZM349 347.953C349.672 347.953 350.268 348.052 350.789 348.25C351.315 348.448 351.721 348.732 352.008 349.102C352.294 349.471 352.438 349.896 352.438 350.375C352.438 350.865 352.294 351.289 352.008 351.648C351.721 352.008 351.318 352.286 350.797 352.484C350.276 352.682 349.677 352.781 349 352.781C348.318 352.781 347.716 352.682 347.195 352.484C346.68 352.286 346.279 352.008 345.992 351.648C345.706 351.289 345.562 350.865 345.562 350.375C345.562 349.896 345.706 349.471 345.992 349.102C346.279 348.732 346.682 348.448 347.203 348.25C347.724 348.052 348.323 347.953 349 347.953ZM349 348.891C348.552 348.885 348.156 348.945 347.812 349.07C347.469 349.19 347.201 349.365 347.008 349.594C346.82 349.823 346.729 350.083 346.734 350.375C346.729 350.672 346.82 350.935 347.008 351.164C347.201 351.388 347.469 351.562 347.812 351.688C348.156 351.812 348.552 351.875 349 351.875C349.438 351.875 349.828 351.812 350.172 351.688C350.516 351.562 350.784 351.388 350.977 351.164C351.169 350.935 351.266 350.672 351.266 350.375C351.266 350.083 351.169 349.823 350.977 349.594C350.784 349.365 350.516 349.19 350.172 349.07C349.828 348.945 349.438 348.885 349 348.891Z" fill="#56555A"/> +<path d="M376 350L380 354L376 358" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +<path d="M390 382H40C35.5817 382 32 385.582 32 390V414C32 418.418 35.5817 422 40 422H390C394.418 422 398 418.418 398 414V390C398 385.582 394.418 382 390 382Z" fill="white"/> +<path d="M55.4922 397.227C55.4922 398.07 55.2656 398.841 54.8125 399.539C54.3646 400.232 53.7109 400.815 52.8516 401.289C51.9922 401.758 50.974 402.073 49.7969 402.234L49.0547 400.68C50.0495 400.56 50.901 400.323 51.6094 399.969C52.3229 399.609 52.8594 399.193 53.2188 398.719C53.5781 398.24 53.7578 397.742 53.7578 397.227V396.797H55.4922V397.227ZM56.0625 397.227C56.0625 397.742 56.2396 398.24 56.5938 398.719C56.9531 399.193 57.487 399.609 58.1953 399.969C58.9089 400.323 59.7708 400.56 60.7812 400.68L60.0625 402.234C58.875 402.073 57.849 401.758 56.9844 401.289C56.1198 400.815 55.4609 400.232 55.0078 399.539C54.5547 398.841 54.3281 398.07 54.3281 397.227V396.797H56.0625V397.227ZM55.8594 409.445H53.8828V404.203H55.8594V409.445ZM61.3984 404.656H48.4297V403.07H61.3984V404.656ZM60.2266 397.523H49.5938V395.969H60.2266V397.523ZM73.625 406.32H71.6172V395.203H73.625V406.32ZM75.4453 401.531H72.9141V399.891H75.4453V401.531ZM74.1094 409.195H64.0859V407.586H74.1094V409.195ZM66.1016 408.062H64.0859V405.586H66.1016V408.062ZM67.5312 404.125H65.5469V402.039H67.5312V404.125ZM62.1016 403.391C63.7474 403.391 65.3099 403.359 66.7891 403.297C68.2682 403.229 69.6589 403.102 70.9609 402.914L71.1094 404.281C69.8594 404.521 68.5703 404.682 67.2422 404.766C65.9141 404.849 64.401 404.904 62.7031 404.93C62.625 404.93 62.5573 404.93 62.5 404.93C62.4427 404.93 62.375 404.93 62.2969 404.93L62.1016 403.391ZM70.6016 397.805H62.4609V396.367H70.6016V397.805ZM66.5312 398.195C67.224 398.195 67.8333 398.284 68.3594 398.461C68.8854 398.633 69.2917 398.888 69.5781 399.227C69.8646 399.56 70.0104 399.958 70.0156 400.422C70.0104 400.859 69.8646 401.242 69.5781 401.57C69.2917 401.893 68.8854 402.146 68.3594 402.328C67.8333 402.505 67.224 402.594 66.5312 402.594C65.8333 402.594 65.2214 402.505 64.6953 402.328C64.1693 402.151 63.7604 401.901 63.4688 401.578C63.1823 401.25 63.0391 400.865 63.0391 400.422C63.0391 399.958 63.1823 399.56 63.4688 399.227C63.7604 398.888 64.1667 398.633 64.6875 398.461C65.2135 398.284 65.8281 398.195 66.5312 398.195ZM66.5312 399.531C66.1875 399.531 65.8984 399.562 65.6641 399.625C65.4297 399.688 65.25 399.786 65.125 399.922C65.0052 400.057 64.9453 400.224 64.9453 400.422C64.9453 400.594 65.0052 400.745 65.125 400.875C65.25 401 65.4297 401.096 65.6641 401.164C65.9036 401.227 66.1927 401.258 66.5312 401.258C66.8594 401.258 67.1406 401.227 67.375 401.164C67.6146 401.096 67.7943 401 67.9141 400.875C68.0391 400.745 68.1016 400.594 68.1016 400.422C68.1016 400.224 68.0417 400.057 67.9219 399.922C67.8021 399.786 67.6224 399.688 67.3828 399.625C67.1484 399.562 66.8646 399.531 66.5312 399.531ZM67.5312 397.008H65.5469V395.164H67.5312V397.008Z" fill="#56555A"/> +<path d="M288.781 404.531L293.875 396.688H294.719V398.469H294.125L290.297 404.359V404.453H297.188V405.688H288.781V404.531ZM294.266 405.344V404.797V396.688H295.609V408H294.266V405.344ZM302.812 396.531C303.531 396.542 304.201 396.714 304.82 397.047C305.44 397.38 305.945 397.945 306.336 398.742C306.727 399.534 306.922 400.583 306.922 401.891C306.922 403.214 306.75 404.344 306.406 405.281C306.062 406.219 305.568 406.932 304.922 407.422C304.276 407.911 303.51 408.156 302.625 408.156C301.969 408.156 301.38 408.029 300.859 407.773C300.339 407.518 299.914 407.167 299.586 406.719C299.258 406.266 299.047 405.74 298.953 405.141H300.344C300.427 405.49 300.57 405.797 300.773 406.062C300.977 406.323 301.234 406.529 301.547 406.68C301.859 406.831 302.219 406.906 302.625 406.906C303.24 406.906 303.771 406.734 304.219 406.391C304.667 406.047 305.008 405.552 305.242 404.906C305.482 404.255 305.604 403.474 305.609 402.562H305.453C305.234 402.875 304.977 403.143 304.68 403.367C304.383 403.591 304.055 403.763 303.695 403.883C303.336 404.003 302.958 404.062 302.562 404.062C301.891 404.062 301.271 403.901 300.703 403.578C300.141 403.255 299.693 402.81 299.359 402.242C299.026 401.674 298.859 401.036 298.859 400.328C298.859 399.625 299.023 398.984 299.352 398.406C299.68 397.823 300.143 397.365 300.742 397.031C301.341 396.693 302.031 396.526 302.812 396.531ZM302.812 397.766C302.328 397.766 301.888 397.88 301.492 398.109C301.102 398.339 300.792 398.648 300.562 399.039C300.339 399.43 300.229 399.854 300.234 400.312C300.234 400.776 300.344 401.201 300.562 401.586C300.781 401.966 301.081 402.268 301.461 402.492C301.846 402.716 302.281 402.828 302.766 402.828C303.245 402.828 303.685 402.708 304.086 402.469C304.487 402.229 304.805 401.914 305.039 401.523C305.273 401.133 305.391 400.719 305.391 400.281C305.391 399.849 305.279 399.44 305.055 399.055C304.831 398.664 304.521 398.352 304.125 398.117C303.734 397.883 303.297 397.766 302.812 397.766ZM309.016 411.203H307.859L308.719 406.953H310.234L309.016 411.203ZM316 408.156C315.219 408.156 314.523 408.021 313.914 407.75C313.305 407.479 312.831 407.104 312.492 406.625C312.154 406.146 311.984 405.604 311.984 405C311.984 404.521 312.086 404.073 312.289 403.656C312.492 403.24 312.768 402.898 313.117 402.633C313.466 402.362 313.854 402.193 314.281 402.125V402.062C313.911 401.979 313.586 401.815 313.305 401.57C313.029 401.326 312.812 401.026 312.656 400.672C312.5 400.318 312.422 399.938 312.422 399.531C312.422 398.964 312.576 398.453 312.883 398C313.19 397.542 313.615 397.182 314.156 396.922C314.703 396.661 315.318 396.531 316 396.531C316.677 396.531 317.289 396.661 317.836 396.922C318.383 397.182 318.81 397.542 319.117 398C319.43 398.453 319.589 398.964 319.594 399.531C319.589 399.938 319.505 400.318 319.344 400.672C319.188 401.026 318.969 401.326 318.688 401.57C318.406 401.815 318.083 401.979 317.719 402.062V402.125C318.141 402.193 318.526 402.362 318.875 402.633C319.229 402.898 319.508 403.24 319.711 403.656C319.919 404.073 320.026 404.521 320.031 405C320.026 405.604 319.852 406.146 319.508 406.625C319.169 407.104 318.693 407.479 318.078 407.75C317.469 408.021 316.776 408.156 316 408.156ZM316 406.922C316.531 406.922 316.995 406.836 317.391 406.664C317.786 406.492 318.091 406.258 318.305 405.961C318.518 405.664 318.625 405.318 318.625 404.922C318.625 404.51 318.513 404.141 318.289 403.812C318.065 403.479 317.753 403.219 317.352 403.031C316.951 402.844 316.5 402.75 316 402.75C315.5 402.75 315.052 402.844 314.656 403.031C314.26 403.219 313.948 403.479 313.719 403.812C313.495 404.141 313.385 404.51 313.391 404.922C313.385 405.318 313.487 405.664 313.695 405.961C313.909 406.258 314.211 406.492 314.602 406.664C314.997 406.836 315.464 406.922 316 406.922ZM316 401.562C316.427 401.562 316.81 401.479 317.148 401.312C317.487 401.146 317.75 400.919 317.938 400.633C318.125 400.346 318.219 400.016 318.219 399.641C318.219 399.266 318.128 398.935 317.945 398.648C317.763 398.362 317.503 398.141 317.164 397.984C316.826 397.828 316.438 397.75 316 397.75C315.557 397.75 315.169 397.828 314.836 397.984C314.508 398.141 314.25 398.362 314.062 398.648C313.875 398.935 313.781 399.266 313.781 399.641C313.781 400.016 313.878 400.346 314.07 400.633C314.263 400.919 314.526 401.146 314.859 401.312C315.193 401.479 315.573 401.562 316 401.562ZM325.609 408.156C324.938 408.156 324.326 408.026 323.773 407.766C323.227 407.505 322.789 407.148 322.461 406.695C322.138 406.242 321.964 405.729 321.938 405.156H323.297C323.328 405.49 323.451 405.789 323.664 406.055C323.878 406.32 324.154 406.531 324.492 406.688C324.836 406.844 325.208 406.922 325.609 406.922C326.094 406.922 326.526 406.812 326.906 406.594C327.292 406.375 327.594 406.076 327.812 405.695C328.031 405.315 328.141 404.891 328.141 404.422C328.141 403.938 328.029 403.503 327.805 403.117C327.581 402.727 327.268 402.419 326.867 402.195C326.466 401.971 326.016 401.859 325.516 401.859C325.021 401.849 324.596 401.927 324.242 402.094C323.888 402.255 323.609 402.516 323.406 402.875H322.047L322.844 396.688H328.969V397.938H324.016L323.594 401.25H323.703C323.964 401.052 324.273 400.893 324.633 400.773C324.997 400.654 325.375 400.594 325.766 400.594C326.474 400.594 327.115 400.755 327.688 401.078C328.26 401.401 328.708 401.854 329.031 402.438C329.354 403.016 329.516 403.667 329.516 404.391C329.516 405.109 329.346 405.755 329.008 406.328C328.669 406.901 328.203 407.349 327.609 407.672C327.021 407.995 326.354 408.156 325.609 408.156ZM335.172 408.156C334.339 408.156 333.628 407.93 333.039 407.477C332.451 407.023 332 406.362 331.688 405.492C331.375 404.622 331.219 403.573 331.219 402.344C331.219 401.13 331.375 400.089 331.688 399.219C332 398.344 332.451 397.677 333.039 397.219C333.633 396.76 334.344 396.531 335.172 396.531C335.995 396.531 336.703 396.76 337.297 397.219C337.891 397.677 338.344 398.344 338.656 399.219C338.969 400.089 339.125 401.13 339.125 402.344C339.125 403.573 338.971 404.622 338.664 405.492C338.357 406.362 337.906 407.023 337.312 407.477C336.719 407.93 336.005 408.156 335.172 408.156ZM335.172 406.906C335.714 406.906 336.18 406.729 336.57 406.375C336.961 406.021 337.255 405.503 337.453 404.82C337.651 404.138 337.75 403.312 337.75 402.344C337.75 401.375 337.648 400.547 337.445 399.859C337.242 399.172 336.948 398.648 336.562 398.289C336.177 397.93 335.714 397.75 335.172 397.75C334.63 397.75 334.167 397.93 333.781 398.289C333.396 398.648 333.099 399.172 332.891 399.859C332.682 400.547 332.578 401.375 332.578 402.344C332.578 403.312 332.682 404.138 332.891 404.82C333.099 405.503 333.393 406.021 333.773 406.375C334.159 406.729 334.625 406.906 335.172 406.906ZM349.75 405.453H348.516V402.359H349.75V405.453ZM355.969 405.938H354.734V395.391H355.969V405.938ZM356.312 408.969H346.438V407.938H356.312V408.969ZM347.672 408.234H346.438V404.906H347.672V408.234ZM344.438 401.828C346.297 401.818 347.943 401.789 349.375 401.742C350.807 401.69 352.177 401.583 353.484 401.422L353.562 402.312C352.214 402.526 350.799 402.667 349.32 402.734C347.841 402.802 346.271 402.833 344.609 402.828L344.438 401.828ZM355.062 404.5H351.859V403.609H355.062V404.5ZM349 395.953C349.672 395.953 350.268 396.052 350.789 396.25C351.315 396.448 351.721 396.732 352.008 397.102C352.294 397.471 352.438 397.896 352.438 398.375C352.438 398.865 352.294 399.289 352.008 399.648C351.721 400.008 351.318 400.286 350.797 400.484C350.276 400.682 349.677 400.781 349 400.781C348.318 400.781 347.716 400.682 347.195 400.484C346.68 400.286 346.279 400.008 345.992 399.648C345.706 399.289 345.562 398.865 345.562 398.375C345.562 397.896 345.706 397.471 345.992 397.102C346.279 396.732 346.682 396.448 347.203 396.25C347.724 396.052 348.323 395.953 349 395.953ZM349 396.891C348.552 396.885 348.156 396.945 347.812 397.07C347.469 397.19 347.201 397.365 347.008 397.594C346.82 397.823 346.729 398.083 346.734 398.375C346.729 398.672 346.82 398.935 347.008 399.164C347.201 399.388 347.469 399.562 347.812 399.688C348.156 399.812 348.552 399.875 349 399.875C349.438 399.875 349.828 399.812 350.172 399.688C350.516 399.562 350.784 399.388 350.977 399.164C351.169 398.935 351.266 398.672 351.266 398.375C351.266 398.083 351.169 397.823 350.977 397.594C350.784 397.365 350.516 397.19 350.172 397.07C349.828 396.945 349.438 396.885 349 396.891Z" fill="#56555A"/> +<path d="M376 398L380 402L376 406" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +<path d="M390 430H40C35.5817 430 32 433.582 32 438V462C32 466.418 35.5817 470 40 470H390C394.418 470 398 466.418 398 462V438C398 433.582 394.418 430 390 430Z" fill="white"/> +<path d="M60.8125 446.609H48.9766V445.016H60.8125V446.609ZM61.4297 455.992H48.4297V454.383H61.4297V455.992ZM55.875 455.008H53.8984V452.469H55.875V455.008ZM54.8906 447.227C55.8698 447.227 56.724 447.336 57.4531 447.555C58.1875 447.773 58.75 448.094 59.1406 448.516C59.5365 448.932 59.7344 449.424 59.7344 449.992C59.7344 450.57 59.5365 451.07 59.1406 451.492C58.75 451.909 58.1901 452.232 57.4609 452.461C56.7318 452.685 55.875 452.799 54.8906 452.805C53.8906 452.799 53.026 452.685 52.2969 452.461C51.5677 452.232 51.0052 451.909 50.6094 451.492C50.2188 451.07 50.026 450.57 50.0312 449.992C50.026 449.419 50.2188 448.924 50.6094 448.508C51.0052 448.091 51.5677 447.773 52.2969 447.555C53.0312 447.336 53.8958 447.227 54.8906 447.227ZM54.8906 448.781C54.2656 448.786 53.7448 448.833 53.3281 448.922C52.9167 449.005 52.6042 449.138 52.3906 449.32C52.1771 449.497 52.0729 449.721 52.0781 449.992C52.0729 450.263 52.1771 450.49 52.3906 450.672C52.6042 450.849 52.9167 450.984 53.3281 451.078C53.7448 451.167 54.2656 451.211 54.8906 451.211C55.5 451.211 56.0104 451.167 56.4219 451.078C56.8385 450.984 57.1536 450.849 57.3672 450.672C57.5807 450.49 57.6875 450.263 57.6875 449.992C57.6875 449.721 57.5807 449.497 57.3672 449.32C57.1536 449.138 56.8385 449.005 56.4219 448.922C56.0104 448.833 55.5 448.786 54.8906 448.781ZM55.875 446.008H53.8984V443.359H55.875V446.008ZM74.2344 453.633H72.25V443.234H74.2344V453.633ZM72.5312 448.977H69.7031V447.352H72.5312V448.977ZM69.8359 444.273C69.8307 445.539 69.5703 446.693 69.0547 447.734C68.5391 448.771 67.7891 449.669 66.8047 450.43C65.8203 451.185 64.6354 451.779 63.25 452.211L62.4297 450.617C63.5234 450.273 64.4661 449.831 65.2578 449.289C66.0547 448.742 66.6615 448.12 67.0781 447.422C67.5 446.724 67.7135 445.974 67.7188 445.172V444.273H69.8359ZM68.9922 445.906H63.1719V444.273H68.9922V445.906ZM74.6016 457.195H64.8516V455.586H74.6016V457.195ZM66.875 456.508H64.8516V452.57H66.875V456.508Z" fill="#56555A"/> +<path d="M288.781 452.531L293.875 444.688H294.719V446.469H294.125L290.297 452.359V452.453H297.188V453.688H288.781V452.531ZM294.266 453.344V452.797V444.688H295.609V456H294.266V453.344ZM302.812 444.531C303.531 444.542 304.201 444.714 304.82 445.047C305.44 445.38 305.945 445.945 306.336 446.742C306.727 447.534 306.922 448.583 306.922 449.891C306.922 451.214 306.75 452.344 306.406 453.281C306.062 454.219 305.568 454.932 304.922 455.422C304.276 455.911 303.51 456.156 302.625 456.156C301.969 456.156 301.38 456.029 300.859 455.773C300.339 455.518 299.914 455.167 299.586 454.719C299.258 454.266 299.047 453.74 298.953 453.141H300.344C300.427 453.49 300.57 453.797 300.773 454.062C300.977 454.323 301.234 454.529 301.547 454.68C301.859 454.831 302.219 454.906 302.625 454.906C303.24 454.906 303.771 454.734 304.219 454.391C304.667 454.047 305.008 453.552 305.242 452.906C305.482 452.255 305.604 451.474 305.609 450.562H305.453C305.234 450.875 304.977 451.143 304.68 451.367C304.383 451.591 304.055 451.763 303.695 451.883C303.336 452.003 302.958 452.062 302.562 452.062C301.891 452.062 301.271 451.901 300.703 451.578C300.141 451.255 299.693 450.81 299.359 450.242C299.026 449.674 298.859 449.036 298.859 448.328C298.859 447.625 299.023 446.984 299.352 446.406C299.68 445.823 300.143 445.365 300.742 445.031C301.341 444.693 302.031 444.526 302.812 444.531ZM302.812 445.766C302.328 445.766 301.888 445.88 301.492 446.109C301.102 446.339 300.792 446.648 300.562 447.039C300.339 447.43 300.229 447.854 300.234 448.312C300.234 448.776 300.344 449.201 300.562 449.586C300.781 449.966 301.081 450.268 301.461 450.492C301.846 450.716 302.281 450.828 302.766 450.828C303.245 450.828 303.685 450.708 304.086 450.469C304.487 450.229 304.805 449.914 305.039 449.523C305.273 449.133 305.391 448.719 305.391 448.281C305.391 447.849 305.279 447.44 305.055 447.055C304.831 446.664 304.521 446.352 304.125 446.117C303.734 445.883 303.297 445.766 302.812 445.766ZM309.016 459.203H307.859L308.719 454.953H310.234L309.016 459.203ZM316 456.156C315.219 456.156 314.523 456.021 313.914 455.75C313.305 455.479 312.831 455.104 312.492 454.625C312.154 454.146 311.984 453.604 311.984 453C311.984 452.521 312.086 452.073 312.289 451.656C312.492 451.24 312.768 450.898 313.117 450.633C313.466 450.362 313.854 450.193 314.281 450.125V450.062C313.911 449.979 313.586 449.815 313.305 449.57C313.029 449.326 312.812 449.026 312.656 448.672C312.5 448.318 312.422 447.938 312.422 447.531C312.422 446.964 312.576 446.453 312.883 446C313.19 445.542 313.615 445.182 314.156 444.922C314.703 444.661 315.318 444.531 316 444.531C316.677 444.531 317.289 444.661 317.836 444.922C318.383 445.182 318.81 445.542 319.117 446C319.43 446.453 319.589 446.964 319.594 447.531C319.589 447.938 319.505 448.318 319.344 448.672C319.188 449.026 318.969 449.326 318.688 449.57C318.406 449.815 318.083 449.979 317.719 450.062V450.125C318.141 450.193 318.526 450.362 318.875 450.633C319.229 450.898 319.508 451.24 319.711 451.656C319.919 452.073 320.026 452.521 320.031 453C320.026 453.604 319.852 454.146 319.508 454.625C319.169 455.104 318.693 455.479 318.078 455.75C317.469 456.021 316.776 456.156 316 456.156ZM316 454.922C316.531 454.922 316.995 454.836 317.391 454.664C317.786 454.492 318.091 454.258 318.305 453.961C318.518 453.664 318.625 453.318 318.625 452.922C318.625 452.51 318.513 452.141 318.289 451.812C318.065 451.479 317.753 451.219 317.352 451.031C316.951 450.844 316.5 450.75 316 450.75C315.5 450.75 315.052 450.844 314.656 451.031C314.26 451.219 313.948 451.479 313.719 451.812C313.495 452.141 313.385 452.51 313.391 452.922C313.385 453.318 313.487 453.664 313.695 453.961C313.909 454.258 314.211 454.492 314.602 454.664C314.997 454.836 315.464 454.922 316 454.922ZM316 449.562C316.427 449.562 316.81 449.479 317.148 449.312C317.487 449.146 317.75 448.919 317.938 448.633C318.125 448.346 318.219 448.016 318.219 447.641C318.219 447.266 318.128 446.935 317.945 446.648C317.763 446.362 317.503 446.141 317.164 445.984C316.826 445.828 316.438 445.75 316 445.75C315.557 445.75 315.169 445.828 314.836 445.984C314.508 446.141 314.25 446.362 314.062 446.648C313.875 446.935 313.781 447.266 313.781 447.641C313.781 448.016 313.878 448.346 314.07 448.633C314.263 448.919 314.526 449.146 314.859 449.312C315.193 449.479 315.573 449.562 316 449.562ZM325.609 456.156C324.938 456.156 324.326 456.026 323.773 455.766C323.227 455.505 322.789 455.148 322.461 454.695C322.138 454.242 321.964 453.729 321.938 453.156H323.297C323.328 453.49 323.451 453.789 323.664 454.055C323.878 454.32 324.154 454.531 324.492 454.688C324.836 454.844 325.208 454.922 325.609 454.922C326.094 454.922 326.526 454.812 326.906 454.594C327.292 454.375 327.594 454.076 327.812 453.695C328.031 453.315 328.141 452.891 328.141 452.422C328.141 451.938 328.029 451.503 327.805 451.117C327.581 450.727 327.268 450.419 326.867 450.195C326.466 449.971 326.016 449.859 325.516 449.859C325.021 449.849 324.596 449.927 324.242 450.094C323.888 450.255 323.609 450.516 323.406 450.875H322.047L322.844 444.688H328.969V445.938H324.016L323.594 449.25H323.703C323.964 449.052 324.273 448.893 324.633 448.773C324.997 448.654 325.375 448.594 325.766 448.594C326.474 448.594 327.115 448.755 327.688 449.078C328.26 449.401 328.708 449.854 329.031 450.438C329.354 451.016 329.516 451.667 329.516 452.391C329.516 453.109 329.346 453.755 329.008 454.328C328.669 454.901 328.203 455.349 327.609 455.672C327.021 455.995 326.354 456.156 325.609 456.156ZM335.172 456.156C334.339 456.156 333.628 455.93 333.039 455.477C332.451 455.023 332 454.362 331.688 453.492C331.375 452.622 331.219 451.573 331.219 450.344C331.219 449.13 331.375 448.089 331.688 447.219C332 446.344 332.451 445.677 333.039 445.219C333.633 444.76 334.344 444.531 335.172 444.531C335.995 444.531 336.703 444.76 337.297 445.219C337.891 445.677 338.344 446.344 338.656 447.219C338.969 448.089 339.125 449.13 339.125 450.344C339.125 451.573 338.971 452.622 338.664 453.492C338.357 454.362 337.906 455.023 337.312 455.477C336.719 455.93 336.005 456.156 335.172 456.156ZM335.172 454.906C335.714 454.906 336.18 454.729 336.57 454.375C336.961 454.021 337.255 453.503 337.453 452.82C337.651 452.138 337.75 451.312 337.75 450.344C337.75 449.375 337.648 448.547 337.445 447.859C337.242 447.172 336.948 446.648 336.562 446.289C336.177 445.93 335.714 445.75 335.172 445.75C334.63 445.75 334.167 445.93 333.781 446.289C333.396 446.648 333.099 447.172 332.891 447.859C332.682 448.547 332.578 449.375 332.578 450.344C332.578 451.312 332.682 452.138 332.891 452.82C333.099 453.503 333.393 454.021 333.773 454.375C334.159 454.729 334.625 454.906 335.172 454.906ZM349.75 453.453H348.516V450.359H349.75V453.453ZM355.969 453.938H354.734V443.391H355.969V453.938ZM356.312 456.969H346.438V455.938H356.312V456.969ZM347.672 456.234H346.438V452.906H347.672V456.234ZM344.438 449.828C346.297 449.818 347.943 449.789 349.375 449.742C350.807 449.69 352.177 449.583 353.484 449.422L353.562 450.312C352.214 450.526 350.799 450.667 349.32 450.734C347.841 450.802 346.271 450.833 344.609 450.828L344.438 449.828ZM355.062 452.5H351.859V451.609H355.062V452.5ZM349 443.953C349.672 443.953 350.268 444.052 350.789 444.25C351.315 444.448 351.721 444.732 352.008 445.102C352.294 445.471 352.438 445.896 352.438 446.375C352.438 446.865 352.294 447.289 352.008 447.648C351.721 448.008 351.318 448.286 350.797 448.484C350.276 448.682 349.677 448.781 349 448.781C348.318 448.781 347.716 448.682 347.195 448.484C346.68 448.286 346.279 448.008 345.992 447.648C345.706 447.289 345.562 446.865 345.562 446.375C345.562 445.896 345.706 445.471 345.992 445.102C346.279 444.732 346.682 444.448 347.203 444.25C347.724 444.052 348.323 443.953 349 443.953ZM349 444.891C348.552 444.885 348.156 444.945 347.812 445.07C347.469 445.19 347.201 445.365 347.008 445.594C346.82 445.823 346.729 446.083 346.734 446.375C346.729 446.672 346.82 446.935 347.008 447.164C347.201 447.388 347.469 447.562 347.812 447.688C348.156 447.812 348.552 447.875 349 447.875C349.438 447.875 349.828 447.812 350.172 447.688C350.516 447.562 350.784 447.388 350.977 447.164C351.169 446.935 351.266 446.672 351.266 446.375C351.266 446.083 351.169 445.823 350.977 445.594C350.784 445.365 350.516 445.19 350.172 445.07C349.828 444.945 349.438 444.885 349 444.891Z" fill="#56555A"/> +<path d="M376 446L380 450L376 454" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +<path d="M390 478H40C35.5817 478 32 481.582 32 486V510C32 514.418 35.5817 518 40 518H390C394.418 518 398 514.418 398 510V486C398 481.582 394.418 478 390 478Z" fill="white"/> +<path d="M55.4922 493.227C55.4922 494.07 55.2656 494.841 54.8125 495.539C54.3646 496.232 53.7109 496.815 52.8516 497.289C51.9922 497.758 50.974 498.073 49.7969 498.234L49.0547 496.68C50.0495 496.56 50.901 496.323 51.6094 495.969C52.3229 495.609 52.8594 495.193 53.2188 494.719C53.5781 494.24 53.7578 493.742 53.7578 493.227V492.797H55.4922V493.227ZM56.0625 493.227C56.0625 493.742 56.2396 494.24 56.5938 494.719C56.9531 495.193 57.487 495.609 58.1953 495.969C58.9089 496.323 59.7708 496.56 60.7812 496.68L60.0625 498.234C58.875 498.073 57.849 497.758 56.9844 497.289C56.1198 496.815 55.4609 496.232 55.0078 495.539C54.5547 494.841 54.3281 494.07 54.3281 493.227V492.797H56.0625V493.227ZM55.8594 505.445H53.8828V500.203H55.8594V505.445ZM61.3984 500.656H48.4297V499.07H61.3984V500.656ZM60.2266 493.523H49.5938V491.969H60.2266V493.523ZM73.4688 505.438H71.5V491.203H73.4688V505.438ZM75.5781 498.422H73.0312V496.789H75.5781V498.422ZM70.5312 494.938H62.1797V493.336H70.5312V494.938ZM66.3906 495.727C67.0729 495.727 67.6901 495.872 68.2422 496.164C68.7995 496.451 69.2344 496.852 69.5469 497.367C69.8646 497.883 70.026 498.466 70.0312 499.117C70.026 499.773 69.8646 500.359 69.5469 500.875C69.2344 501.385 68.7995 501.786 68.2422 502.078C67.6901 502.365 67.0729 502.508 66.3906 502.508C65.6979 502.508 65.0755 502.365 64.5234 502.078C63.9714 501.786 63.5391 501.385 63.2266 500.875C62.9141 500.359 62.7578 499.773 62.7578 499.117C62.7578 498.466 62.9141 497.883 63.2266 497.367C63.5391 496.852 63.9714 496.451 64.5234 496.164C65.0755 495.872 65.6979 495.727 66.3906 495.727ZM66.3906 497.352C66.0573 497.357 65.7604 497.43 65.5 497.57C65.2396 497.711 65.0339 497.917 64.8828 498.188C64.737 498.453 64.6641 498.763 64.6641 499.117C64.6641 499.482 64.737 499.797 64.8828 500.062C65.0339 500.323 65.2396 500.523 65.5 500.664C65.7604 500.805 66.0573 500.878 66.3906 500.883C66.724 500.878 67.0208 500.805 67.2812 500.664C67.5469 500.523 67.75 500.323 67.8906 500.062C68.0365 499.797 68.1094 499.482 68.1094 499.117C68.1094 498.763 68.0365 498.453 67.8906 498.188C67.75 497.917 67.5469 497.711 67.2812 497.57C67.0208 497.43 66.724 497.357 66.3906 497.352ZM67.3828 493.945H65.3984V491.43H67.3828V493.945Z" fill="#56555A"/> +<path d="M288.781 500.531L293.875 492.688H294.719V494.469H294.125L290.297 500.359V500.453H297.188V501.688H288.781V500.531ZM294.266 501.344V500.797V492.688H295.609V504H294.266V501.344ZM302.812 492.531C303.531 492.542 304.201 492.714 304.82 493.047C305.44 493.38 305.945 493.945 306.336 494.742C306.727 495.534 306.922 496.583 306.922 497.891C306.922 499.214 306.75 500.344 306.406 501.281C306.062 502.219 305.568 502.932 304.922 503.422C304.276 503.911 303.51 504.156 302.625 504.156C301.969 504.156 301.38 504.029 300.859 503.773C300.339 503.518 299.914 503.167 299.586 502.719C299.258 502.266 299.047 501.74 298.953 501.141H300.344C300.427 501.49 300.57 501.797 300.773 502.062C300.977 502.323 301.234 502.529 301.547 502.68C301.859 502.831 302.219 502.906 302.625 502.906C303.24 502.906 303.771 502.734 304.219 502.391C304.667 502.047 305.008 501.552 305.242 500.906C305.482 500.255 305.604 499.474 305.609 498.562H305.453C305.234 498.875 304.977 499.143 304.68 499.367C304.383 499.591 304.055 499.763 303.695 499.883C303.336 500.003 302.958 500.062 302.562 500.062C301.891 500.062 301.271 499.901 300.703 499.578C300.141 499.255 299.693 498.81 299.359 498.242C299.026 497.674 298.859 497.036 298.859 496.328C298.859 495.625 299.023 494.984 299.352 494.406C299.68 493.823 300.143 493.365 300.742 493.031C301.341 492.693 302.031 492.526 302.812 492.531ZM302.812 493.766C302.328 493.766 301.888 493.88 301.492 494.109C301.102 494.339 300.792 494.648 300.562 495.039C300.339 495.43 300.229 495.854 300.234 496.312C300.234 496.776 300.344 497.201 300.562 497.586C300.781 497.966 301.081 498.268 301.461 498.492C301.846 498.716 302.281 498.828 302.766 498.828C303.245 498.828 303.685 498.708 304.086 498.469C304.487 498.229 304.805 497.914 305.039 497.523C305.273 497.133 305.391 496.719 305.391 496.281C305.391 495.849 305.279 495.44 305.055 495.055C304.831 494.664 304.521 494.352 304.125 494.117C303.734 493.883 303.297 493.766 302.812 493.766ZM309.016 507.203H307.859L308.719 502.953H310.234L309.016 507.203ZM316 504.156C315.219 504.156 314.523 504.021 313.914 503.75C313.305 503.479 312.831 503.104 312.492 502.625C312.154 502.146 311.984 501.604 311.984 501C311.984 500.521 312.086 500.073 312.289 499.656C312.492 499.24 312.768 498.898 313.117 498.633C313.466 498.362 313.854 498.193 314.281 498.125V498.062C313.911 497.979 313.586 497.815 313.305 497.57C313.029 497.326 312.812 497.026 312.656 496.672C312.5 496.318 312.422 495.938 312.422 495.531C312.422 494.964 312.576 494.453 312.883 494C313.19 493.542 313.615 493.182 314.156 492.922C314.703 492.661 315.318 492.531 316 492.531C316.677 492.531 317.289 492.661 317.836 492.922C318.383 493.182 318.81 493.542 319.117 494C319.43 494.453 319.589 494.964 319.594 495.531C319.589 495.938 319.505 496.318 319.344 496.672C319.188 497.026 318.969 497.326 318.688 497.57C318.406 497.815 318.083 497.979 317.719 498.062V498.125C318.141 498.193 318.526 498.362 318.875 498.633C319.229 498.898 319.508 499.24 319.711 499.656C319.919 500.073 320.026 500.521 320.031 501C320.026 501.604 319.852 502.146 319.508 502.625C319.169 503.104 318.693 503.479 318.078 503.75C317.469 504.021 316.776 504.156 316 504.156ZM316 502.922C316.531 502.922 316.995 502.836 317.391 502.664C317.786 502.492 318.091 502.258 318.305 501.961C318.518 501.664 318.625 501.318 318.625 500.922C318.625 500.51 318.513 500.141 318.289 499.812C318.065 499.479 317.753 499.219 317.352 499.031C316.951 498.844 316.5 498.75 316 498.75C315.5 498.75 315.052 498.844 314.656 499.031C314.26 499.219 313.948 499.479 313.719 499.812C313.495 500.141 313.385 500.51 313.391 500.922C313.385 501.318 313.487 501.664 313.695 501.961C313.909 502.258 314.211 502.492 314.602 502.664C314.997 502.836 315.464 502.922 316 502.922ZM316 497.562C316.427 497.562 316.81 497.479 317.148 497.312C317.487 497.146 317.75 496.919 317.938 496.633C318.125 496.346 318.219 496.016 318.219 495.641C318.219 495.266 318.128 494.935 317.945 494.648C317.763 494.362 317.503 494.141 317.164 493.984C316.826 493.828 316.438 493.75 316 493.75C315.557 493.75 315.169 493.828 314.836 493.984C314.508 494.141 314.25 494.362 314.062 494.648C313.875 494.935 313.781 495.266 313.781 495.641C313.781 496.016 313.878 496.346 314.07 496.633C314.263 496.919 314.526 497.146 314.859 497.312C315.193 497.479 315.573 497.562 316 497.562ZM325.609 504.156C324.938 504.156 324.326 504.026 323.773 503.766C323.227 503.505 322.789 503.148 322.461 502.695C322.138 502.242 321.964 501.729 321.938 501.156H323.297C323.328 501.49 323.451 501.789 323.664 502.055C323.878 502.32 324.154 502.531 324.492 502.688C324.836 502.844 325.208 502.922 325.609 502.922C326.094 502.922 326.526 502.812 326.906 502.594C327.292 502.375 327.594 502.076 327.812 501.695C328.031 501.315 328.141 500.891 328.141 500.422C328.141 499.938 328.029 499.503 327.805 499.117C327.581 498.727 327.268 498.419 326.867 498.195C326.466 497.971 326.016 497.859 325.516 497.859C325.021 497.849 324.596 497.927 324.242 498.094C323.888 498.255 323.609 498.516 323.406 498.875H322.047L322.844 492.688H328.969V493.938H324.016L323.594 497.25H323.703C323.964 497.052 324.273 496.893 324.633 496.773C324.997 496.654 325.375 496.594 325.766 496.594C326.474 496.594 327.115 496.755 327.688 497.078C328.26 497.401 328.708 497.854 329.031 498.438C329.354 499.016 329.516 499.667 329.516 500.391C329.516 501.109 329.346 501.755 329.008 502.328C328.669 502.901 328.203 503.349 327.609 503.672C327.021 503.995 326.354 504.156 325.609 504.156ZM335.172 504.156C334.339 504.156 333.628 503.93 333.039 503.477C332.451 503.023 332 502.362 331.688 501.492C331.375 500.622 331.219 499.573 331.219 498.344C331.219 497.13 331.375 496.089 331.688 495.219C332 494.344 332.451 493.677 333.039 493.219C333.633 492.76 334.344 492.531 335.172 492.531C335.995 492.531 336.703 492.76 337.297 493.219C337.891 493.677 338.344 494.344 338.656 495.219C338.969 496.089 339.125 497.13 339.125 498.344C339.125 499.573 338.971 500.622 338.664 501.492C338.357 502.362 337.906 503.023 337.312 503.477C336.719 503.93 336.005 504.156 335.172 504.156ZM335.172 502.906C335.714 502.906 336.18 502.729 336.57 502.375C336.961 502.021 337.255 501.503 337.453 500.82C337.651 500.138 337.75 499.312 337.75 498.344C337.75 497.375 337.648 496.547 337.445 495.859C337.242 495.172 336.948 494.648 336.562 494.289C336.177 493.93 335.714 493.75 335.172 493.75C334.63 493.75 334.167 493.93 333.781 494.289C333.396 494.648 333.099 495.172 332.891 495.859C332.682 496.547 332.578 497.375 332.578 498.344C332.578 499.312 332.682 500.138 332.891 500.82C333.099 501.503 333.393 502.021 333.773 502.375C334.159 502.729 334.625 502.906 335.172 502.906ZM349.75 501.453H348.516V498.359H349.75V501.453ZM355.969 501.938H354.734V491.391H355.969V501.938ZM356.312 504.969H346.438V503.938H356.312V504.969ZM347.672 504.234H346.438V500.906H347.672V504.234ZM344.438 497.828C346.297 497.818 347.943 497.789 349.375 497.742C350.807 497.69 352.177 497.583 353.484 497.422L353.562 498.312C352.214 498.526 350.799 498.667 349.32 498.734C347.841 498.802 346.271 498.833 344.609 498.828L344.438 497.828ZM355.062 500.5H351.859V499.609H355.062V500.5ZM349 491.953C349.672 491.953 350.268 492.052 350.789 492.25C351.315 492.448 351.721 492.732 352.008 493.102C352.294 493.471 352.438 493.896 352.438 494.375C352.438 494.865 352.294 495.289 352.008 495.648C351.721 496.008 351.318 496.286 350.797 496.484C350.276 496.682 349.677 496.781 349 496.781C348.318 496.781 347.716 496.682 347.195 496.484C346.68 496.286 346.279 496.008 345.992 495.648C345.706 495.289 345.562 494.865 345.562 494.375C345.562 493.896 345.706 493.471 345.992 493.102C346.279 492.732 346.682 492.448 347.203 492.25C347.724 492.052 348.323 491.953 349 491.953ZM349 492.891C348.552 492.885 348.156 492.945 347.812 493.07C347.469 493.19 347.201 493.365 347.008 493.594C346.82 493.823 346.729 494.083 346.734 494.375C346.729 494.672 346.82 494.935 347.008 495.164C347.201 495.388 347.469 495.562 347.812 495.688C348.156 495.812 348.552 495.875 349 495.875C349.438 495.875 349.828 495.812 350.172 495.688C350.516 495.562 350.784 495.388 350.977 495.164C351.169 494.935 351.266 494.672 351.266 494.375C351.266 494.083 351.169 493.823 350.977 493.594C350.784 493.365 350.516 493.19 350.172 493.07C349.828 492.945 349.438 492.885 349 492.891Z" fill="#56555A"/> +<path d="M376 494L380 498L376 502" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +<path d="M390 526H40C35.5817 526 32 529.582 32 534V558C32 562.418 35.5817 566 40 566H390C394.418 566 398 562.418 398 558V534C398 529.582 394.418 526 390 526Z" fill="white"/> +<path d="M61.4297 551.742H48.4297V550.148H61.4297V551.742ZM55.8438 550.57H53.8594V546.922H55.8438V550.57ZM55.5312 541.047C55.5312 542.062 55.2891 543.01 54.8047 543.891C54.3255 544.766 53.6354 545.51 52.7344 546.125C51.8385 546.74 50.7891 547.159 49.5859 547.383L48.7266 545.719C49.763 545.557 50.6641 545.237 51.4297 544.758C52.1953 544.273 52.776 543.708 53.1719 543.062C53.5729 542.411 53.776 541.74 53.7812 541.047V540.039H55.5312V541.047ZM55.8984 541.047C55.8984 541.745 56.099 542.419 56.5 543.07C56.9062 543.716 57.4922 544.279 58.2578 544.758C59.0286 545.237 59.9375 545.557 60.9844 545.719L60.1328 547.383C58.9245 547.159 57.8698 546.745 56.9688 546.141C56.0677 545.531 55.375 544.789 54.8906 543.914C54.4062 543.034 54.1667 542.078 54.1719 541.047V540.039H55.8984V541.047ZM72.9609 542.82H68.7422V541.219H72.9609V542.82ZM72.9609 546.258H68.7422V544.664H72.9609V546.258ZM74.2344 549.633H72.25V539.234H74.2344V549.633ZM74.5781 553.195H64.7969V551.586H74.5781V553.195ZM66.7969 552.406H64.7969V548.578H66.7969V552.406ZM66.2188 540.055C66.9062 540.055 67.5365 540.214 68.1094 540.531C68.6875 540.849 69.1432 541.289 69.4766 541.852C69.8099 542.414 69.9792 543.047 69.9844 543.75C69.9792 544.443 69.8073 545.068 69.4688 545.625C69.1354 546.182 68.6823 546.622 68.1094 546.945C67.5365 547.263 66.9062 547.422 66.2188 547.422C65.5052 547.422 64.8594 547.263 64.2812 546.945C63.7083 546.622 63.2552 546.182 62.9219 545.625C62.5938 545.068 62.4297 544.443 62.4297 543.75C62.4297 543.047 62.5938 542.414 62.9219 541.852C63.2552 541.289 63.7083 540.849 64.2812 540.531C64.8594 540.214 65.5052 540.055 66.2188 540.055ZM66.2188 541.828C65.849 541.823 65.5208 541.898 65.2344 542.055C64.9479 542.211 64.724 542.435 64.5625 542.727C64.401 543.018 64.3203 543.359 64.3203 543.75C64.3203 544.135 64.401 544.471 64.5625 544.758C64.724 545.044 64.9479 545.266 65.2344 545.422C65.5208 545.573 65.849 545.651 66.2188 545.656C66.5729 545.651 66.8906 545.573 67.1719 545.422C67.4531 545.266 67.6745 545.044 67.8359 544.758C67.9974 544.471 68.0781 544.135 68.0781 543.75C68.0781 543.359 67.9974 543.021 67.8359 542.734C67.6745 542.443 67.4531 542.219 67.1719 542.062C66.8906 541.901 66.5729 541.823 66.2188 541.828Z" fill="#56555A"/> +<path d="M289.047 550.969L292.906 546.906C293.411 546.365 293.797 545.927 294.062 545.594C294.333 545.26 294.539 544.943 294.68 544.641C294.82 544.333 294.891 544.01 294.891 543.672C294.891 543.292 294.792 542.958 294.594 542.672C294.396 542.38 294.125 542.154 293.781 541.992C293.443 541.831 293.062 541.75 292.641 541.75C292.198 541.75 291.81 541.839 291.477 542.016C291.148 542.193 290.893 542.443 290.711 542.766C290.529 543.083 290.438 543.453 290.438 543.875H289.109C289.104 543.219 289.255 542.638 289.562 542.133C289.875 541.628 290.305 541.234 290.852 540.953C291.398 540.672 292.01 540.531 292.688 540.531C293.359 540.531 293.961 540.669 294.492 540.945C295.029 541.221 295.448 541.599 295.75 542.078C296.052 542.557 296.203 543.089 296.203 543.672C296.198 544.104 296.117 544.518 295.961 544.914C295.81 545.305 295.549 545.74 295.18 546.219C294.81 546.698 294.286 547.286 293.609 547.984L291.016 550.656V550.75H296.406V552H289.062L289.047 550.969ZM302.359 552.156C301.615 552.156 300.948 552.031 300.359 551.781C299.776 551.531 299.312 551.18 298.969 550.727C298.625 550.268 298.443 549.745 298.422 549.156H299.844C299.87 549.51 299.995 549.818 300.219 550.078C300.448 550.339 300.745 550.542 301.109 550.688C301.479 550.833 301.891 550.906 302.344 550.906C302.839 550.906 303.281 550.823 303.672 550.656C304.068 550.49 304.375 550.255 304.594 549.953C304.812 549.651 304.922 549.307 304.922 548.922C304.917 548.51 304.807 548.146 304.594 547.828C304.385 547.505 304.073 547.255 303.656 547.078C303.24 546.901 302.745 546.812 302.172 546.812H301.25V545.578H302.172C302.625 545.578 303.029 545.497 303.383 545.336C303.742 545.174 304.018 544.948 304.211 544.656C304.404 544.359 304.5 544.021 304.5 543.641C304.5 543.266 304.414 542.935 304.242 542.648C304.07 542.362 303.826 542.141 303.508 541.984C303.19 541.828 302.818 541.75 302.391 541.75C301.984 541.755 301.604 541.831 301.25 541.977C300.896 542.117 300.607 542.323 300.383 542.594C300.159 542.859 300.036 543.172 300.016 543.531H298.656C298.677 542.948 298.859 542.427 299.203 541.969C299.547 541.51 300 541.156 300.562 540.906C301.125 540.656 301.74 540.531 302.406 540.531C303.104 540.531 303.716 540.669 304.242 540.945C304.768 541.221 305.169 541.591 305.445 542.055C305.727 542.518 305.865 543.021 305.859 543.562C305.865 543.984 305.789 544.37 305.633 544.719C305.482 545.062 305.26 545.354 304.969 545.594C304.677 545.833 304.333 546.01 303.938 546.125V546.203C304.422 546.276 304.841 546.435 305.195 546.68C305.555 546.924 305.828 547.24 306.016 547.625C306.203 548.01 306.297 548.443 306.297 548.922C306.297 549.531 306.128 550.083 305.789 550.578C305.451 551.068 304.979 551.453 304.375 551.734C303.776 552.016 303.104 552.156 302.359 552.156ZM308.531 555.203H307.375L308.234 550.953H309.75L308.531 555.203ZM315.516 552.156C314.734 552.156 314.039 552.021 313.43 551.75C312.82 551.479 312.346 551.104 312.008 550.625C311.669 550.146 311.5 549.604 311.5 549C311.5 548.521 311.602 548.073 311.805 547.656C312.008 547.24 312.284 546.898 312.633 546.633C312.982 546.362 313.37 546.193 313.797 546.125V546.062C313.427 545.979 313.102 545.815 312.82 545.57C312.544 545.326 312.328 545.026 312.172 544.672C312.016 544.318 311.938 543.938 311.938 543.531C311.938 542.964 312.091 542.453 312.398 542C312.706 541.542 313.13 541.182 313.672 540.922C314.219 540.661 314.833 540.531 315.516 540.531C316.193 540.531 316.805 540.661 317.352 540.922C317.898 541.182 318.326 541.542 318.633 542C318.945 542.453 319.104 542.964 319.109 543.531C319.104 543.938 319.021 544.318 318.859 544.672C318.703 545.026 318.484 545.326 318.203 545.57C317.922 545.815 317.599 545.979 317.234 546.062V546.125C317.656 546.193 318.042 546.362 318.391 546.633C318.745 546.898 319.023 547.24 319.227 547.656C319.435 548.073 319.542 548.521 319.547 549C319.542 549.604 319.367 550.146 319.023 550.625C318.685 551.104 318.208 551.479 317.594 551.75C316.984 552.021 316.292 552.156 315.516 552.156ZM315.516 550.922C316.047 550.922 316.51 550.836 316.906 550.664C317.302 550.492 317.607 550.258 317.82 549.961C318.034 549.664 318.141 549.318 318.141 548.922C318.141 548.51 318.029 548.141 317.805 547.812C317.581 547.479 317.268 547.219 316.867 547.031C316.466 546.844 316.016 546.75 315.516 546.75C315.016 546.75 314.568 546.844 314.172 547.031C313.776 547.219 313.464 547.479 313.234 547.812C313.01 548.141 312.901 548.51 312.906 548.922C312.901 549.318 313.003 549.664 313.211 549.961C313.424 550.258 313.727 550.492 314.117 550.664C314.513 550.836 314.979 550.922 315.516 550.922ZM315.516 545.562C315.943 545.562 316.326 545.479 316.664 545.312C317.003 545.146 317.266 544.919 317.453 544.633C317.641 544.346 317.734 544.016 317.734 543.641C317.734 543.266 317.643 542.935 317.461 542.648C317.279 542.362 317.018 542.141 316.68 541.984C316.341 541.828 315.953 541.75 315.516 541.75C315.073 541.75 314.685 541.828 314.352 541.984C314.023 542.141 313.766 542.362 313.578 542.648C313.391 542.935 313.297 543.266 313.297 543.641C313.297 544.016 313.393 544.346 313.586 544.633C313.779 544.919 314.042 545.146 314.375 545.312C314.708 545.479 315.089 545.562 315.516 545.562ZM325.125 552.156C324.453 552.156 323.841 552.026 323.289 551.766C322.742 551.505 322.305 551.148 321.977 550.695C321.654 550.242 321.479 549.729 321.453 549.156H322.812C322.844 549.49 322.966 549.789 323.18 550.055C323.393 550.32 323.669 550.531 324.008 550.688C324.352 550.844 324.724 550.922 325.125 550.922C325.609 550.922 326.042 550.812 326.422 550.594C326.807 550.375 327.109 550.076 327.328 549.695C327.547 549.315 327.656 548.891 327.656 548.422C327.656 547.938 327.544 547.503 327.32 547.117C327.096 546.727 326.784 546.419 326.383 546.195C325.982 545.971 325.531 545.859 325.031 545.859C324.536 545.849 324.112 545.927 323.758 546.094C323.404 546.255 323.125 546.516 322.922 546.875H321.562L322.359 540.688H328.484V541.938H323.531L323.109 545.25H323.219C323.479 545.052 323.789 544.893 324.148 544.773C324.513 544.654 324.891 544.594 325.281 544.594C325.99 544.594 326.63 544.755 327.203 545.078C327.776 545.401 328.224 545.854 328.547 546.438C328.87 547.016 329.031 547.667 329.031 548.391C329.031 549.109 328.862 549.755 328.523 550.328C328.185 550.901 327.719 551.349 327.125 551.672C326.536 551.995 325.87 552.156 325.125 552.156ZM334.688 552.156C333.854 552.156 333.143 551.93 332.555 551.477C331.966 551.023 331.516 550.362 331.203 549.492C330.891 548.622 330.734 547.573 330.734 546.344C330.734 545.13 330.891 544.089 331.203 543.219C331.516 542.344 331.966 541.677 332.555 541.219C333.148 540.76 333.859 540.531 334.688 540.531C335.51 540.531 336.219 540.76 336.812 541.219C337.406 541.677 337.859 542.344 338.172 543.219C338.484 544.089 338.641 545.13 338.641 546.344C338.641 547.573 338.487 548.622 338.18 549.492C337.872 550.362 337.422 551.023 336.828 551.477C336.234 551.93 335.521 552.156 334.688 552.156ZM334.688 550.906C335.229 550.906 335.695 550.729 336.086 550.375C336.477 550.021 336.771 549.503 336.969 548.82C337.167 548.138 337.266 547.312 337.266 546.344C337.266 545.375 337.164 544.547 336.961 543.859C336.758 543.172 336.464 542.648 336.078 542.289C335.693 541.93 335.229 541.75 334.688 541.75C334.146 541.75 333.682 541.93 333.297 542.289C332.911 542.648 332.615 543.172 332.406 543.859C332.198 544.547 332.094 545.375 332.094 546.344C332.094 547.312 332.198 548.138 332.406 548.82C332.615 549.503 332.909 550.021 333.289 550.375C333.674 550.729 334.141 550.906 334.688 550.906ZM349.266 549.453H348.031V546.359H349.266V549.453ZM355.484 549.938H354.25V539.391H355.484V549.938ZM355.828 552.969H345.953V551.938H355.828V552.969ZM347.188 552.234H345.953V548.906H347.188V552.234ZM343.953 545.828C345.812 545.818 347.458 545.789 348.891 545.742C350.323 545.69 351.693 545.583 353 545.422L353.078 546.312C351.729 546.526 350.315 546.667 348.836 546.734C347.357 546.802 345.786 546.833 344.125 546.828L343.953 545.828ZM354.578 548.5H351.375V547.609H354.578V548.5ZM348.516 539.953C349.188 539.953 349.784 540.052 350.305 540.25C350.831 540.448 351.237 540.732 351.523 541.102C351.81 541.471 351.953 541.896 351.953 542.375C351.953 542.865 351.81 543.289 351.523 543.648C351.237 544.008 350.833 544.286 350.312 544.484C349.792 544.682 349.193 544.781 348.516 544.781C347.833 544.781 347.232 544.682 346.711 544.484C346.195 544.286 345.794 544.008 345.508 543.648C345.221 543.289 345.078 542.865 345.078 542.375C345.078 541.896 345.221 541.471 345.508 541.102C345.794 540.732 346.198 540.448 346.719 540.25C347.24 540.052 347.839 539.953 348.516 539.953ZM348.516 540.891C348.068 540.885 347.672 540.945 347.328 541.07C346.984 541.19 346.716 541.365 346.523 541.594C346.336 541.823 346.245 542.083 346.25 542.375C346.245 542.672 346.336 542.935 346.523 543.164C346.716 543.388 346.984 543.562 347.328 543.688C347.672 543.812 348.068 543.875 348.516 543.875C348.953 543.875 349.344 543.812 349.688 543.688C350.031 543.562 350.299 543.388 350.492 543.164C350.685 542.935 350.781 542.672 350.781 542.375C350.781 542.083 350.685 541.823 350.492 541.594C350.299 541.365 350.031 541.19 349.688 541.07C349.344 540.945 348.953 540.885 348.516 540.891Z" fill="#56555A"/> +<path d="M376 542L380 546L376 550" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +<path d="M390 574H40C35.5817 574 32 577.582 32 582V606C32 610.418 35.5817 614 40 614H390C394.418 614 398 610.418 398 606V582C398 577.582 394.418 574 390 574Z" fill="white"/> +<path d="M56.4922 593.648H54.0703V592.016H56.4922V593.648ZM52.5781 590.891C52.5781 592.005 52.4635 593.06 52.2344 594.055C52.0104 595.044 51.659 595.938 51.1798 596.734C50.7058 597.526 50.1042 598.143 49.375 598.586L48.1562 597.102C48.8281 596.69 49.3802 596.156 49.8125 595.5C50.2448 594.839 50.5573 594.12 50.75 593.344C50.9479 592.568 51.0469 591.75 51.0469 590.891V588.438H52.5781V590.891ZM52.9767 590.797C52.9767 591.641 53.06 592.43 53.2267 593.164C53.3933 593.893 53.6694 594.57 54.0548 595.195C54.4402 595.815 54.9427 596.326 55.5625 596.727L54.4844 598.258C53.7604 597.82 53.1746 597.216 52.7267 596.445C52.2787 595.674 51.9583 594.818 51.7656 593.875C51.5729 592.927 51.4792 591.901 51.4844 590.797V588.438H52.9767V590.797ZM60.75 601.438H58.8359V587.203H60.75V601.438ZM57.7734 600.781H55.9062V587.422H57.7734V600.781ZM74.2345 598.062H72.25V587.234H74.2345V598.062ZM72.9922 592.375H70.3281V590.766H72.9922V592.375ZM72.9922 595.383H70.3281V593.797H72.9922V595.383ZM70.1797 590.289H62.2812V588.719H70.1797V590.289ZM66.3125 590.789C66.9531 590.789 67.5287 590.909 68.0392 591.148C68.5548 591.383 68.9557 591.714 69.2422 592.141C69.5339 592.568 69.6797 593.049 69.6797 593.586C69.6797 594.128 69.5339 594.612 69.2422 595.039C68.9557 595.461 68.5574 595.792 68.047 596.031C67.5366 596.266 66.9583 596.383 66.3125 596.383C65.6771 596.383 65.1069 596.266 64.6017 596.031C64.0965 595.792 63.698 595.461 63.4062 595.039C63.1199 594.612 62.9793 594.128 62.9845 593.586C62.9793 593.049 63.1199 592.57 63.4062 592.148C63.698 591.721 64.0965 591.388 64.6017 591.148C65.1069 590.909 65.6771 590.789 66.3125 590.789ZM66.3125 592.344C66.0208 592.349 65.7631 592.401 65.5392 592.5C65.3204 592.594 65.1484 592.734 65.0234 592.922C64.8984 593.109 64.8359 593.331 64.8359 593.586C64.8359 593.857 64.8984 594.086 65.0234 594.273C65.1484 594.461 65.3204 594.604 65.5392 594.703C65.7631 594.802 66.0208 594.852 66.3125 594.852C66.6042 594.852 66.862 594.802 67.0859 594.703C67.3099 594.604 67.4845 594.461 67.6095 594.273C67.7397 594.081 67.8047 593.852 67.8047 593.586C67.8047 593.331 67.7397 593.109 67.6095 592.922C67.4845 592.729 67.3099 592.586 67.0859 592.492C66.862 592.398 66.6042 592.349 66.3125 592.344ZM67.3281 589.688H65.3359V587.195H67.3281V589.688ZM74.5392 601.195H64.7656V599.586H74.5392V601.195ZM66.7812 600.328H64.7656V597.133H66.7812V600.328Z" fill="#56555A"/> +<path d="M289.047 598.969L292.906 594.906C293.411 594.365 293.797 593.927 294.062 593.594C294.333 593.26 294.539 592.943 294.68 592.641C294.82 592.333 294.891 592.01 294.891 591.672C294.891 591.292 294.792 590.958 294.594 590.672C294.396 590.38 294.125 590.154 293.781 589.992C293.443 589.831 293.062 589.75 292.641 589.75C292.198 589.75 291.81 589.839 291.477 590.016C291.148 590.193 290.893 590.443 290.711 590.766C290.529 591.083 290.438 591.453 290.438 591.875H289.109C289.104 591.219 289.255 590.638 289.562 590.133C289.875 589.628 290.305 589.234 290.852 588.953C291.398 588.672 292.01 588.531 292.688 588.531C293.359 588.531 293.961 588.669 294.492 588.945C295.029 589.221 295.448 589.599 295.75 590.078C296.052 590.557 296.203 591.089 296.203 591.672C296.198 592.104 296.117 592.518 295.961 592.914C295.81 593.305 295.549 593.74 295.18 594.219C294.81 594.698 294.286 595.286 293.609 595.984L291.016 598.656V598.75H296.406V600H289.062L289.047 598.969ZM302.359 600.156C301.615 600.156 300.948 600.031 300.359 599.781C299.776 599.531 299.312 599.18 298.969 598.727C298.625 598.268 298.443 597.745 298.422 597.156H299.844C299.87 597.51 299.995 597.818 300.219 598.078C300.448 598.339 300.745 598.542 301.109 598.688C301.479 598.833 301.891 598.906 302.344 598.906C302.839 598.906 303.281 598.823 303.672 598.656C304.068 598.49 304.375 598.255 304.594 597.953C304.812 597.651 304.922 597.307 304.922 596.922C304.917 596.51 304.807 596.146 304.594 595.828C304.385 595.505 304.073 595.255 303.656 595.078C303.24 594.901 302.745 594.812 302.172 594.812H301.25V593.578H302.172C302.625 593.578 303.029 593.497 303.383 593.336C303.742 593.174 304.018 592.948 304.211 592.656C304.404 592.359 304.5 592.021 304.5 591.641C304.5 591.266 304.414 590.935 304.242 590.648C304.07 590.362 303.826 590.141 303.508 589.984C303.19 589.828 302.818 589.75 302.391 589.75C301.984 589.755 301.604 589.831 301.25 589.977C300.896 590.117 300.607 590.323 300.383 590.594C300.159 590.859 300.036 591.172 300.016 591.531H298.656C298.677 590.948 298.859 590.427 299.203 589.969C299.547 589.51 300 589.156 300.562 588.906C301.125 588.656 301.74 588.531 302.406 588.531C303.104 588.531 303.716 588.669 304.242 588.945C304.768 589.221 305.169 589.591 305.445 590.055C305.727 590.518 305.865 591.021 305.859 591.562C305.865 591.984 305.789 592.37 305.633 592.719C305.482 593.062 305.26 593.354 304.969 593.594C304.677 593.833 304.333 594.01 303.938 594.125V594.203C304.422 594.276 304.841 594.435 305.195 594.68C305.555 594.924 305.828 595.24 306.016 595.625C306.203 596.01 306.297 596.443 306.297 596.922C306.297 597.531 306.128 598.083 305.789 598.578C305.451 599.068 304.979 599.453 304.375 599.734C303.776 600.016 303.104 600.156 302.359 600.156ZM308.531 603.203H307.375L308.234 598.953H309.75L308.531 603.203ZM315.516 600.156C314.734 600.156 314.039 600.021 313.43 599.75C312.82 599.479 312.346 599.104 312.008 598.625C311.669 598.146 311.5 597.604 311.5 597C311.5 596.521 311.602 596.073 311.805 595.656C312.008 595.24 312.284 594.898 312.633 594.633C312.982 594.362 313.37 594.193 313.797 594.125V594.062C313.427 593.979 313.102 593.815 312.82 593.57C312.544 593.326 312.328 593.026 312.172 592.672C312.016 592.318 311.938 591.938 311.938 591.531C311.938 590.964 312.091 590.453 312.398 590C312.706 589.542 313.13 589.182 313.672 588.922C314.219 588.661 314.833 588.531 315.516 588.531C316.193 588.531 316.805 588.661 317.352 588.922C317.898 589.182 318.326 589.542 318.633 590C318.945 590.453 319.104 590.964 319.109 591.531C319.104 591.938 319.021 592.318 318.859 592.672C318.703 593.026 318.484 593.326 318.203 593.57C317.922 593.815 317.599 593.979 317.234 594.062V594.125C317.656 594.193 318.042 594.362 318.391 594.633C318.745 594.898 319.023 595.24 319.227 595.656C319.435 596.073 319.542 596.521 319.547 597C319.542 597.604 319.367 598.146 319.023 598.625C318.685 599.104 318.208 599.479 317.594 599.75C316.984 600.021 316.292 600.156 315.516 600.156ZM315.516 598.922C316.047 598.922 316.51 598.836 316.906 598.664C317.302 598.492 317.607 598.258 317.82 597.961C318.034 597.664 318.141 597.318 318.141 596.922C318.141 596.51 318.029 596.141 317.805 595.812C317.581 595.479 317.268 595.219 316.867 595.031C316.466 594.844 316.016 594.75 315.516 594.75C315.016 594.75 314.568 594.844 314.172 595.031C313.776 595.219 313.464 595.479 313.234 595.812C313.01 596.141 312.901 596.51 312.906 596.922C312.901 597.318 313.003 597.664 313.211 597.961C313.424 598.258 313.727 598.492 314.117 598.664C314.513 598.836 314.979 598.922 315.516 598.922ZM315.516 593.562C315.943 593.562 316.326 593.479 316.664 593.312C317.003 593.146 317.266 592.919 317.453 592.633C317.641 592.346 317.734 592.016 317.734 591.641C317.734 591.266 317.643 590.935 317.461 590.648C317.279 590.362 317.018 590.141 316.68 589.984C316.341 589.828 315.953 589.75 315.516 589.75C315.073 589.75 314.685 589.828 314.352 589.984C314.023 590.141 313.766 590.362 313.578 590.648C313.391 590.935 313.297 591.266 313.297 591.641C313.297 592.016 313.393 592.346 313.586 592.633C313.779 592.919 314.042 593.146 314.375 593.312C314.708 593.479 315.089 593.562 315.516 593.562ZM325.125 600.156C324.453 600.156 323.841 600.026 323.289 599.766C322.742 599.505 322.305 599.148 321.977 598.695C321.654 598.242 321.479 597.729 321.453 597.156H322.812C322.844 597.49 322.966 597.789 323.18 598.055C323.393 598.32 323.669 598.531 324.008 598.688C324.352 598.844 324.724 598.922 325.125 598.922C325.609 598.922 326.042 598.812 326.422 598.594C326.807 598.375 327.109 598.076 327.328 597.695C327.547 597.315 327.656 596.891 327.656 596.422C327.656 595.938 327.544 595.503 327.32 595.117C327.096 594.727 326.784 594.419 326.383 594.195C325.982 593.971 325.531 593.859 325.031 593.859C324.536 593.849 324.112 593.927 323.758 594.094C323.404 594.255 323.125 594.516 322.922 594.875H321.562L322.359 588.688H328.484V589.938H323.531L323.109 593.25H323.219C323.479 593.052 323.789 592.893 324.148 592.773C324.513 592.654 324.891 592.594 325.281 592.594C325.99 592.594 326.63 592.755 327.203 593.078C327.776 593.401 328.224 593.854 328.547 594.438C328.87 595.016 329.031 595.667 329.031 596.391C329.031 597.109 328.862 597.755 328.523 598.328C328.185 598.901 327.719 599.349 327.125 599.672C326.536 599.995 325.87 600.156 325.125 600.156ZM334.688 600.156C333.854 600.156 333.143 599.93 332.555 599.477C331.966 599.023 331.516 598.362 331.203 597.492C330.891 596.622 330.734 595.573 330.734 594.344C330.734 593.13 330.891 592.089 331.203 591.219C331.516 590.344 331.966 589.677 332.555 589.219C333.148 588.76 333.859 588.531 334.688 588.531C335.51 588.531 336.219 588.76 336.812 589.219C337.406 589.677 337.859 590.344 338.172 591.219C338.484 592.089 338.641 593.13 338.641 594.344C338.641 595.573 338.487 596.622 338.18 597.492C337.872 598.362 337.422 599.023 336.828 599.477C336.234 599.93 335.521 600.156 334.688 600.156ZM334.688 598.906C335.229 598.906 335.695 598.729 336.086 598.375C336.477 598.021 336.771 597.503 336.969 596.82C337.167 596.138 337.266 595.312 337.266 594.344C337.266 593.375 337.164 592.547 336.961 591.859C336.758 591.172 336.464 590.648 336.078 590.289C335.693 589.93 335.229 589.75 334.688 589.75C334.146 589.75 333.682 589.93 333.297 590.289C332.911 590.648 332.615 591.172 332.406 591.859C332.198 592.547 332.094 593.375 332.094 594.344C332.094 595.312 332.198 596.138 332.406 596.82C332.615 597.503 332.909 598.021 333.289 598.375C333.674 598.729 334.141 598.906 334.688 598.906ZM349.266 597.453H348.031V594.359H349.266V597.453ZM355.484 597.938H354.25V587.391H355.484V597.938ZM355.828 600.969H345.953V599.938H355.828V600.969ZM347.188 600.234H345.953V596.906H347.188V600.234ZM343.953 593.828C345.812 593.818 347.458 593.789 348.891 593.742C350.323 593.69 351.693 593.583 353 593.422L353.078 594.312C351.729 594.526 350.315 594.667 348.836 594.734C347.357 594.802 345.786 594.833 344.125 594.828L343.953 593.828ZM354.578 596.5H351.375V595.609H354.578V596.5ZM348.516 587.953C349.188 587.953 349.784 588.052 350.305 588.25C350.831 588.448 351.237 588.732 351.523 589.102C351.81 589.471 351.953 589.896 351.953 590.375C351.953 590.865 351.81 591.289 351.523 591.648C351.237 592.008 350.833 592.286 350.312 592.484C349.792 592.682 349.193 592.781 348.516 592.781C347.833 592.781 347.232 592.682 346.711 592.484C346.195 592.286 345.794 592.008 345.508 591.648C345.221 591.289 345.078 590.865 345.078 590.375C345.078 589.896 345.221 589.471 345.508 589.102C345.794 588.732 346.198 588.448 346.719 588.25C347.24 588.052 347.839 587.953 348.516 587.953ZM348.516 588.891C348.068 588.885 347.672 588.945 347.328 589.07C346.984 589.19 346.716 589.365 346.523 589.594C346.336 589.823 346.245 590.083 346.25 590.375C346.245 590.672 346.336 590.935 346.523 591.164C346.716 591.388 346.984 591.562 347.328 591.688C347.672 591.812 348.068 591.875 348.516 591.875C348.953 591.875 349.344 591.812 349.688 591.688C350.031 591.562 350.299 591.388 350.492 591.164C350.685 590.935 350.781 590.672 350.781 590.375C350.781 590.083 350.685 589.823 350.492 589.594C350.299 589.365 350.031 589.19 349.688 589.07C349.344 588.945 348.953 588.885 348.516 588.891Z" fill="#56555A"/> +<path d="M376 590L380 594L376 598" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +<path d="M390 622H40C35.5817 622 32 625.582 32 630V654C32 658.418 35.5817 662 40 662H390C394.418 662 398 658.418 398 654V630C398 625.582 394.418 622 390 622Z" fill="white"/> +<path d="M53.6016 638.031C53.5964 638.938 53.4401 639.789 53.1328 640.586C52.8307 641.378 52.3724 642.07 51.7578 642.664C51.1432 643.258 50.3958 643.701 49.5156 643.992L48.4844 642.43C49.2448 642.19 49.8828 641.841 50.3984 641.383C50.9193 640.924 51.3047 640.409 51.5547 639.836C51.8099 639.258 51.9375 638.656 51.9375 638.031V636.789H53.6016V638.031ZM53.9609 638.031C53.9609 638.62 54.0833 639.185 54.3281 639.727C54.5781 640.268 54.9583 640.755 55.4688 641.188C55.9792 641.615 56.6068 641.94 57.3516 642.164L56.3438 643.734C55.474 643.453 54.7396 643.031 54.1406 642.469C53.5417 641.901 53.0885 641.237 52.7812 640.477C52.4792 639.716 52.3307 638.901 52.3359 638.031V636.789H53.9609V638.031ZM56.8281 637.828H49.0078V636.234H56.8281V637.828ZM60.3203 645.508H58.3281V635.234H60.3203V645.508ZM60.7109 649.195H50.7969V647.586H60.7109V649.195ZM52.8125 648.391H50.7969V644.57H52.8125V648.391ZM74.6406 638.609H62.8047V637.016H74.6406V638.609ZM75.2578 647.992H62.2578V646.383H75.2578V647.992ZM69.7031 647.008H67.7266V644.469H69.7031V647.008ZM68.7188 639.227C69.6979 639.227 70.5521 639.336 71.2812 639.555C72.0156 639.773 72.5781 640.094 72.9688 640.516C73.3646 640.932 73.5625 641.424 73.5625 641.992C73.5625 642.57 73.3646 643.07 72.9688 643.492C72.5781 643.909 72.0182 644.232 71.2891 644.461C70.5599 644.685 69.7031 644.799 68.7188 644.805C67.7188 644.799 66.8542 644.685 66.125 644.461C65.3958 644.232 64.8333 643.909 64.4375 643.492C64.0469 643.07 63.8542 642.57 63.8594 641.992C63.8542 641.419 64.0469 640.924 64.4375 640.508C64.8333 640.091 65.3958 639.773 66.125 639.555C66.8594 639.336 67.724 639.227 68.7188 639.227ZM68.7188 640.781C68.0938 640.786 67.5729 640.833 67.1562 640.922C66.7448 641.005 66.4323 641.138 66.2188 641.32C66.0052 641.497 65.901 641.721 65.9062 641.992C65.901 642.263 66.0052 642.49 66.2188 642.672C66.4323 642.849 66.7448 642.984 67.1562 643.078C67.5729 643.167 68.0938 643.211 68.7188 643.211C69.3281 643.211 69.8385 643.167 70.25 643.078C70.6667 642.984 70.9818 642.849 71.1953 642.672C71.4089 642.49 71.5156 642.263 71.5156 641.992C71.5156 641.721 71.4089 641.497 71.1953 641.32C70.9818 641.138 70.6667 641.005 70.25 640.922C69.8385 640.833 69.3281 640.786 68.7188 640.781ZM69.7031 638.008H67.7266V635.359H69.7031V638.008Z" fill="#56555A"/> +<path d="M289.047 646.969L292.906 642.906C293.411 642.365 293.797 641.927 294.062 641.594C294.333 641.26 294.539 640.943 294.68 640.641C294.82 640.333 294.891 640.01 294.891 639.672C294.891 639.292 294.792 638.958 294.594 638.672C294.396 638.38 294.125 638.154 293.781 637.992C293.443 637.831 293.062 637.75 292.641 637.75C292.198 637.75 291.81 637.839 291.477 638.016C291.148 638.193 290.893 638.443 290.711 638.766C290.529 639.083 290.438 639.453 290.438 639.875H289.109C289.104 639.219 289.255 638.638 289.562 638.133C289.875 637.628 290.305 637.234 290.852 636.953C291.398 636.672 292.01 636.531 292.688 636.531C293.359 636.531 293.961 636.669 294.492 636.945C295.029 637.221 295.448 637.599 295.75 638.078C296.052 638.557 296.203 639.089 296.203 639.672C296.198 640.104 296.117 640.518 295.961 640.914C295.81 641.305 295.549 641.74 295.18 642.219C294.81 642.698 294.286 643.286 293.609 643.984L291.016 646.656V646.75H296.406V648H289.062L289.047 646.969ZM302.359 648.156C301.615 648.156 300.948 648.031 300.359 647.781C299.776 647.531 299.312 647.18 298.969 646.727C298.625 646.268 298.443 645.745 298.422 645.156H299.844C299.87 645.51 299.995 645.818 300.219 646.078C300.448 646.339 300.745 646.542 301.109 646.688C301.479 646.833 301.891 646.906 302.344 646.906C302.839 646.906 303.281 646.823 303.672 646.656C304.068 646.49 304.375 646.255 304.594 645.953C304.812 645.651 304.922 645.307 304.922 644.922C304.917 644.51 304.807 644.146 304.594 643.828C304.385 643.505 304.073 643.255 303.656 643.078C303.24 642.901 302.745 642.812 302.172 642.812H301.25V641.578H302.172C302.625 641.578 303.029 641.497 303.383 641.336C303.742 641.174 304.018 640.948 304.211 640.656C304.404 640.359 304.5 640.021 304.5 639.641C304.5 639.266 304.414 638.935 304.242 638.648C304.07 638.362 303.826 638.141 303.508 637.984C303.19 637.828 302.818 637.75 302.391 637.75C301.984 637.755 301.604 637.831 301.25 637.977C300.896 638.117 300.607 638.323 300.383 638.594C300.159 638.859 300.036 639.172 300.016 639.531H298.656C298.677 638.948 298.859 638.427 299.203 637.969C299.547 637.51 300 637.156 300.562 636.906C301.125 636.656 301.74 636.531 302.406 636.531C303.104 636.531 303.716 636.669 304.242 636.945C304.768 637.221 305.169 637.591 305.445 638.055C305.727 638.518 305.865 639.021 305.859 639.562C305.865 639.984 305.789 640.37 305.633 640.719C305.482 641.062 305.26 641.354 304.969 641.594C304.677 641.833 304.333 642.01 303.938 642.125V642.203C304.422 642.276 304.841 642.435 305.195 642.68C305.555 642.924 305.828 643.24 306.016 643.625C306.203 644.01 306.297 644.443 306.297 644.922C306.297 645.531 306.128 646.083 305.789 646.578C305.451 647.068 304.979 647.453 304.375 647.734C303.776 648.016 303.104 648.156 302.359 648.156ZM308.531 651.203H307.375L308.234 646.953H309.75L308.531 651.203ZM315.516 648.156C314.734 648.156 314.039 648.021 313.43 647.75C312.82 647.479 312.346 647.104 312.008 646.625C311.669 646.146 311.5 645.604 311.5 645C311.5 644.521 311.602 644.073 311.805 643.656C312.008 643.24 312.284 642.898 312.633 642.633C312.982 642.362 313.37 642.193 313.797 642.125V642.062C313.427 641.979 313.102 641.815 312.82 641.57C312.544 641.326 312.328 641.026 312.172 640.672C312.016 640.318 311.938 639.938 311.938 639.531C311.938 638.964 312.091 638.453 312.398 638C312.706 637.542 313.13 637.182 313.672 636.922C314.219 636.661 314.833 636.531 315.516 636.531C316.193 636.531 316.805 636.661 317.352 636.922C317.898 637.182 318.326 637.542 318.633 638C318.945 638.453 319.104 638.964 319.109 639.531C319.104 639.938 319.021 640.318 318.859 640.672C318.703 641.026 318.484 641.326 318.203 641.57C317.922 641.815 317.599 641.979 317.234 642.062V642.125C317.656 642.193 318.042 642.362 318.391 642.633C318.745 642.898 319.023 643.24 319.227 643.656C319.435 644.073 319.542 644.521 319.547 645C319.542 645.604 319.367 646.146 319.023 646.625C318.685 647.104 318.208 647.479 317.594 647.75C316.984 648.021 316.292 648.156 315.516 648.156ZM315.516 646.922C316.047 646.922 316.51 646.836 316.906 646.664C317.302 646.492 317.607 646.258 317.82 645.961C318.034 645.664 318.141 645.318 318.141 644.922C318.141 644.51 318.029 644.141 317.805 643.812C317.581 643.479 317.268 643.219 316.867 643.031C316.466 642.844 316.016 642.75 315.516 642.75C315.016 642.75 314.568 642.844 314.172 643.031C313.776 643.219 313.464 643.479 313.234 643.812C313.01 644.141 312.901 644.51 312.906 644.922C312.901 645.318 313.003 645.664 313.211 645.961C313.424 646.258 313.727 646.492 314.117 646.664C314.513 646.836 314.979 646.922 315.516 646.922ZM315.516 641.562C315.943 641.562 316.326 641.479 316.664 641.312C317.003 641.146 317.266 640.919 317.453 640.633C317.641 640.346 317.734 640.016 317.734 639.641C317.734 639.266 317.643 638.935 317.461 638.648C317.279 638.362 317.018 638.141 316.68 637.984C316.341 637.828 315.953 637.75 315.516 637.75C315.073 637.75 314.685 637.828 314.352 637.984C314.023 638.141 313.766 638.362 313.578 638.648C313.391 638.935 313.297 639.266 313.297 639.641C313.297 640.016 313.393 640.346 313.586 640.633C313.779 640.919 314.042 641.146 314.375 641.312C314.708 641.479 315.089 641.562 315.516 641.562ZM325.125 648.156C324.453 648.156 323.841 648.026 323.289 647.766C322.742 647.505 322.305 647.148 321.977 646.695C321.654 646.242 321.479 645.729 321.453 645.156H322.812C322.844 645.49 322.966 645.789 323.18 646.055C323.393 646.32 323.669 646.531 324.008 646.688C324.352 646.844 324.724 646.922 325.125 646.922C325.609 646.922 326.042 646.812 326.422 646.594C326.807 646.375 327.109 646.076 327.328 645.695C327.547 645.315 327.656 644.891 327.656 644.422C327.656 643.938 327.544 643.503 327.32 643.117C327.096 642.727 326.784 642.419 326.383 642.195C325.982 641.971 325.531 641.859 325.031 641.859C324.536 641.849 324.112 641.927 323.758 642.094C323.404 642.255 323.125 642.516 322.922 642.875H321.562L322.359 636.688H328.484V637.938H323.531L323.109 641.25H323.219C323.479 641.052 323.789 640.893 324.148 640.773C324.513 640.654 324.891 640.594 325.281 640.594C325.99 640.594 326.63 640.755 327.203 641.078C327.776 641.401 328.224 641.854 328.547 642.438C328.87 643.016 329.031 643.667 329.031 644.391C329.031 645.109 328.862 645.755 328.523 646.328C328.185 646.901 327.719 647.349 327.125 647.672C326.536 647.995 325.87 648.156 325.125 648.156ZM334.688 648.156C333.854 648.156 333.143 647.93 332.555 647.477C331.966 647.023 331.516 646.362 331.203 645.492C330.891 644.622 330.734 643.573 330.734 642.344C330.734 641.13 330.891 640.089 331.203 639.219C331.516 638.344 331.966 637.677 332.555 637.219C333.148 636.76 333.859 636.531 334.688 636.531C335.51 636.531 336.219 636.76 336.812 637.219C337.406 637.677 337.859 638.344 338.172 639.219C338.484 640.089 338.641 641.13 338.641 642.344C338.641 643.573 338.487 644.622 338.18 645.492C337.872 646.362 337.422 647.023 336.828 647.477C336.234 647.93 335.521 648.156 334.688 648.156ZM334.688 646.906C335.229 646.906 335.695 646.729 336.086 646.375C336.477 646.021 336.771 645.503 336.969 644.82C337.167 644.138 337.266 643.312 337.266 642.344C337.266 641.375 337.164 640.547 336.961 639.859C336.758 639.172 336.464 638.648 336.078 638.289C335.693 637.93 335.229 637.75 334.688 637.75C334.146 637.75 333.682 637.93 333.297 638.289C332.911 638.648 332.615 639.172 332.406 639.859C332.198 640.547 332.094 641.375 332.094 642.344C332.094 643.312 332.198 644.138 332.406 644.82C332.615 645.503 332.909 646.021 333.289 646.375C333.674 646.729 334.141 646.906 334.688 646.906ZM349.266 645.453H348.031V642.359H349.266V645.453ZM355.484 645.938H354.25V635.391H355.484V645.938ZM355.828 648.969H345.953V647.938H355.828V648.969ZM347.188 648.234H345.953V644.906H347.188V648.234ZM343.953 641.828C345.812 641.818 347.458 641.789 348.891 641.742C350.323 641.69 351.693 641.583 353 641.422L353.078 642.312C351.729 642.526 350.315 642.667 348.836 642.734C347.357 642.802 345.786 642.833 344.125 642.828L343.953 641.828ZM354.578 644.5H351.375V643.609H354.578V644.5ZM348.516 635.953C349.188 635.953 349.784 636.052 350.305 636.25C350.831 636.448 351.237 636.732 351.523 637.102C351.81 637.471 351.953 637.896 351.953 638.375C351.953 638.865 351.81 639.289 351.523 639.648C351.237 640.008 350.833 640.286 350.312 640.484C349.792 640.682 349.193 640.781 348.516 640.781C347.833 640.781 347.232 640.682 346.711 640.484C346.195 640.286 345.794 640.008 345.508 639.648C345.221 639.289 345.078 638.865 345.078 638.375C345.078 637.896 345.221 637.471 345.508 637.102C345.794 636.732 346.198 636.448 346.719 636.25C347.24 636.052 347.839 635.953 348.516 635.953ZM348.516 636.891C348.068 636.885 347.672 636.945 347.328 637.07C346.984 637.19 346.716 637.365 346.523 637.594C346.336 637.823 346.245 638.083 346.25 638.375C346.245 638.672 346.336 638.935 346.523 639.164C346.716 639.388 346.984 639.562 347.328 639.688C347.672 639.812 348.068 639.875 348.516 639.875C348.953 639.875 349.344 639.812 349.688 639.688C350.031 639.562 350.299 639.388 350.492 639.164C350.685 638.935 350.781 638.672 350.781 638.375C350.781 638.083 350.685 637.823 350.492 637.594C350.299 637.365 350.031 637.19 349.688 637.07C349.344 636.945 348.953 636.885 348.516 636.891Z" fill="#56555A"/> +<path d="M376 638L380 642L376 646" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +<path d="M390 670H40C35.5817 670 32 673.582 32 678V702C32 706.418 35.5817 710 40 710H390C394.418 710 398 706.418 398 702V678C398 673.582 394.418 670 390 670Z" fill="white"/> +<path d="M49.8984 692.523C51.0703 692.518 52.0183 692.497 52.7423 692.461C53.4662 692.424 54.2083 692.352 54.9688 692.242L55.1173 693.875C54.3308 694 53.5522 694.083 52.7812 694.125C52.0156 694.167 51.0547 694.185 49.8984 694.18H48.9062V692.523H49.8984ZM54.6953 686.273H50.8048V693.195H48.9062V684.711H54.6953V686.273ZM54.4219 689.961H50.2656V688.43H54.4219V689.961ZM60.75 697.438H58.8359V683.203H60.75V697.438ZM59.4688 690.328H57.0625V688.727H59.4688V690.328ZM57.6172 696.781H55.7267V683.422H57.6172V696.781ZM75.2267 692.766H62.2579V691.195H75.2267V692.766ZM69.8984 694.523H67.9297V692.344H69.8984V694.523ZM73.8125 697.195H63.7579V695.617H73.8125V697.195ZM65.7579 696.602H63.7579V693.641H65.7579V696.602ZM74.5392 685.906H62.8672V684.414H74.5392V685.906ZM68.7345 686.297C70.2605 686.297 71.4375 686.482 72.2656 686.852C73.0938 687.216 73.5079 687.747 73.5079 688.445C73.5079 688.919 73.3229 689.32 72.9531 689.648C72.5833 689.971 72.0392 690.219 71.3204 690.391C70.6069 690.562 69.7449 690.648 68.7345 690.648C67.7189 690.648 66.8542 690.562 66.1406 690.391C65.4271 690.219 64.8829 689.971 64.5079 689.648C64.1329 689.32 63.9454 688.919 63.9454 688.445C63.9454 687.747 64.3594 687.216 65.1875 686.852C66.0208 686.482 67.2032 686.297 68.7345 686.297ZM68.7345 687.688C68.0834 687.682 67.5574 687.706 67.1562 687.758C66.7553 687.81 66.4583 687.893 66.2656 688.008C66.0729 688.122 65.9793 688.268 65.9845 688.445C65.9793 688.633 66.0729 688.784 66.2656 688.898C66.4583 689.008 66.7526 689.091 67.1484 689.148C67.5495 689.201 68.0782 689.227 68.7345 689.227C69.3803 689.227 69.9011 689.201 70.297 689.148C70.6928 689.091 70.987 689.008 71.1797 688.898C71.3776 688.784 71.4767 688.633 71.4767 688.445C71.4767 688.268 71.3776 688.122 71.1797 688.008C70.987 687.893 70.6928 687.81 70.297 687.758C69.9011 687.706 69.3803 687.682 68.7345 687.688ZM69.7267 685.359H67.7267V683.141H69.7267V685.359Z" fill="#56555A"/> +<path d="M289.047 694.969L292.906 690.906C293.411 690.365 293.797 689.927 294.062 689.594C294.333 689.26 294.539 688.943 294.68 688.641C294.82 688.333 294.891 688.01 294.891 687.672C294.891 687.292 294.792 686.958 294.594 686.672C294.396 686.38 294.125 686.154 293.781 685.992C293.443 685.831 293.062 685.75 292.641 685.75C292.198 685.75 291.81 685.839 291.477 686.016C291.148 686.193 290.893 686.443 290.711 686.766C290.529 687.083 290.438 687.453 290.438 687.875H289.109C289.104 687.219 289.255 686.638 289.562 686.133C289.875 685.628 290.305 685.234 290.852 684.953C291.398 684.672 292.01 684.531 292.688 684.531C293.359 684.531 293.961 684.669 294.492 684.945C295.029 685.221 295.448 685.599 295.75 686.078C296.052 686.557 296.203 687.089 296.203 687.672C296.198 688.104 296.117 688.518 295.961 688.914C295.81 689.305 295.549 689.74 295.18 690.219C294.81 690.698 294.286 691.286 293.609 691.984L291.016 694.656V694.75H296.406V696H289.062L289.047 694.969ZM302.359 696.156C301.615 696.156 300.948 696.031 300.359 695.781C299.776 695.531 299.312 695.18 298.969 694.727C298.625 694.268 298.443 693.745 298.422 693.156H299.844C299.87 693.51 299.995 693.818 300.219 694.078C300.448 694.339 300.745 694.542 301.109 694.688C301.479 694.833 301.891 694.906 302.344 694.906C302.839 694.906 303.281 694.823 303.672 694.656C304.068 694.49 304.375 694.255 304.594 693.953C304.812 693.651 304.922 693.307 304.922 692.922C304.917 692.51 304.807 692.146 304.594 691.828C304.385 691.505 304.073 691.255 303.656 691.078C303.24 690.901 302.745 690.812 302.172 690.812H301.25V689.578H302.172C302.625 689.578 303.029 689.497 303.383 689.336C303.742 689.174 304.018 688.948 304.211 688.656C304.404 688.359 304.5 688.021 304.5 687.641C304.5 687.266 304.414 686.935 304.242 686.648C304.07 686.362 303.826 686.141 303.508 685.984C303.19 685.828 302.818 685.75 302.391 685.75C301.984 685.755 301.604 685.831 301.25 685.977C300.896 686.117 300.607 686.323 300.383 686.594C300.159 686.859 300.036 687.172 300.016 687.531H298.656C298.677 686.948 298.859 686.427 299.203 685.969C299.547 685.51 300 685.156 300.562 684.906C301.125 684.656 301.74 684.531 302.406 684.531C303.104 684.531 303.716 684.669 304.242 684.945C304.768 685.221 305.169 685.591 305.445 686.055C305.727 686.518 305.865 687.021 305.859 687.562C305.865 687.984 305.789 688.37 305.633 688.719C305.482 689.062 305.26 689.354 304.969 689.594C304.677 689.833 304.333 690.01 303.938 690.125V690.203C304.422 690.276 304.841 690.435 305.195 690.68C305.555 690.924 305.828 691.24 306.016 691.625C306.203 692.01 306.297 692.443 306.297 692.922C306.297 693.531 306.128 694.083 305.789 694.578C305.451 695.068 304.979 695.453 304.375 695.734C303.776 696.016 303.104 696.156 302.359 696.156ZM308.531 699.203H307.375L308.234 694.953H309.75L308.531 699.203ZM315.516 696.156C314.734 696.156 314.039 696.021 313.43 695.75C312.82 695.479 312.346 695.104 312.008 694.625C311.669 694.146 311.5 693.604 311.5 693C311.5 692.521 311.602 692.073 311.805 691.656C312.008 691.24 312.284 690.898 312.633 690.633C312.982 690.362 313.37 690.193 313.797 690.125V690.062C313.427 689.979 313.102 689.815 312.82 689.57C312.544 689.326 312.328 689.026 312.172 688.672C312.016 688.318 311.938 687.938 311.938 687.531C311.938 686.964 312.091 686.453 312.398 686C312.706 685.542 313.13 685.182 313.672 684.922C314.219 684.661 314.833 684.531 315.516 684.531C316.193 684.531 316.805 684.661 317.352 684.922C317.898 685.182 318.326 685.542 318.633 686C318.945 686.453 319.104 686.964 319.109 687.531C319.104 687.938 319.021 688.318 318.859 688.672C318.703 689.026 318.484 689.326 318.203 689.57C317.922 689.815 317.599 689.979 317.234 690.062V690.125C317.656 690.193 318.042 690.362 318.391 690.633C318.745 690.898 319.023 691.24 319.227 691.656C319.435 692.073 319.542 692.521 319.547 693C319.542 693.604 319.367 694.146 319.023 694.625C318.685 695.104 318.208 695.479 317.594 695.75C316.984 696.021 316.292 696.156 315.516 696.156ZM315.516 694.922C316.047 694.922 316.51 694.836 316.906 694.664C317.302 694.492 317.607 694.258 317.82 693.961C318.034 693.664 318.141 693.318 318.141 692.922C318.141 692.51 318.029 692.141 317.805 691.812C317.581 691.479 317.268 691.219 316.867 691.031C316.466 690.844 316.016 690.75 315.516 690.75C315.016 690.75 314.568 690.844 314.172 691.031C313.776 691.219 313.464 691.479 313.234 691.812C313.01 692.141 312.901 692.51 312.906 692.922C312.901 693.318 313.003 693.664 313.211 693.961C313.424 694.258 313.727 694.492 314.117 694.664C314.513 694.836 314.979 694.922 315.516 694.922ZM315.516 689.562C315.943 689.562 316.326 689.479 316.664 689.312C317.003 689.146 317.266 688.919 317.453 688.633C317.641 688.346 317.734 688.016 317.734 687.641C317.734 687.266 317.643 686.935 317.461 686.648C317.279 686.362 317.018 686.141 316.68 685.984C316.341 685.828 315.953 685.75 315.516 685.75C315.073 685.75 314.685 685.828 314.352 685.984C314.023 686.141 313.766 686.362 313.578 686.648C313.391 686.935 313.297 687.266 313.297 687.641C313.297 688.016 313.393 688.346 313.586 688.633C313.779 688.919 314.042 689.146 314.375 689.312C314.708 689.479 315.089 689.562 315.516 689.562ZM325.125 696.156C324.453 696.156 323.841 696.026 323.289 695.766C322.742 695.505 322.305 695.148 321.977 694.695C321.654 694.242 321.479 693.729 321.453 693.156H322.812C322.844 693.49 322.966 693.789 323.18 694.055C323.393 694.32 323.669 694.531 324.008 694.688C324.352 694.844 324.724 694.922 325.125 694.922C325.609 694.922 326.042 694.812 326.422 694.594C326.807 694.375 327.109 694.076 327.328 693.695C327.547 693.315 327.656 692.891 327.656 692.422C327.656 691.938 327.544 691.503 327.32 691.117C327.096 690.727 326.784 690.419 326.383 690.195C325.982 689.971 325.531 689.859 325.031 689.859C324.536 689.849 324.112 689.927 323.758 690.094C323.404 690.255 323.125 690.516 322.922 690.875H321.562L322.359 684.688H328.484V685.938H323.531L323.109 689.25H323.219C323.479 689.052 323.789 688.893 324.148 688.773C324.513 688.654 324.891 688.594 325.281 688.594C325.99 688.594 326.63 688.755 327.203 689.078C327.776 689.401 328.224 689.854 328.547 690.438C328.87 691.016 329.031 691.667 329.031 692.391C329.031 693.109 328.862 693.755 328.523 694.328C328.185 694.901 327.719 695.349 327.125 695.672C326.536 695.995 325.87 696.156 325.125 696.156ZM334.688 696.156C333.854 696.156 333.143 695.93 332.555 695.477C331.966 695.023 331.516 694.362 331.203 693.492C330.891 692.622 330.734 691.573 330.734 690.344C330.734 689.13 330.891 688.089 331.203 687.219C331.516 686.344 331.966 685.677 332.555 685.219C333.148 684.76 333.859 684.531 334.688 684.531C335.51 684.531 336.219 684.76 336.812 685.219C337.406 685.677 337.859 686.344 338.172 687.219C338.484 688.089 338.641 689.13 338.641 690.344C338.641 691.573 338.487 692.622 338.18 693.492C337.872 694.362 337.422 695.023 336.828 695.477C336.234 695.93 335.521 696.156 334.688 696.156ZM334.688 694.906C335.229 694.906 335.695 694.729 336.086 694.375C336.477 694.021 336.771 693.503 336.969 692.82C337.167 692.138 337.266 691.312 337.266 690.344C337.266 689.375 337.164 688.547 336.961 687.859C336.758 687.172 336.464 686.648 336.078 686.289C335.693 685.93 335.229 685.75 334.688 685.75C334.146 685.75 333.682 685.93 333.297 686.289C332.911 686.648 332.615 687.172 332.406 687.859C332.198 688.547 332.094 689.375 332.094 690.344C332.094 691.312 332.198 692.138 332.406 692.82C332.615 693.503 332.909 694.021 333.289 694.375C333.674 694.729 334.141 694.906 334.688 694.906ZM349.266 693.453H348.031V690.359H349.266V693.453ZM355.484 693.938H354.25V683.391H355.484V693.938ZM355.828 696.969H345.953V695.938H355.828V696.969ZM347.188 696.234H345.953V692.906H347.188V696.234ZM343.953 689.828C345.812 689.818 347.458 689.789 348.891 689.742C350.323 689.69 351.693 689.583 353 689.422L353.078 690.312C351.729 690.526 350.315 690.667 348.836 690.734C347.357 690.802 345.786 690.833 344.125 690.828L343.953 689.828ZM354.578 692.5H351.375V691.609H354.578V692.5ZM348.516 683.953C349.188 683.953 349.784 684.052 350.305 684.25C350.831 684.448 351.237 684.732 351.523 685.102C351.81 685.471 351.953 685.896 351.953 686.375C351.953 686.865 351.81 687.289 351.523 687.648C351.237 688.008 350.833 688.286 350.312 688.484C349.792 688.682 349.193 688.781 348.516 688.781C347.833 688.781 347.232 688.682 346.711 688.484C346.195 688.286 345.794 688.008 345.508 687.648C345.221 687.289 345.078 686.865 345.078 686.375C345.078 685.896 345.221 685.471 345.508 685.102C345.794 684.732 346.198 684.448 346.719 684.25C347.24 684.052 347.839 683.953 348.516 683.953ZM348.516 684.891C348.068 684.885 347.672 684.945 347.328 685.07C346.984 685.19 346.716 685.365 346.523 685.594C346.336 685.823 346.245 686.083 346.25 686.375C346.245 686.672 346.336 686.935 346.523 687.164C346.716 687.388 346.984 687.562 347.328 687.688C347.672 687.812 348.068 687.875 348.516 687.875C348.953 687.875 349.344 687.812 349.688 687.688C350.031 687.562 350.299 687.388 350.492 687.164C350.685 686.935 350.781 686.672 350.781 686.375C350.781 686.083 350.685 685.823 350.492 685.594C350.299 685.365 350.031 685.19 349.688 685.07C349.344 684.945 348.953 684.885 348.516 684.891Z" fill="#56555A"/> +<path d="M376 686L380 690L376 694" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> +</g> +</g> +<mask id="mask3_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="426" y="221" width="3" height="105"> +<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="white"/> +</mask> +<g mask="url(#mask3_1837_11068)"> +<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="url(#paint0_linear_1837_11068)"/> +</g> +<mask id="mask4_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="428" y="221" width="2" height="105"> +<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="white"/> +</mask> +<g mask="url(#mask4_1837_11068)"> +<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="url(#paint1_linear_1837_11068)"/> +</g> +<mask id="mask5_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="3" height="67"> +<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="white"/> +</mask> +<g mask="url(#mask5_1837_11068)"> +<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="url(#paint2_linear_1837_11068)"/> +</g> +<mask id="mask6_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="1" height="67"> +<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.353 0 200.307L0.706443 199.447V265.633V265.637Z" fill="white"/> +</mask> +<g mask="url(#mask6_1837_11068)"> +<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.353 0 200.307L0.706443 199.447V265.633V265.637Z" fill="url(#paint3_linear_1837_11068)"/> +</g> +<mask id="mask7_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="199" width="2" height="67"> +<path d="M2.11914 265.652H3.63295V199.447H2.11914V265.652Z" fill="white"/> +</mask> +<g mask="url(#mask7_1837_11068)"> +<path d="M2.11914 265.652H3.63295V199.447H2.11914V265.652Z" fill="url(#paint4_linear_1837_11068)"/> +</g> +<mask id="mask8_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="3" height="67"> +<path d="M2.11943 348.925H0.706543V282.721H2.11943V348.925Z" fill="white"/> +</mask> +<g mask="url(#mask8_1837_11068)"> +<path d="M2.11943 348.925H0.706543V282.721H2.11943V348.925Z" fill="url(#paint5_linear_1837_11068)"/> +</g> +<mask id="mask9_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="1" height="67"> +<path d="M0.706443 348.929L0 348.069C0.333038 341.037 0.357259 290.645 0 283.599L0.706443 282.739V348.925V348.929Z" fill="white"/> +</mask> +<g mask="url(#mask9_1837_11068)"> +<path d="M0.706443 348.929L0 348.069C0.333038 341.037 0.357259 290.645 0 283.599L0.706443 282.739V348.925V348.929Z" fill="url(#paint6_linear_1837_11068)"/> +</g> +<mask id="mask10_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="282" width="2" height="67"> +<path d="M2.11914 348.944H3.63295V282.739H2.11914V348.944Z" fill="white"/> +</mask> +<g mask="url(#mask10_1837_11068)"> +<path d="M2.11914 348.944H3.63295V282.739H2.11914V348.944Z" fill="url(#paint7_linear_1837_11068)"/> +</g> +<mask id="mask11_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="3" height="35"> +<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="white"/> +</mask> +<g mask="url(#mask11_1837_11068)"> +<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="url(#paint8_linear_1837_11068)"/> +</g> +<mask id="mask12_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="1" height="35"> +<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="white"/> +</mask> +<g mask="url(#mask12_1837_11068)"> +<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="url(#paint9_linear_1837_11068)"/> +</g> +<mask id="mask13_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="136" width="2" height="35"> +<path d="M2.11914 170.879H3.63295V136.896H2.11914V170.879Z" fill="white"/> +</mask> +<g mask="url(#mask13_1837_11068)"> +<path d="M2.11914 170.879H3.63295V136.896H2.11914V170.879Z" fill="url(#paint10_linear_1837_11068)"/> +</g> +<path d="M246.886 60.54H179.37C171.773 60.54 165.615 54.3819 165.615 46.7846C165.615 39.1873 171.773 33.0291 179.37 33.0291H246.886C254.483 33.0291 260.641 39.1873 260.641 46.7846C260.641 54.3819 254.483 60.54 246.886 60.54ZM243.083 40.7798C239.767 40.7798 237.079 43.4683 237.079 46.7846C237.079 50.1029 239.767 52.7894 243.083 52.7894C246.4 52.7894 249.088 50.1029 249.088 46.7846C249.088 43.4683 246.4 40.7798 243.083 40.7798Z" fill="#1D1D1B"/> +<mask id="mask14_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="40" width="13" height="13"> +<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="white"/> +</mask> +<g mask="url(#mask14_1837_11068)"> +<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="url(#paint11_linear_1837_11068)"/> +</g> +<mask id="mask15_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="41" width="12" height="12"> +<path d="M243.063 52.3916C242.504 52.3916 241.943 52.3089 241.4 52.1373C240.526 51.8628 239.747 51.3804 239.117 50.7526C238.473 50.1067 238.011 49.3216 237.746 48.4779C237.294 47.0347 237.419 45.422 238.182 44.0535C238.437 43.5994 238.75 43.1836 239.115 42.8203C239.745 42.1886 240.524 41.7082 241.398 41.4317C241.941 41.2621 242.502 41.1794 243.061 41.1794C243.715 41.1794 244.367 41.2924 244.982 41.5124C245.751 41.7889 246.464 42.2289 247.053 42.8203C247.419 43.1836 247.734 43.5994 247.986 44.0535C248.749 45.422 248.874 47.0347 248.42 48.4779C248.155 49.3216 247.697 50.1067 247.051 50.7526C246.462 51.342 245.749 51.782 244.98 52.0565C244.367 52.2765 243.717 52.3916 243.063 52.3916ZM243.083 43.3532C241.19 43.3532 239.654 44.8892 239.654 46.7845C239.654 48.6798 241.19 50.2158 243.083 50.2158C244.978 50.2158 246.516 48.6798 246.516 46.7845C246.516 44.8892 244.978 43.3532 243.083 43.3532Z" fill="white"/> +</mask> +<g mask="url(#mask15_1837_11068)"> +<rect x="235.513" y="39.4111" width="14.7748" height="14.7748" fill="url(#pattern0_1837_11068)"/> +</g> +<mask id="mask16_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="239" y="43" width="8" height="8"> +<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="white"/> +</mask> +<g mask="url(#mask16_1837_11068)"> +<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="url(#paint12_linear_1837_11068)"/> +</g> +<mask id="mask17_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="240" y="43" width="7" height="7"> +<path d="M243.081 49.79C241.416 49.79 240.08 48.4459 240.08 46.7887C240.08 45.1236 241.416 43.7833 243.081 43.7833C244.74 43.7833 246.084 45.1236 246.084 46.7887C246.084 47.2631 245.973 47.7152 245.778 48.1148C245.669 47.6364 245.241 47.2812 244.732 47.2812C244.139 47.2812 243.66 47.7616 243.66 48.353C243.66 48.8818 244.042 49.3218 244.546 49.4086C244.112 49.6508 243.612 49.79 243.081 49.79Z" fill="white"/> +</mask> +<g mask="url(#mask17_1837_11068)"> +<rect x="238.337" y="42.2383" width="8.92141" height="8.92141" fill="url(#pattern1_1837_11068)"/> +</g> +<mask id="mask18_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="244" y="48" width="2" height="2"> +<path d="M244.732 49.4258C244.668 49.4258 244.607 49.4177 244.546 49.4076C245.077 49.1109 245.507 48.6588 245.778 48.1138C245.794 48.1885 245.804 48.2693 245.804 48.352C245.804 48.9434 245.324 49.4258 244.732 49.4258Z" fill="white"/> +</mask> +<g mask="url(#mask18_1837_11068)"> +<rect x="243.182" y="46.2734" width="4.07723" height="4.88459" fill="url(#pattern2_1837_11068)"/> +</g> +<mask id="mask19_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="243" y="47" width="3" height="3"> +<path d="M244.547 49.4082C244.042 49.3214 243.661 48.8814 243.661 48.3526C243.661 47.7612 244.139 47.2808 244.732 47.2808C245.241 47.2808 245.669 47.636 245.778 48.1144C245.507 48.6593 245.078 49.1115 244.547 49.4082Z" fill="white"/> +</mask> +<g mask="url(#mask19_1837_11068)"> +<rect x="242.173" y="46.2734" width="5.08643" height="4.88459" fill="url(#pattern3_1837_11068)"/> +</g> +<defs> +<pattern id="pattern0_1837_11068" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_1837_11068" transform="scale(0.0666667)"/> +</pattern> +<pattern id="pattern1_1837_11068" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image1_1837_11068" transform="scale(0.111111)"/> +</pattern> +<pattern id="pattern2_1837_11068" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image2_1837_11068" transform="scale(0.25 0.2)"/> +</pattern> +<pattern id="pattern3_1837_11068" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image3_1837_11068" transform="scale(0.2)"/> +</pattern> +<linearGradient id="paint0_linear_1837_11068" x1="427.525" y1="221.428" x2="427.525" y2="325.938" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2B1D2A"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2B1D2A"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint1_linear_1837_11068" x1="429.38" y1="221.455" x2="429.38" y2="325.943" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint2_linear_1837_11068" x1="1.41299" y1="199.429" x2="1.41299" y2="265.633" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint3_linear_1837_11068" x1="0.353221" y1="199.447" x2="0.353221" y2="265.637" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint4_linear_1837_11068" x1="2.87604" y1="265.652" x2="2.87604" y2="199.445" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint5_linear_1837_11068" x1="1.41299" y1="282.721" x2="1.41299" y2="348.925" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint6_linear_1837_11068" x1="0.353221" y1="282.739" x2="0.353221" y2="348.929" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint7_linear_1837_11068" x1="2.87604" y1="348.944" x2="2.87604" y2="282.737" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint8_linear_1837_11068" x1="1.41299" y1="136.878" x2="1.41299" y2="170.859" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0185053" stop-color="#896E80"/> +<stop offset="0.0381953" stop-color="#5E3B5B"/> +<stop offset="0.0820552" stop-color="#2D1E2C"/> +<stop offset="0.105304" stop-color="#704A6A"/> +<stop offset="0.904875" stop-color="#615060"/> +<stop offset="0.939094" stop-color="#2D1E2C"/> +<stop offset="0.96458" stop-color="#5E3B5B"/> +<stop offset="0.98292" stop-color="#845675"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint9_linear_1837_11068" x1="0.353222" y1="136.895" x2="0.353222" y2="170.862" gradientUnits="userSpaceOnUse"> +<stop stop-color="#676067"/> +<stop offset="0.0640242" stop-color="#654E63"/> +<stop offset="0.186012" stop-color="#786F77"/> +<stop offset="0.806376" stop-color="#786F77"/> +<stop offset="0.919115" stop-color="#654E63"/> +<stop offset="1" stop-color="#676067"/> +</linearGradient> +<linearGradient id="paint10_linear_1837_11068" x1="2.87604" y1="170.879" x2="2.87604" y2="136.895" gradientUnits="userSpaceOnUse"> +<stop stop-color="#68595F"/> +<stop offset="0.0530612" stop-color="#2D1E2C"/> +<stop offset="0.518367" stop-color="#5E3B5B"/> +<stop offset="0.96458" stop-color="#2D1E2C"/> +<stop offset="1" stop-color="#5B4A5C"/> +</linearGradient> +<linearGradient id="paint11_linear_1837_11068" x1="243.083" y1="52.4197" x2="243.083" y2="40.5892" gradientUnits="userSpaceOnUse"> +<stop stop-color="#666666"/> +<stop offset="1" stop-color="#010104"/> +</linearGradient> +<linearGradient id="paint12_linear_1837_11068" x1="243.083" y1="43.5652" x2="243.083" y2="50.325" gradientUnits="userSpaceOnUse"> +<stop stop-color="#0B131C"/> +<stop offset="1" stop-color="#354039"/> +</linearGradient> +<clipPath id="clip0_1837_11068"> +<rect width="382" height="827" fill="white" transform="translate(24 20)"/> +</clipPath> +<image id="image0_1837_11068" width="15" height="15" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAUBJREFUKJGFks1S3TAMhT/JshPndl8ehIH3X8LQ9m1uAP+IhXMbAs1U2nhkHR0dSfLz7s45sTRNRItYtEP8slz48/sXegb8n90/PGJnnxoCACKCqo4O7Jh+Cr6ZM1SJCuEL+LTtoIFoEdm81kop70dms/iNxbtz87C1b2aEYOAOIiOmYSd3902vYmbkJRMtEmMkpUQpdVBseSZbFWBLKExpIsaIiCIiXC4/iDHy+rrSWuO9lAFeluUvuJRCnjPIkJBzZkoJVSGEwDxn1vW6a/7K/Pk9pYSZMc8ZC4E3d1R3mWZhH7/70KOq4OCAqtJ756011nXluq47eJrnw/i9d2qt4yB8FCy1YMEIQdGt0+7+/UhEFdUxqNYq12uh9T628EkinFzY7ZJqa4d4v61ShJfnJwTw+4fHf9U4tZfnJwA+AH+jc5A39zmDAAAAAElFTkSuQmCC"/> +<image id="image1_1837_11068" width="9" height="9" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAABHNCSVQICAgIfAhkiAAAAMRJREFUGJWF0LFKA1EQheH/3GxW4qIkogSCjUGstLDQKnUqKx9CH0vs8kYhxNJCElJkCSy6985YhDUoQqb+ivmP2lnm/HOWF6SDI5Rqwj4g+4sUiJcPpPELGoyQ1SjF36i+fcavn2D9hp9c4Wc3yCJZA+LgHoaPaPqKVlP88BRvd8DSFlle4P07WM+hWsJXCXIgIjfCz5OzCVQLyAu808Ptk1C+A47onXtTIbWw7gXEDWHzQajKbY+O+95UyCJYQm7Abr5vonZV760IjhkAAAAASUVORK5CYII="/> +<image id="image2_1837_11068" width="4" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAFCAYAAABirU3bAAAABHNCSVQICAgIfAhkiAAAAEVJREFUCJljlFHV+M+ABFjY2FkYUAXYWBg8XFwZPnz8yHDi9CkGRj1Lk/+srKwMf//+Zfj37x9EBQPDfwYWFiYGBgYmBgAtwhBN2erPwAAAAABJRU5ErkJggg=="/> +<image id="image3_1837_11068" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABHNCSVQICAgIfAhkiAAAAGJJREFUCJk1wbEKglAAheH/yE0rp8A18A1samxpa+4BfNMew7EHEBPkgiBeT5PfJzWtNXT4XGES4fshMPewTCADK/JGRl7i04X368HzVgNGut7NGjkuPxxHUkooHArLG2B2f3kOIpEJnXBlAAAAAElFTkSuQmCC"/> +</defs> +</svg> diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index 33f1bfe3f..d3a1cd079 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -1,19 +1,21 @@ -import {useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; +import {MainLayout} from 'haengdong-design'; -import {Logo} from '@components/Common/Logo'; - -import {ROUTER_URLS} from '@constants/routerUrls'; +import Nav from './Nav/Nav'; +import MainSection from './Section/MainSection'; +import DescriptionSection from './Section/DescriptionSection'; +import AddBillSection from './Section/AddBillSection'; +import AddMemberSection from './Section/AddMemberSection'; +import MemberReportSection from './Section/MemberReportSection'; const MainPage = () => { - const navigate = useNavigate(); - return ( <MainLayout> - <TopNav children={<></>} /> - <Title title="행동대장" description="👑행동대장들의 행복한 행사 진행을 위해... 📢행동개시!" /> - <Logo /> - <FixedButton onClick={() => navigate(ROUTER_URLS.eventCreateName)}>행사 생성하기</FixedButton> + <Nav /> + <MainSection /> + <DescriptionSection /> + <AddBillSection /> + <AddMemberSection /> + <MemberReportSection /> </MainLayout> ); }; diff --git a/client/src/pages/MainPage/Nav/Nav.style.ts b/client/src/pages/MainPage/Nav/Nav.style.ts new file mode 100644 index 000000000..de0939bc6 --- /dev/null +++ b/client/src/pages/MainPage/Nav/Nav.style.ts @@ -0,0 +1,25 @@ +import {css} from '@emotion/react'; +import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +interface NavStyleProps {} + +export const navStyle = css({ + position: 'fixed', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '1rem', + + top: '0', + width: '100%', + zIndex: '20', + height: '4rem', + boxShadow: '0 0.25rem 0.25rem 0 rgba(0, 0, 0, 0.12)', + backgroundColor: 'white', +}); + +export const logoStyle = css({ + display: 'flex', + gap: '0.5rem', + alignItems: 'center', +}); diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx new file mode 100644 index 000000000..94d05cb4e --- /dev/null +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -0,0 +1,25 @@ +import {css} from '@emotion/react'; +import {Button, Text} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; + +import {Logo} from '@components/Common/Logo'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +import {logoStyle, navStyle} from './Nav.style'; + +const Nav = () => { + const navigate = useNavigate(); + return ( + <header css={navStyle}> + <div css={logoStyle}> + <Text size="subTitle">행동대장</Text> + </div> + <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + 정산 시작하기 + </Button> + </header> + ); +}; + +export default Nav; diff --git a/client/src/pages/MainPage/Section/AddBillSection.tsx b/client/src/pages/MainPage/Section/AddBillSection.tsx new file mode 100644 index 000000000..ecf7dd90d --- /dev/null +++ b/client/src/pages/MainPage/Section/AddBillSection.tsx @@ -0,0 +1,31 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; + +import AddBillMockup from '@assets/image/addBillMockup.svg'; + +const AddBillSection = () => { + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: 'white', + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">지출내역을 쉽게 추가하세요</Text> + <Text size="body" textColor="gray"> + {`나중에 한번에 기록할 수도 있지만, + 실시간으로 기록해 놓을 수 있어요`} + </Text> + </div> + <AddBillMockup /> + </div> + ); +}; + +export default AddBillSection; diff --git a/client/src/pages/MainPage/Section/AddMemberSection.tsx b/client/src/pages/MainPage/Section/AddMemberSection.tsx new file mode 100644 index 000000000..ae6e7d1fc --- /dev/null +++ b/client/src/pages/MainPage/Section/AddMemberSection.tsx @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; +import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +import AddMemberMockup from '@assets/image/addMemberMockup.svg'; + +const AddMemberSection = () => { + const {theme} = useTheme(); + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: theme.colors.lightGrayContainer, + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">인원 변동은 신경쓰지 마세요</Text> + <Text size="body" textColor="gray"> + {`누가 나가고 들어왔는지만 기록하세요 + 행동대장이 알아서 차수를 나눠줘요`} + </Text> + </div> + <AddMemberMockup /> + </div> + ); +}; + +export default AddMemberSection; diff --git a/client/src/pages/MainPage/Section/DescriptionSection.tsx b/client/src/pages/MainPage/Section/DescriptionSection.tsx new file mode 100644 index 000000000..193cfe465 --- /dev/null +++ b/client/src/pages/MainPage/Section/DescriptionSection.tsx @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; +import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +const DescriptionSection = () => { + const {theme} = useTheme(); + + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + gap: '1.5rem', + padding: '3rem 1.5rem', + backgroundColor: theme.colors.lightGrayContainer, + })} + > + <Text style={{textAlign: 'center'}} size="subTitle">{`행동대장들을 위해 + 행동대장을 준비했어요 + `}</Text> + <Text style={{textAlign: 'center'}} size="subTitle" textColor="gray">{`주환이가 먼저 집에 가도 + 소연이가 늦게 도착해도 + 건상이가 술을 마시지 않아도 + `}</Text> + <Text style={{textAlign: 'center'}} size="subTitle">{`간편하게 정산할 수 있어요`}</Text> + </div> + ); +}; + +export default DescriptionSection; diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx new file mode 100644 index 000000000..4f62d2e1b --- /dev/null +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -0,0 +1,93 @@ +import {css, keyframes} from '@emotion/react'; +import {Button, Text} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; + +import {Logo} from '@components/Common/Logo'; +import ChevronDown from '@assets/image/chevronDownLarge.svg'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const MainSection = () => { + const navigate = useNavigate(); + return ( + <div + css={css({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100vh', + width: '100%', + backgroundColor: 'white', + })} + > + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + gap: '2rem', + padding: '1.5rem', + height: '100vh', + width: '100%', + })} + > + <div css={animateWithDelay(0)}> + <Logo /> + </div> + <Text css={animateWithDelay(1)} style={{textAlign: 'center'}} size="title">{`행동대장을 통해 + 간편하게 정산하세요 + `}</Text> + <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + 정산 시작하기 + </Button> + </div> + <div + css={css({ + position: 'absolute', + bottom: '2rem', + left: '50%', + animation: `${bounce} 2s infinite ease-in-out`, + })} + > + <ChevronDown /> + </div> + </div> + ); +}; + +const fadeIn = keyframes` + from { + opacity: 0; + } + to { + opacity: 1; + } +`; + +const slideIn = keyframes` + from { + transform: translateY(1rem); + } + to { + transform: translateY(0); + } +`; + +const bounce = keyframes` + 0%, 100% { + transform: translate(-50%, 0); + } + 50% { + transform: translate(-50%, -1rem); + } +`; + +const animateWithDelay = (delay: number) => css` + opacity: 0; + animation: + ${fadeIn} 1s ease-in-out ${delay}s forwards, + ${slideIn} 1s ease-in-out ${delay}s forwards; +`; + +export default MainSection; diff --git a/client/src/pages/MainPage/Section/MemberReportSection.tsx b/client/src/pages/MainPage/Section/MemberReportSection.tsx new file mode 100644 index 000000000..69871e1c9 --- /dev/null +++ b/client/src/pages/MainPage/Section/MemberReportSection.tsx @@ -0,0 +1,31 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; + +import MemberReportMockup from '@assets/image/memberReportMockup.svg'; + +const MemberReportSection = () => { + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: 'white', + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">친구에게 링크를 공유하세요</Text> + <Text size="body" textColor="gray"> + {`지출내역과 인원변동을 통해 + 금액은 자동으로 계산돼요`} + </Text> + </div> + <MemberReportMockup /> + </div> + ); +}; + +export default MemberReportSection; From bc77462af3be1b0b6b893a170462d50dbb1c47b1 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:08:24 +0900 Subject: [PATCH 186/273] =?UTF-8?q?fix:=20=EB=9E=9C=EB=94=A9=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20Nav=20=EB=B2=84=EA=B7=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#438)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 사용하지 않는 import 제거 * fix: maxWidth를 추가하여 데스크탑에서 Nav가 정상적으로 렌더링되도록 수정 --- client/src/hooks/useDynamicInput.tsx | 2 +- client/src/pages/MainPage/Nav/Nav.style.ts | 1 + client/src/pages/MainPage/Nav/Nav.tsx | 3 --- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index cd639d770..01febb517 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -1,4 +1,4 @@ -import {useEffect, useRef, useState} from 'react'; +import {useEffect, useRef} from 'react'; import {ValidateResult} from '@utils/validate/type'; diff --git a/client/src/pages/MainPage/Nav/Nav.style.ts b/client/src/pages/MainPage/Nav/Nav.style.ts index de0939bc6..55d5551b4 100644 --- a/client/src/pages/MainPage/Nav/Nav.style.ts +++ b/client/src/pages/MainPage/Nav/Nav.style.ts @@ -12,6 +12,7 @@ export const navStyle = css({ top: '0', width: '100%', + maxWidth: '768px', zIndex: '20', height: '4rem', boxShadow: '0 0.25rem 0.25rem 0 rgba(0, 0, 0, 0.12)', diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index 94d05cb4e..d59517466 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -1,9 +1,6 @@ -import {css} from '@emotion/react'; import {Button, Text} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; -import {Logo} from '@components/Common/Logo'; - import {ROUTER_URLS} from '@constants/routerUrls'; import {logoStyle, navStyle} from './Nav.style'; From c68101b83d361cc3332ecb287b63f9f811bd6fdc Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:43:59 +0900 Subject: [PATCH 187/273] =?UTF-8?q?fix:=20totalPrice=EB=A5=BC=20=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EC=9A=B4=20=EC=9E=85=EB=A0=A5=EA=B0=92=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=84=98=EA=B2=A8=EC=A3=BC=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EC=95=98=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?(#442)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index 182f40bda..3ed40dea0 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -53,7 +53,7 @@ const PutAndDeleteBillActionModal = ({ } = useMemberReportInput({ data: memberReportListInAction, addAdjustedMember, - totalPrice: billAction.price, + totalPrice: Number(inputPair.price), getIsSamePriceStateAndServerState, getOnlyOneNotAdjustedRemainMemberIndex, }); From a8f0af49002e29c4869bce098170b75042bc1b55 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:57:27 +0900 Subject: [PATCH 188/273] =?UTF-8?q?fix:=20=EB=B0=B0=EA=B2=BD=EC=83=89?= =?UTF-8?q?=EC=83=81=20height=20=EB=B2=84=EA=B7=B8=20(#443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 사용하지 않는 코드 제거 * fix: 배경 heigth가 잘리는 문제를 background color를 넣어 해결 --- client/src/GlobalStyle.ts | 1 + client/src/pages/MainPage/Nav/Nav.style.ts | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index a37f2ac13..0401428cd 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -136,6 +136,7 @@ export const GlobalStyle = css` html { height: 100%; + background-color: #f1f0f5; } body { diff --git a/client/src/pages/MainPage/Nav/Nav.style.ts b/client/src/pages/MainPage/Nav/Nav.style.ts index 55d5551b4..0d2ab0432 100644 --- a/client/src/pages/MainPage/Nav/Nav.style.ts +++ b/client/src/pages/MainPage/Nav/Nav.style.ts @@ -1,7 +1,4 @@ import {css} from '@emotion/react'; -import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; - -interface NavStyleProps {} export const navStyle = css({ position: 'fixed', From e9c3f8061dee2c25df18855381146ce199c4ddd6 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:30:31 +0900 Subject: [PATCH 189/273] =?UTF-8?q?fix:=20=EB=B0=B1=EA=B7=B8=EB=9D=BC?= =?UTF-8?q?=EC=9A=B4=EB=93=9C=20=EC=88=98=EC=A0=95=20(#447)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/GlobalStyle.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index 0401428cd..ecbfdef56 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -136,7 +136,6 @@ export const GlobalStyle = css` html { height: 100%; - background-color: #f1f0f5; } body { @@ -158,5 +157,7 @@ export const GlobalStyle = css` display: flex; flex-direction: column; height: 100%; + + background-color: #f1f0f5; } `; From c1bb0c37118ae6e5c8f40675ca580c0249f7a83b Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Wed, 21 Aug 2024 17:33:22 +0900 Subject: [PATCH 190/273] =?UTF-8?q?fix:=20=EB=A9=A4=EB=B2=84=EA=B0=80=20?= =?UTF-8?q?=EB=B3=80=EB=8F=99=EB=90=90=EC=9D=84=20=EB=95=8C=20=EC=A7=80?= =?UTF-8?q?=EC=B6=9C=20=EC=83=81=EC=84=B8=20=EC=A0=95=EB=B3=B4=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EA=B0=80=20=EB=82=A0=EB=9D=BC=EA=B0=80?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#448)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/queries/useRequestDeleteAllMemberList.ts | 1 + client/src/hooks/queries/useRequestDeleteMemberAction.ts | 1 + client/src/hooks/queries/useRequestPutAllMemberList.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts index a6b761e99..38354a0fd 100644 --- a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts +++ b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts @@ -19,6 +19,7 @@ const useRequestDeleteAllMemberList = () => { onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); }, }); diff --git a/client/src/hooks/queries/useRequestDeleteMemberAction.ts b/client/src/hooks/queries/useRequestDeleteMemberAction.ts index 46ac65204..08e69ac1f 100644 --- a/client/src/hooks/queries/useRequestDeleteMemberAction.ts +++ b/client/src/hooks/queries/useRequestDeleteMemberAction.ts @@ -19,6 +19,7 @@ const useRequestDeleteMemberAction = () => { onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); }, }); diff --git a/client/src/hooks/queries/useRequestPutAllMemberList.ts b/client/src/hooks/queries/useRequestPutAllMemberList.ts index d7e25ff73..a2faf0c09 100644 --- a/client/src/hooks/queries/useRequestPutAllMemberList.ts +++ b/client/src/hooks/queries/useRequestPutAllMemberList.ts @@ -19,6 +19,7 @@ const useRequestPutAllMemberList = () => { onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); }, }); From 1ee84650aa115f2af295262738ffdc09f17090d6 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:17:47 +0900 Subject: [PATCH 191/273] =?UTF-8?q?fix:=20=EC=B0=A8=EB=93=B1=20=EC=A0=95?= =?UTF-8?q?=EC=82=B0=20=EB=AA=A8=EB=8B=AC=EC=97=90=EC=84=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EC=99=84=EB=A3=8C=20=EB=B2=84=ED=8A=BC=EC=9D=84=20?= =?UTF-8?q?=EB=88=84=EB=A5=BC=20=EB=95=8C=20=EB=B3=B4=EB=82=B4=EB=8A=94=20?= =?UTF-8?q?2=EA=B0=9C=EC=9D=98=20api=EC=9D=98=20=EC=88=9C=EC=84=9C?= =?UTF-8?q?=EB=A5=BC=20=EB=B3=B4=EC=9E=A5=ED=95=98=EA=B3=A0=20=EB=B3=80?= =?UTF-8?q?=EB=8F=99=EC=9D=B4=20=EC=97=86=EC=9C=BC=EB=A9=B4=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=EC=9D=84=20=EB=B3=B4=EB=82=B4=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=ED=95=A8=20=20(#455)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: callback을 넘겨받아 api 요청 순서를 보장할 수 있도록 함 * fix: 지출 내역을 수정하고 나서 정상 응답이 와야 차등 정산 요청을 보내도록 함 * feat: 변경이 발생한 것에 대해서만 요청이 가도록 수정 * feat: 모달 자동 닫히도록 onClose전달 * feat: onClose를 전달해 모달을 닫는 함수를 스스로 호출하도록 함 * test: 훅에서 받는 인자가 수정되었으므로 이를 반영 * feat: onSuccessCallBack 을 없앰 --- .../PutAndDeleteBillActionModal.tsx | 13 +++++++++---- .../useMemberReportListInAction.test.tsx | 2 +- .../useMemberReportListInAction.ts | 4 +++- client/src/hooks/usePutAndDeleteBillAction.ts | 5 +++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index 3ed40dea0..3d62c5c77 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -6,6 +6,7 @@ import validatePurchase from '@utils/validate/validatePurchase'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; +import {useToast} from '@hooks/useToast/useToast'; import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; @@ -44,7 +45,7 @@ const PutAndDeleteBillActionModal = ({ getIsSamePriceStateAndServerState, getOnlyOneNotAdjustedRemainMemberIndex, isExistAdjustedPrice, - } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price)); + } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); const { inputList, onChange, @@ -64,13 +65,17 @@ const PutAndDeleteBillActionModal = ({ actions.find(({actionId}) => actionId === billAction.actionId), )[0].members; + const {showToast} = useToast(); + return ( <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> <form css={bottomSheetStyle} - onSubmit={event => { - putBillAction(event, inputPair, billAction.actionId); - putMemberReportListInAction(); + onSubmit={async event => { + event.preventDefault(); + + if (canSubmit) await putBillAction(event, inputPair, billAction.actionId); + if (isChangedMemberReportInput) putMemberReportListInAction(); }} > <h2 css={bottomSheetHeaderStyle}> diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx index e499157c2..4d94804f4 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx @@ -19,7 +19,7 @@ describe('useMemberReportListInActionTest', () => { }); const initializeProvider = (actionId: number, totalPrice: number) => - renderHook(() => useMemberReportListInAction(actionId, totalPrice), { + renderHook(() => useMemberReportListInAction(actionId, totalPrice, () => {}), { wrapper: ({children}) => ( <QueryClientProvider client={queryClient}> <MemoryRouter> diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts index 4ae984ae6..0e32d740c 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts @@ -5,7 +5,7 @@ import {useEffect, useState} from 'react'; import useRequestGetMemberReportListInAction from '@hooks/queries/useRequestGetMemberReportListInAction'; import useRequestPutMemberReportListInAction from '@hooks/queries/useRequestPutMemberReportListInAction'; -const useMemberReportListInAction = (actionId: number, totalPrice: number) => { +const useMemberReportListInAction = (actionId: number, totalPrice: number, onClose: () => void) => { const {memberReportListInActionFromServer, queryResult} = useRequestGetMemberReportListInAction(actionId); const {putMemberReportListInAction} = useRequestPutMemberReportListInAction(actionId); @@ -122,6 +122,8 @@ const useMemberReportListInAction = (actionId: number, totalPrice: number) => { const onSubmit = () => { putMemberReportListInAction(memberReportListInAction); + + onClose(); }; const getIsSamePriceStateAndServerState = () => { diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index b1ae2b78f..2bd7366ed 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -19,7 +19,7 @@ const usePutAndDeleteBillAction = ( const [errorInfo, setErrorInfo] = useState<Record<string, boolean>>({title: false, price: false}); const [errorMessage, setErrorMessage] = useState<string | null>(null); - const {mutate: putBillAction} = usePutBillAction(); + const {mutateAsync: putBillAction} = usePutBillAction(); const {mutate: deleteBillAction} = useDeleteBillAction(); // 현재 타겟의 event.target.value를 넣어주기 위해서 @@ -83,12 +83,13 @@ const usePutAndDeleteBillAction = ( setErrorInfo(errorInfo ?? {title: false, price: false}); }; - const onSubmit = async (event: React.FormEvent<HTMLFormElement>, inputPair: InputPair, actionId: number) => { + const onSubmit = (event: React.FormEvent<HTMLFormElement>, inputPair: InputPair, actionId: number) => { event.preventDefault(); const {title, price} = inputPair; putBillAction({actionId, title, price: Number(price)}); + onClose(); }; From 124c97ff4780a7db7e0b490cb1ecab5b8098c06f Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Wed, 21 Aug 2024 18:29:22 +0900 Subject: [PATCH 192/273] =?UTF-8?q?feat:=20Step=EC=97=90=20stepName=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=ED=95=98=EA=B8=B0=20(#452)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 서버로 부터 받은 stepName 출력 * feat: 마지막 action의 stepName에서 1을 더한 값을 새로 생성한 stepName에 넣기 * chore: 백엔드의 요청으로 인해 인원수 click시 BottomSheet가 띄워지지 않도록 주석처리 --- client/src/components/StepList/BillStepItem.tsx | 8 ++++---- client/src/components/StepList/StepList.tsx | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 89fbe7e2e..50cca202b 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -34,7 +34,6 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ const [clickedIndex, setClickedIndex] = useState(-1); const [isOpenMemberListInBillStep, setIsOpenMemberListInBillStep] = useState(false); - const stepName = `차`; const totalPrice = step.actions && step.type === 'BILL' ? step.actions.reduce((acc, cur) => acc + cur.price, 0) : 0; const handleDragHandleItemClick = (index: number) => { @@ -55,12 +54,13 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ <> <DragHandleItemContainer id={`${index}`} - topLeftText={stepName} + topLeftText={step.stepName} topRightText={`${step.members.length}명`} bottomLeftText="총액" bottomRightText={`${totalPrice.toLocaleString('ko-kr')} 원`} backgroundColor="white" - onTopRightTextClick={handleTopRightTextClick} + // TODO: (@soha) 백엔드의 요청으로 인해 인원수 click시 BottomSheet가 띄워지지 않도록 주석처리 + // onTopRightTextClick={handleTopRightTextClick} > {step.actions && step.type === 'BILL' && @@ -107,7 +107,7 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ </DragHandleItemContainer> {isOpenMemberListInBillStep && ( <MemberListInBillStep - stepName={stepName} + stepName={step.stepName} memberList={memberList} isOpenBottomSheet={isOpenMemberListInBillStep} setIsOpenBottomSheet={setIsOpenMemberListInBillStep} diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 88a1ee425..4d4c4a77d 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -16,6 +16,7 @@ const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: const [stepList, setStepList] = useState<(MemberStep | BillStep)[]>([]); const existIndexInStepList = stepList.map((step, index) => ({...step, index})); const [hasAddedItem, setHasAddedItem] = useState(false); + const nextStepName = stepList.length > 0 ? String(stepList[stepList.length - 1].stepName).match(/.*(?=차)/) : ''; useEffect(() => { if (stepListData) { @@ -43,7 +44,7 @@ const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: ...prev, { type: 'BILL', - stepName: '', + stepName: `${Number(nextStepName) + 1}차`, members: [], actions: [], }, From 32ebc61c60c3dbb6b740821419b442867e62b049 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Wed, 21 Aug 2024 23:18:17 +0900 Subject: [PATCH 193/273] =?UTF-8?q?fix:=20async,=20await=20=EC=9D=B4=20?= =?UTF-8?q?=EC=97=86=EC=96=B4=EC=84=9C=20api=20=EC=88=9C=EC=84=9C=20?= =?UTF-8?q?=EB=B3=B4=EC=9E=A5=EC=9D=B4=20=EC=95=88=EB=90=98=EA=B8=B0=20?= =?UTF-8?q?=EB=95=8C=EB=AC=B8=EC=97=90=20=EC=B6=94=EA=B0=80=20(#462)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/usePutAndDeleteBillAction.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 2bd7366ed..6f1e4feaf 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -83,12 +83,12 @@ const usePutAndDeleteBillAction = ( setErrorInfo(errorInfo ?? {title: false, price: false}); }; - const onSubmit = (event: React.FormEvent<HTMLFormElement>, inputPair: InputPair, actionId: number) => { + const onSubmit = async (event: React.FormEvent<HTMLFormElement>, inputPair: InputPair, actionId: number) => { event.preventDefault(); const {title, price} = inputPair; - putBillAction({actionId, title, price: Number(price)}); + await putBillAction({actionId, title, price: Number(price)}); onClose(); }; From ebdf17c1cd48000d6f82447f681cf279e4ca5be5 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:50:26 +0900 Subject: [PATCH 194/273] =?UTF-8?q?[FE]=20=EC=A7=80=EC=B6=9C=20Input=20?= =?UTF-8?q?=EA=B8=88=EC=95=A1=20default=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F?= =?UTF-8?q?=20autoFocus=20(#470)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 지출 내역 금액 default가 0이 아닌 ‘’로 변경 * feat: 지출 내역을 추가하면 title에 autoFocus * feat: enter 키를 눌렀을 때 handleBlurBillRequest가 실행되는 기능 추가 --- client/src/components/StepList/BillStepItem.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 50cca202b..61e5b1c75 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -85,18 +85,27 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ ))} {isAddEditableItem && isLastBillItem && ( - <EditableItem backgroundColor="lightGrayContainer" onBlur={handleBlurBillRequest}> + <EditableItem + backgroundColor="lightGrayContainer" + onBlur={handleBlurBillRequest} + onKeyDown={e => { + if (e.key === 'Enter') { + handleBlurBillRequest(); + } + }} + > <EditableItem.Input placeholder="지출 내역" textSize="bodyBold" value={billInput.title} onChange={e => handleChangeBillInput('title', e)} + autoFocus ></EditableItem.Input> <Flex gap="0.25rem" alignItems="center"> <EditableItem.Input placeholder="0" type="number" - value={billInput.price} + value={billInput.price || ''} onChange={e => handleChangeBillInput('price', e)} style={{textAlign: 'right'}} ></EditableItem.Input> From af39b52b8208be6e6fa901b8c21d03d1aaa44b2f Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:51:05 +0900 Subject: [PATCH 195/273] =?UTF-8?q?feat:=20StepList=EC=97=90=20isFixed=20?= =?UTF-8?q?=EB=94=94=EC=9E=90=EC=9D=B8=EC=8B=9C=EC=8A=A4=ED=85=9C=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20(#465)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: v0.1.77 배포 * chore: 디자인 시스템 적용 * fix: 변동된 금액인지를 나타내는 isFixed prop 추가 --- HDesign/package-lock.json | 4 ++-- HDesign/package.json | 2 +- client/package-lock.json | 8 ++++---- client/package.json | 2 +- client/src/components/StepList/BillStepItem.tsx | 5 ++++- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 14b7563a3..4bfb80709 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.76", + "version": "0.1.77", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.76", + "version": "0.1.77", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index e26c96ddd..0cc67d62f 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.76", + "version": "0.1.77", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/client/package-lock.json b/client/package-lock.json index b7df876e4..3a0f5e4ef 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.76", + "haengdong-design": "^0.1.77", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -10137,9 +10137,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.76", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.76.tgz", - "integrity": "sha512-wTZv/3XK9I8N5NAyCAoYyykWu76MzWQlQ+jDZDuTFuzyV2c+MoYI2Ouvyu+9rl+HDYRuBVIaQ6ysfM6hQcwVYg==", + "version": "0.1.77", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.77.tgz", + "integrity": "sha512-+M41hUpL2ilwBAlaeYSinfsHy2DAMHnTq0B3tRtccJ1EKzCU3GPK3rA4z3km3GFLlmE3aOErtOeRV/xp6Y2kKA==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index ff2abe9d8..81ea29821 100644 --- a/client/package.json +++ b/client/package.json @@ -68,7 +68,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.76", + "haengdong-design": "^0.1.77", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 61e5b1c75..16e40c6af 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -67,11 +67,14 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ step.actions.map((action, index) => ( <Fragment key={action.actionId}> <DragHandleItem - hasDragHandler={isAdmin} + // TODO: (@todari) dnd 없으므로 false + // hasDragHandler={isAdmin} + hasDragHandler={false} prefix={action.name} suffix={`${action.price.toLocaleString('ko-kr')} 원`} backgroundColor="lightGrayContainer" onClick={() => handleDragHandleItemClick(index)} + isFixed={action.isFixed} /> {isOpenBottomSheet && clickedIndex === index && isAdmin && ( From 803f1c65fb20f090aea29f1f608f8e634ef7fd67 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:51:44 +0900 Subject: [PATCH 196/273] =?UTF-8?q?feat:=20=EC=B0=A8=EB=93=B1=20=EC=A0=95?= =?UTF-8?q?=EC=82=B0=20=EC=A0=81=EC=9A=A9=EC=8B=9C=20=EC=8B=A0=EC=84=A0?= =?UTF-8?q?=ED=95=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EA=B0=80=20=EB=B0=94?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=98=EC=98=81=EB=90=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EA=B3=A0=20=EC=8B=9C=EA=B0=84=EC=B0=A8=EB=A5=BC=20=EB=91=90?= =?UTF-8?q?=EA=B3=A0=20=EB=B0=98=EC=98=81=EB=90=98=EB=8A=94=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EC=88=98=EC=A0=95=20(#458)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 차등 정산 내용이 수정되었을 경우 낙관적 업데이트 적용 * feat: any제거하고 타입 적용 * fix: 차등정산 수정 후 다시 로드 시 깜빡이는 현상 해결 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> --- client/src/apis/request/bill.ts | 2 +- .../queries/useRequestDeleteAllMemberList.ts | 2 +- .../queries/useRequestPutAllMemberList.ts | 2 +- .../useRequestPutMemberReportListInAction.ts | 24 +++++++++++++++++-- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 418429d33..c08168520 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -43,7 +43,7 @@ export const requestPutBillAction = async ({eventId, actionId, title, price}: Wi }); }; -type MemberReportList = {members: MemberReportInAction[]}; +export type MemberReportList = {members: MemberReportInAction[]}; export const requestGetMemberReportListInAction = async ({eventId, actionId}: WithEventId<RequestBillAction>) => { return requestGet<MemberReportList>({ diff --git a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts index 38354a0fd..da6fc4223 100644 --- a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts +++ b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts @@ -19,7 +19,7 @@ const useRequestDeleteAllMemberList = () => { onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); }, }); diff --git a/client/src/hooks/queries/useRequestPutAllMemberList.ts b/client/src/hooks/queries/useRequestPutAllMemberList.ts index a2faf0c09..4bd746d0c 100644 --- a/client/src/hooks/queries/useRequestPutAllMemberList.ts +++ b/client/src/hooks/queries/useRequestPutAllMemberList.ts @@ -19,7 +19,7 @@ const useRequestPutAllMemberList = () => { onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); }, }); diff --git a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts index 2765e278e..a87fa44f1 100644 --- a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts +++ b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts @@ -1,6 +1,6 @@ import {useMutation, useQueryClient} from '@tanstack/react-query'; -import {requestPutMemberReportListInAction} from '@apis/request/bill'; +import {MemberReportList, requestPutMemberReportListInAction} from '@apis/request/bill'; import {MemberReportInAction} from 'types/serviceType'; import getEventIdByUrl from '@utils/getEventIdByUrl'; @@ -16,7 +16,27 @@ const useRequestPutMemberReportListInAction = (actionId: number) => { onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + }, + onMutate: async (newMembers: MemberReportInAction[]) => { + await queryClient.cancelQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + + const previousMembers = queryClient.getQueryData([QUERY_KEYS.memberReportInAction, actionId]); + + queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], (oldData: MemberReportList) => ({ + ...oldData, + members: oldData.members.map((member: MemberReportInAction) => { + const updatedMember = newMembers.find(m => m.name === member.name); + return updatedMember ? {...member, ...updatedMember} : member; + }), + })); + + return {previousMembers}; + }, + onError: (err, newMembers, context) => { + if (context?.previousMembers) { + queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], context.previousMembers); + } }, }); From 1e37410db71a1e602c0931136e0a4b99b77e50c9 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:54:56 +0900 Subject: [PATCH 197/273] =?UTF-8?q?feat:=20=EA=B4=80=EB=A6=AC=EC=9E=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=8A=A4=EC=9C=84=EC=B9=98=EA=B0=80=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EB=A1=9C=20=ED=99=9C=EC=84=B1=ED=99=94?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?(#469)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 관리페이지 로그인에서도 top nav 관리 탭으로 활성화 되도록 수정 * refactor: useEventLogin으로 훅 분리 --- client/src/hooks/useEventLogin.ts | 42 ++++++++++++++++++ client/src/hooks/useNavSwitch.tsx | 7 ++- .../EventPage/AdminPage/EventLoginPage.tsx | 43 +++---------------- .../src/pages/EventPage/EventPageLayout.tsx | 35 ++++++++------- client/src/router.tsx | 8 ++-- 5 files changed, 76 insertions(+), 59 deletions(-) create mode 100644 client/src/hooks/useEventLogin.ts diff --git a/client/src/hooks/useEventLogin.ts b/client/src/hooks/useEventLogin.ts new file mode 100644 index 000000000..ccabe20c1 --- /dev/null +++ b/client/src/hooks/useEventLogin.ts @@ -0,0 +1,42 @@ +import {useState} from 'react'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import RULE from '@constants/rule'; + +import useRequestPostLogin from './queries/useRequestPostLogin'; + +const useEventLogin = () => { + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState<string | null>(null); + const [canSubmit, setCanSubmit] = useState(false); + const {mutate: postLogin} = useRequestPostLogin(); + + const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + postLogin({password}, {onError: () => setErrorMessage('비밀번호가 틀렸어요')}); + }; + + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + setErrorMessage(validation.errorMessage); + + if (validation.isValid) { + setPassword(newValue); + } + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + }; + + return { + password, + errorMessage, + handleChange, + canSubmit, + submitPassword, + }; +}; + +export default useEventLogin; diff --git a/client/src/hooks/useNavSwitch.tsx b/client/src/hooks/useNavSwitch.tsx index 7ecd3def8..a622a7a30 100644 --- a/client/src/hooks/useNavSwitch.tsx +++ b/client/src/hooks/useNavSwitch.tsx @@ -1,4 +1,4 @@ -import {useState} from 'react'; +import {useEffect, useState} from 'react'; import {useLocation, useNavigate} from 'react-router-dom'; const PATH_TABLE: Record<string, string> = { @@ -22,6 +22,11 @@ const useNavSwitch = () => { const [nav, setNav] = useState(PATH_DISPLAY_TABLE[lastPath]); + useEffect(() => { + const isLogin = lastPath === 'login'; + setNav(isLogin ? '관리' : PATH_DISPLAY_TABLE[lastPath]); + }, [location]); + const onChange = (displayName: string) => { setNav(displayName); navigate(`${basePath}/${PATH_TABLE[displayName]}`); diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index 974ad44d4..741dca3eb 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,48 +1,15 @@ -import {useState} from 'react'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Switch} from 'haengdong-design'; +import {FixedButton, LabelInput, Title} from 'haengdong-design'; -import validateEventPassword from '@utils/validate/validateEventPassword'; -import useRequestPostLogin from '@hooks/queries/useRequestPostLogin'; - -import useNavSwitch from '@hooks/useNavSwitch'; +import useEventLogin from '@hooks/useEventLogin'; import RULE from '@constants/rule'; import {PASSWORD_LENGTH} from '@constants/password'; const EventLoginPage = () => { - const [password, setPassword] = useState(''); - const {nav, paths, onChange} = useNavSwitch(); - const [errorMessage, setErrorMessage] = useState(''); - const [canSubmit, setCanSubmit] = useState(false); - const {mutate: postLogin} = useRequestPostLogin(); - - const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - - postLogin({password}, {onError: () => setErrorMessage('비밀번호가 틀렸어요')}); - }; - - const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { - const newValue = event.target.value; - const validation = validateEventPassword(newValue); - - setCanSubmit(newValue.length === RULE.maxEventPasswordLength); - - if (validation.isValid) { - setPassword(newValue); - setErrorMessage(''); - } else { - event.target.value = password; - setErrorMessage(validation.errorMessage ?? ''); - } - }; + const {password, errorMessage, handleChange, canSubmit, submitPassword} = useEventLogin(); return ( - <MainLayout> - <TopNav> - <Switch value={nav} values={paths} onChange={onChange} /> - {/* <Back /> */} - </TopNav> + <> <Title title="행사 비밀번호 입력" description={`관리를 위해선 비밀번호가 필요해요. 행사 생성 시 설정한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} @@ -61,7 +28,7 @@ const EventLoginPage = () => { ></LabelInput> <FixedButton disabled={!canSubmit}>관리 페이지로</FixedButton> </form> - </MainLayout> + </> ); }; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 589f9ab52..6f00c23f1 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -24,6 +24,7 @@ const EventPageLayout = () => { const eventId = getEventIdByUrl(); const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; + const isLoginPage = useMatch(ROUTER_URLS.eventLogin) !== null; const outletContext: EventPageContextProps = { isAdmin, @@ -37,22 +38,24 @@ const EventPageLayout = () => { <MainLayout backgroundColor="gray"> <TopNav> <Switch value={nav} values={paths} onChange={onChange} /> - <CopyToClipboard - text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\n${url}`} - onCopy={() => - showToast({ - showingTime: 3000, - message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', - type: 'confirm', - position: 'bottom', - bottom: '8rem', - }) - } - > - <Button size="small" variants="secondary"> - 정산 초대하기 - </Button> - </CopyToClipboard> + {!isLoginPage && ( + <CopyToClipboard + text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\n${url}`} + onCopy={() => + showToast({ + showingTime: 3000, + message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', + type: 'confirm', + position: 'bottom', + bottom: '8rem', + }) + } + > + <Button size="small" variants="secondary"> + 정산 초대하기 + </Button> + </CopyToClipboard> + )} </TopNav> <Outlet context={outletContext} /> </MainLayout> diff --git a/client/src/router.tsx b/client/src/router.tsx index a6af2184d..51162c775 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -35,16 +35,16 @@ const router = createBrowserRouter([ path: ROUTER_URLS.eventCreateComplete, element: <CompleteCreateEventPage />, }, - { - path: ROUTER_URLS.eventLogin, - element: <EventLoginPage />, - }, { path: ROUTER_URLS.event, element: <EventPage />, children: [ {path: ROUTER_URLS.eventManage, element: <AdminPage />}, {path: ROUTER_URLS.home, element: <HomePage />}, + { + path: ROUTER_URLS.eventLogin, + element: <EventLoginPage />, + }, ], }, { From 8ef3978f5afe8c749c91abde1078bf9445d6f55e Mon Sep 17 00:00:00 2001 From: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Date: Thu, 22 Aug 2024 17:40:21 +0900 Subject: [PATCH 198/273] =?UTF-8?q?refactor:=20DB=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=A5=BC=20drop=20=ED=95=A0=20=EC=88=98=20=EC=97=86?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20DB=20user=20=EA=B6=8C=ED=95=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=ED=95=A9=EB=8B=88=EB=8B=A4.=20(#485)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe <pigkill40@naver.com> * design: 기본 css style 초기화 작업 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * design: 전역 스타일링 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우터 셋팅 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 앱의 진입점 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우트 경로 설정 Co-authored-by: pakxe <pigkill40@naver.com> * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 인원 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Input component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Title component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: BottomSheet component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 메서드 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 코드 컨벤션 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: 메서드 순서 변경 Co-authored-by: Arachne <jhg2819@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> authored-by: khabh <khabh@naver.com> * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 클라이언트 코드 삭제 * refactor: CD workflow main, develop 분리 (#163) * refactor: CD workflow main, develop 분리 및 dockerfile 수정 * refactor: trigger test 브랜치 추가 * refactor: feature/#147 에 push test * refactor: github actions self-hosted runner tag 추가 * refactor: feature/#147 runner 구분 테스트 * refactor: feature/#147 prod runner 구분 테스트 * refactor: feature/#147 prod runner 구분 테스트2 * refactor: feature/#147 prod runner 구분 테스트3 * refactor: feature/#147 prod runner 구분 테스트3 * refactor: prod, dev yml 분리 완료 및 서버 테스트 완료 * feat: 로그 모니터링 환경 구축 (#169) * feat: 예외메시지 구체화 (#161) * feat: 예외 핸들링 추가 * refactor: 예외 메시지 구체화 및 검증 역할 변경 * feat: 에러 코드 추가 * style: 개행 제거 * refactor: 멤버 액션 예외 ErrorCode 분리 * feat: 로깅 추가 * refactor: 액션 이력 조회 리펙토링 (#141) * feat: 멤버 액션 삭제 기능 구현 (#181) * feat: 액션 삭제 기능 구현 중 지출 삭제 가능, 인원 삭제는 아직입니다. * feat: 멤버 액션 삭제 구현 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * feat: 맴버 액션 삭제 기능 구현 * refactor: api 매개변수에 값 넣도록 수정 * fix: 테스트 코드에 action 올바르게 사용하도록 수정 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: pakxe <pigkill40@naver.com> * feat: ERD svg 생성하여 스키마 변경에 대한 이력 관리 (#190) * feat: 지출 액션 수정 기능 구현 (#180) * feat: 지출 액션 삭제 기능 구현 (#179) * feat: 행사의 전체 참여자 중 특정 참여자의 멤버 액션을 모두 삭제하는 기능 구현 (#185) * feat: 행사의 전체 참여자 중 특정 참여자의 멤버 액션을 모두 삭제하는 기능 구현 * test: eventId String으로 변경 * fix: 다른 행사에 있는 멤버 액션도 지워지는 버그 수정 * refactor: 전체 참여자 중에서 특정 참여자를 전부 삭제하는 메서드명 변경 * refactor: 전체 참여자 중에서 특정 참여자를 전부 삭제하는 메서드명 변경 * refactor: MemberActionController 메서드 파라미터 컨벤션 반영 * refactor: conflict resolve * refactor: conflict resolve * feat: 행사에 참여한 전체 인원 조회 기능 구현 (#195) * feat: 행사에 참여한 전체 인원 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * refactor: EventServiceTest, MemberActionRepository 코드 리팩터링 * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * feat: 행사 참여 인원 이름 변경 기능 구현 (#197) * feat: 행사 참여 인원 이름 변경 기능 구현 * refactor: 지출 액션 수정 기능 리펙토링 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * refactor: API 엔드포인트 수정 (#200) * refactor: 멤버 액션, 지출 액션 관련 API 엔드포인트 수정 * refactor: 요청 url에 token을 eventId로 수정 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * feat: 테스트 데이터 클리너 구현 (#199) * feat: 테스트 데이터 클리너 구현 * feat: 테스트 클리너 상수, 메서드 분리 * refactor: 데이터베이스 클리너 적용 * feat: 행사 관리자 비밀번호 추가 (#213) * feat: 이벤트 비밀번호 추 * test: 테스트 공통 설정 클래스 분리 * feat: 어드민 인터셉터 추가 및 jwt 설정 추가 * feat: 이벤트 로그인 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * feat: 쿠키 설정 분리 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * submodule 업데이트 * style: 주석 제거 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * refactor: 로컬 환경 쿠키 secure 옵션 제거 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * test: 접근제어자 수정 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * test: 개행 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * fix: 쿠키 인증 버그 수정 (#222) Co-authored-by: khabh <khabh@naver.com> * fix: 쿠키 인증 버그 수정 (#235) * refactor: 에러 코드 재정의 (#227) * refactor: 에러 코드 재정의 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: 변수를 받는 예외 메세지 수정 Co-authored-by: 3juhwan <13selfesteem91@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * fix: 쿠키 저장 오류 2차 수정 (#237) * fix: 쿠키 인증 버그 수정 Co-authored-by: khabh <khabh@naver.com> * fix: 쿠키 인증 버그 수정 --------- Co-authored-by: khabh <khabh@naver.com> * feat: REST docs를 통한 문서화 (#238) * feat: REST Docs 적용 * feat: REST Docs prettyPrint 및 snippets 적용 * feat: REST Docs에 예외 항목 추가 * test: 행사 액션 이력 조회 테스트 추가 * refactor: 중복된 http-request snippet 제거 * refactor: 사용되지 않는 snippet 제거 * refactor: 빌드 시 자동으로 문서 최신화하도록 gradle 설정 추가 * fix: CookieProperties에 sameSite 옵션 추가 --------- Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * fix: JWT 유효기간 만료 버그 수정 (#248) * fix: JWT 기간 오류 수정 * fix: JWT 기간 오류 수정 * feat: 관리자 권한 확인 API 구현 (#259) * feat: 관리자 권한 확인 API 구현 * backend-pull-request workflow 파일 수정 * feat: HTTP Method를 POST에서 GET으로 변경 * fix: 참여자 삭제 서비스 메서드에 Transactional 추가 (#265) Co-authored-by: 3juhwan <13selfesteem91@naver.com> * refactor: application.yml metrics 추가 (#269) * feat: CI/CD 숙제 (#290) * feat: CI/CD 숙제 (#291) * refactor: 행사 참여 인원 이름 변경 api 수정 (#268) * refactor: 회원 이름 변경 api 여러명으로 추가 * style: 메소드 순서 변경 * fix: rest docs 저장 파일 위치 변경 (#273) * fix: 어드민 권한 확인 불가 버그 수정 (#275) * fix: 행사 로그인 불가 버그 수정 (#283) * fix: CI/CD 트리거 조건에서 server 폴더 조건 제거 (#308) * fix: CI 트리거 조건을 수정 * feat: be-dev CD 트리거 조건에서 server 폴더 제거 * feat: pr 머지시 issue close 기능 추가 (#309) * refactor: yml, Dockerfile TZ Asia/Seoul 적용 (#305) Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * refactor: actuator health 엔드포인트 설정 변경 (#303) * feat: actuator health 엔드포인트 설정 변경 * refactor: AdminInterceptor log level 변경 --------- Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * feat: 서버 로그 볼륨 마운트 설정 (#300) * feat: 로그 파일 볼륨 설정 * feat: 볼륨 이름 지정 * feat: LogBack 롤링 정책 수정, 로그 레벨에 따른 분리 (#332) * feat: Logback 로그 레벨 분리 * feat: Lockback 로그 레벨 분리 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * fix: 서브 모듈 프로파일 오타 수정 (#334) * refactor: 현재 참여 인원 목록 조회 API 반환 형식 수정 (#361) * feat: BillActionDetail 베이스 코드 생성 (#363) * feat: 액션 이력 조회 v2 기능 구현 (#375) * [BE] 행사 참여 인원 또는 지출 총액 변동시 차등 정산 초기화 기능 구현 (#370) * feat: 지출 액션 수정시 지출 디테일 초기화 기능 구현 * feat: 맴버 액션 삭제시 지출 디테일 초기화 기능 구현 * feat: 맴버 삭제시 지출 디테일 초기화 기능 구현 * fix: 버그 수정 * fix: 버그 수정 * feat: 요구사항 변경에 따른 지출 내역 추가, 지출 액션 삭제 API 수정 (#373) * feat: 지출 내역 추가 시, 상세 내역 생성 로직 추가 * feat: 지출 내역 삭제 시, 상세 내역 삭제 로직 추가 * fix: 멤버가 없는 상황에 대해 0으로 나누는 상황 방지 * refactor: 참여자별 정산 현황 조회 및 액션 이력 조회 수정 (#377) * refactor: BillActionDetail 변경 사항을 반영하여 참여자별 정산 현황 조회하도록 수정 * refactor: 액션 이력 조회 시 지출 액션 고정 금액 설정 여부 필드 추가 * refactor: isFixed 필드 삭제 * refactor: 메서드 이름 변경 * fix: BillAction 변경 로직 수정 * feat: 참여자 개별 지출 금액 수정 및 조회 기능 구현 (#378) * feat: 참여자 개별 지출 금액 수정 기능 구현 * refactor: BillActionDetailService 코드 리팩터링 * docs: restdocs 작성 * feat: 참여자별 지출 금액 조회 기능 구현 * docs: index.adoc에 billActionDetail.adoc 추가 * refactor: 충돌 해결 * feat: 에러를 재현할 수 있는 로그로 수정 (#392) * feat: 로깅에 요청 정보 포함 * feat: 개발 환경 ddl update로 변경 * feat: 예외 처리 및 로깅 형식 수정 (#394) * fix: 리스트 형태의 요청 바디에 null을 넣으면 500이 뜨는 에러 수정 * feat: 로그를 json 형태로 수정 * feat: 예외 처리 및 로깅 형식 수정 (#395) * fix: 리스트 형태의 요청 바디에 null을 넣으면 500이 뜨는 에러 수정 * feat: 로그를 json 형태로 수정 * feat: 로그를 json 인덴트 추가 * refactor: BillActionDetail isFixed 추가 (#405) * fix: 로깅 적용 후 예외 응답 불가 버그 수정 (#413) * feat: 액션 이력 조회 stepName 추가 (#420) * feat: 이슈, PR 템플릿 추가 (#160) (#426) * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * docs: pr issue close 삭제 * feat: 행사 비밀번호 암호화 추가 (#429) * feat: 행사 비밀번호 암호화 추가 * refactor: 비밀번호 암호화 로직 수정 * fix: MessageDigest를 싱글톤으로 관리하지 않도록 수정 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: BillActionDetail 초기화시 totalPrice와 정합성 안맞는 버그 수정 (#460) * fix: BillActionDetail 초기화시 totalPrice와 정합성 안맞는 버그 수정 * refactor: BillActionDetail 초기화 로직 BillAction으로 위임 * style: 메소드 이름 수정 * refactor: BillActionDetail 계산 공통 로직 메소드 분리 * fix: price 분배 로직 버그 수정 * style: 미사용 필드 제거 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * refactor: DB 데이터를 drop 할 수 없도록 DB user 권한 수정 (#484) --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: juha <khabh@naver.com> Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> --- .github/workflows/backend-dev.yml | 72 ++++ .github/workflows/backend-prod.yml | 74 ++++ .github/workflows/backend-pull-request.yml | 44 ++ .gitmodules | 4 + client/.gitkeep | 0 server/.gitignore | 244 +++++++++++ server/.gitkeep | 0 server/Dockerfile | 9 + server/build.gradle | 86 ++++ server/docs/24-08-04-erd.sql | 65 +++ server/docs/24-08-04-erd.svg | 4 + server/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43453 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + server/gradlew | 249 ++++++++++++ server/gradlew.bat | 92 +++++ server/settings.gradle | 1 + server/src/docs/asciidoc/billAction.adoc | 121 ++++++ .../src/docs/asciidoc/billActionDetail.adoc | 93 +++++ server/src/docs/asciidoc/event.adoc | 205 ++++++++++ server/src/docs/asciidoc/index.adoc | 15 + server/src/docs/asciidoc/memberAction.adoc | 100 +++++ .../src/docs/asciidoc/memberBillReport.adoc | 17 + .../haengdong/HaengdongApplication.java | 15 + .../haengdong/application/ActionService.java | 39 ++ .../haengdong/application/AuthService.java | 41 ++ .../application/BillActionDetailService.java | 76 ++++ .../application/BillActionService.java | 80 ++++ .../haengdong/application/EventService.java | 165 ++++++++ .../application/MemberActionFactory.java | 62 +++ .../application/MemberActionService.java | 100 +++++ .../request/BillActionAppRequest.java | 15 + .../BillActionDetailUpdateAppRequest.java | 8 + .../BillActionDetailsUpdateAppRequest.java | 8 + .../request/BillActionUpdateAppRequest.java | 7 + .../application/request/EventAppRequest.java | 10 + .../request/EventLoginAppRequest.java | 4 + .../request/MemberActionSaveAppRequest.java | 12 + .../request/MemberActionsSaveAppRequest.java | 6 + .../request/MemberNameUpdateAppRequest.java | 7 + .../request/MemberNamesUpdateAppRequest.java | 8 + .../response/ActionAppResponse.java | 61 +++ .../response/BillActionDetailAppResponse.java | 18 + .../BillActionDetailsAppResponse.java | 14 + .../response/CurrentMemberAppResponse.java | 10 + .../response/EventAppResponse.java | 10 + .../response/EventDetailAppResponse.java | 10 + .../response/MemberBillReportAppResponse.java | 4 + .../response/MembersAppResponse.java | 8 + .../haengdong/config/AdminInterceptor.java | 51 +++ .../config/RequestServletFilter.java | 23 ++ .../server/haengdong/config/WebMvcConfig.java | 66 +++ .../haengdong/domain/TokenProvider.java | 12 + .../haengdong/domain/action/Action.java | 42 ++ .../domain/action/ActionRepository.java | 23 ++ .../haengdong/domain/action/BillAction.java | 156 +++++++ .../domain/action/BillActionDetail.java | 57 +++ .../action/BillActionDetailRepository.java | 17 + .../domain/action/BillActionRepository.java | 27 ++ .../domain/action/CurrentMembers.java | 81 ++++ .../haengdong/domain/action/MemberAction.java | 76 ++++ .../domain/action/MemberActionRepository.java | 53 +++ .../domain/action/MemberActionStatus.java | 19 + .../domain/action/MemberBillReport.java | 75 ++++ .../domain/action/MemberGroupIdProvider.java | 11 + .../server/haengdong/domain/event/Event.java | 70 ++++ .../domain/event/EventRepository.java | 11 + .../haengdong/domain/event/EventStep.java | 28 ++ .../domain/event/EventTokenProvider.java | 12 + .../haengdong/domain/event/Password.java | 52 +++ .../exception/AuthenticationException.java | 19 + .../haengdong/exception/ErrorResponse.java | 15 + .../exception/GlobalExceptionHandler.java | 90 +++++ .../exception/HaengdongErrorCode.java | 69 ++++ .../exception/HaengdongException.java | 19 + .../auth/AuthenticationExtractor.java | 23 ++ .../infrastructure/auth/CookieProperties.java | 15 + .../infrastructure/auth/JwtTokenProvider.java | 54 +++ .../infrastructure/auth/TokenProperties.java | 7 + .../presentation/ActionController.java | 26 ++ .../presentation/BillActionController.java | 55 +++ .../BillActionDetailController.java | 42 ++ .../presentation/EventController.java | 120 ++++++ .../presentation/MemberActionController.java | 60 +++ .../BillActionDetailUpdateRequest.java | 21 + .../BillActionDetailsUpdateRequest.java | 16 + .../request/BillActionSaveRequest.java | 19 + .../request/BillActionUpdateRequest.java | 18 + .../request/BillActionsSaveRequest.java | 18 + .../request/EventLoginRequest.java | 14 + .../request/EventSaveRequest.java | 18 + .../request/MemberActionsSaveRequest.java | 25 ++ .../request/MemberNameUpdateRequest.java | 18 + .../request/MemberNamesUpdateRequest.java | 17 + .../presentation/response/ActionResponse.java | 26 ++ .../response/ActionResponse2.java | 22 + .../response/ActionsResponse.java | 14 + .../response/BillActionDetailResponse.java | 18 + .../response/BillActionDetailsResponse.java | 16 + .../response/CurrentMembersResponse.java | 15 + .../response/EventDetailResponse.java | 10 + .../presentation/response/EventResponse.java | 10 + .../response/MemberBillReportResponse.java | 10 + .../response/MemberBillReportsResponse.java | 15 + .../response/MembersResponse.java | 13 + .../presentation/response/StepResponse.java | 27 ++ .../presentation/response/StepsResponse.java | 56 +++ server/src/main/resources/application.yml | 66 +++ server/src/main/resources/config | 1 + server/src/main/resources/logback-spring.xml | 97 +++++ .../application/ActionServiceTest.java | 91 +++++ .../BillActionDetailServiceTest.java | 111 +++++ .../application/BillActionServiceTest.java | 229 +++++++++++ .../application/EventServiceTest.java | 231 +++++++++++ .../application/MemberActionFactoryTest.java | 223 ++++++++++ .../application/MemberActionServiceTest.java | 251 ++++++++++++ .../application/ServiceTestSupport.java | 11 + .../docs/ActionControllerDocsTest.java | 70 ++++ .../docs/BillActionControllerDocsTest.java | 128 ++++++ .../BillActionDetailControllerDocsTest.java | 127 ++++++ .../docs/EventControllerDocsTest.java | 381 ++++++++++++++++++ .../docs/MemberActionControllerDocsTest.java | 157 ++++++++ .../haengdong/docs/RestDocsSupport.java | 28 ++ .../haengdong/domain/action/ActionTest.java | 31 ++ .../domain/action/BillActionTest.java | 89 ++++ .../domain/action/CurrentMembersTest.java | 97 +++++ .../domain/action/MemberBillReportTest.java | 56 +++ .../haengdong/domain/event/EventTest.java | 65 +++ .../haengdong/domain/event/PasswordTest.java | 19 + .../presentation/ActionControllerTest.java | 36 ++ .../BillActionControllerTest.java | 97 +++++ .../BillActionDetailControllerTest.java | 56 +++ .../presentation/ControllerTestSupport.java | 53 +++ .../presentation/EventControllerTest.java | 111 +++++ .../MemberActionControllerTest.java | 74 ++++ .../response/StepsResponseTest.java | 63 +++ .../support/extension/DatabaseCleaner.java | 52 +++ .../extension/DatabaseCleanerExtension.java | 19 + .../haengdong/support/fixture/Fixture.java | 15 + 138 files changed, 7447 insertions(+) create mode 100644 .github/workflows/backend-dev.yml create mode 100644 .github/workflows/backend-prod.yml create mode 100644 .github/workflows/backend-pull-request.yml create mode 100644 .gitmodules delete mode 100644 client/.gitkeep create mode 100644 server/.gitignore delete mode 100644 server/.gitkeep create mode 100644 server/Dockerfile create mode 100644 server/build.gradle create mode 100644 server/docs/24-08-04-erd.sql create mode 100644 server/docs/24-08-04-erd.svg create mode 100644 server/gradle/wrapper/gradle-wrapper.jar create mode 100644 server/gradle/wrapper/gradle-wrapper.properties create mode 100644 server/gradlew create mode 100644 server/gradlew.bat create mode 100644 server/settings.gradle create mode 100644 server/src/docs/asciidoc/billAction.adoc create mode 100644 server/src/docs/asciidoc/billActionDetail.adoc create mode 100644 server/src/docs/asciidoc/event.adoc create mode 100644 server/src/docs/asciidoc/index.adoc create mode 100644 server/src/docs/asciidoc/memberAction.adoc create mode 100644 server/src/docs/asciidoc/memberBillReport.adoc create mode 100644 server/src/main/java/server/haengdong/HaengdongApplication.java create mode 100644 server/src/main/java/server/haengdong/application/ActionService.java create mode 100644 server/src/main/java/server/haengdong/application/AuthService.java create mode 100644 server/src/main/java/server/haengdong/application/BillActionDetailService.java create mode 100644 server/src/main/java/server/haengdong/application/BillActionService.java create mode 100644 server/src/main/java/server/haengdong/application/EventService.java create mode 100644 server/src/main/java/server/haengdong/application/MemberActionFactory.java create mode 100644 server/src/main/java/server/haengdong/application/MemberActionService.java create mode 100644 server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/EventAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java create mode 100644 server/src/main/java/server/haengdong/application/response/ActionAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/EventAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java create mode 100644 server/src/main/java/server/haengdong/application/response/MembersAppResponse.java create mode 100644 server/src/main/java/server/haengdong/config/AdminInterceptor.java create mode 100644 server/src/main/java/server/haengdong/config/RequestServletFilter.java create mode 100644 server/src/main/java/server/haengdong/config/WebMvcConfig.java create mode 100644 server/src/main/java/server/haengdong/domain/TokenProvider.java create mode 100644 server/src/main/java/server/haengdong/domain/action/Action.java create mode 100644 server/src/main/java/server/haengdong/domain/action/ActionRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/action/BillAction.java create mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionDetail.java create mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/action/CurrentMembers.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberAction.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberBillReport.java create mode 100644 server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java create mode 100644 server/src/main/java/server/haengdong/domain/event/Event.java create mode 100644 server/src/main/java/server/haengdong/domain/event/EventRepository.java create mode 100644 server/src/main/java/server/haengdong/domain/event/EventStep.java create mode 100644 server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java create mode 100644 server/src/main/java/server/haengdong/domain/event/Password.java create mode 100644 server/src/main/java/server/haengdong/exception/AuthenticationException.java create mode 100644 server/src/main/java/server/haengdong/exception/ErrorResponse.java create mode 100644 server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java create mode 100644 server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java create mode 100644 server/src/main/java/server/haengdong/exception/HaengdongException.java create mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java create mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java create mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java create mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java create mode 100644 server/src/main/java/server/haengdong/presentation/ActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/BillActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/BillActionDetailController.java create mode 100644 server/src/main/java/server/haengdong/presentation/EventController.java create mode 100644 server/src/main/java/server/haengdong/presentation/MemberActionController.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/EventResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/MembersResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/StepResponse.java create mode 100644 server/src/main/java/server/haengdong/presentation/response/StepsResponse.java create mode 100644 server/src/main/resources/application.yml create mode 160000 server/src/main/resources/config create mode 100644 server/src/main/resources/logback-spring.xml create mode 100644 server/src/test/java/server/haengdong/application/ActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java create mode 100644 server/src/test/java/server/haengdong/application/BillActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/application/EventServiceTest.java create mode 100644 server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java create mode 100644 server/src/test/java/server/haengdong/application/MemberActionServiceTest.java create mode 100644 server/src/test/java/server/haengdong/application/ServiceTestSupport.java create mode 100644 server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java create mode 100644 server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java create mode 100644 server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java create mode 100644 server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java create mode 100644 server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java create mode 100644 server/src/test/java/server/haengdong/docs/RestDocsSupport.java create mode 100644 server/src/test/java/server/haengdong/domain/action/ActionTest.java create mode 100644 server/src/test/java/server/haengdong/domain/action/BillActionTest.java create mode 100644 server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java create mode 100644 server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java create mode 100644 server/src/test/java/server/haengdong/domain/event/EventTest.java create mode 100644 server/src/test/java/server/haengdong/domain/event/PasswordTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/ActionControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java create mode 100644 server/src/test/java/server/haengdong/presentation/EventControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java create mode 100644 server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java create mode 100644 server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java create mode 100644 server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java create mode 100644 server/src/test/java/server/haengdong/support/fixture/Fixture.java diff --git a/.github/workflows/backend-dev.yml b/.github/workflows/backend-dev.yml new file mode 100644 index 000000000..a3257f028 --- /dev/null +++ b/.github/workflows/backend-dev.yml @@ -0,0 +1,72 @@ +name: backend-push + +on: + push: + branches: [ "be-dev" ] + +jobs: + build: + runs-on: [ self-hosted, backend-dev ] + + defaults: + run: + shell: bash + working-directory: ./server + + permissions: + contents: read + + steps: + - name: CheckOut + uses: actions/checkout@v4 + with: + token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} + submodules: true + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Test with Gradle Wrapper + run: ./gradlew clean build + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Set up Docker BuildX + uses: docker/setup-buildx-action@v3 + + - name: Build and push + run: | + docker buildx build --platform linux/arm64 -t \ + ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} --push . + + deploy: + needs: build + runs-on: [ self-hosted, backend-dev ] + steps: + - name: Docker remove + run: | + CONTAINER_IDS=$(sudo docker ps -qa) + if [ -n "$CONTAINER_IDS" ]; then + sudo docker rm -f $CONTAINER_IDS + else + echo "No running containers found." + fi + + - name: Docker Image pull + run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} + + - name: Docker run + run: sudo docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=dev -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} diff --git a/.github/workflows/backend-prod.yml b/.github/workflows/backend-prod.yml new file mode 100644 index 000000000..f7daacd33 --- /dev/null +++ b/.github/workflows/backend-prod.yml @@ -0,0 +1,74 @@ +name: backend-push + +on: + push: + branches: [ "main" ] + paths: + - 'server/**' + +jobs: + build: + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ./server + + permissions: + contents: read + + steps: + - name: CheckOut + uses: actions/checkout@v4 + with: + token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} + submodules: true + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Test with Gradle Wrapper + run: ./gradlew clean build + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Set up Docker BuildX + uses: docker/setup-buildx-action@v3 + + - name: Build and push + run: | + docker buildx build --platform linux/arm64 -t \ + ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} --push . + + deploy: + needs: build + runs-on: [ self-hosted, backend-prod ] + steps: + - name: Docker remove + run: | + CONTAINER_IDS=$(sudo docker ps -qa) + if [ -n "$CONTAINER_IDS" ]; then + sudo docker rm -f $CONTAINER_IDS + else + echo "No running containers found." + fi + + - name: Docker Image pull + run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} + + - name: Docker run + run: sudo docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml new file mode 100644 index 000000000..df008fd97 --- /dev/null +++ b/.github/workflows/backend-pull-request.yml @@ -0,0 +1,44 @@ +name: backend-pull-request + +on: + pull_request: + branches: [ "main", "be-dev" ] + +jobs: + build: + runs-on: [ ubuntu-latest ] + + defaults: + run: + working-directory: ./server + + steps: + - name: CheckOut + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Test with Gradle Wrapper + run: ./gradlew clean build + + - name: publish unit test results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: server/build/test-results/test/TEST-*.xml + + - name: add comments to a pull request + uses: mikepenz/action-junit-report@v3 + if: always() + with: + report_paths: server/build/test-results/test/TEST-*.xml diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..d013a93bc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "server/src/main/resources/config"] + branch = main + path = server/src/main/resources/config + url = https://github.com/woowacourse-teams/2024-haeng-dong-config.git diff --git a/client/.gitkeep b/client/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 000000000..671ee930b --- /dev/null +++ b/server/.gitignore @@ -0,0 +1,244 @@ +# Created by https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux +# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij,gradle,macos,windows,linux + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### Gradle Patch ### +# Java heap dump +*.hprof + +# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux diff --git a/server/.gitkeep b/server/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 000000000..df2cf44e0 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,9 @@ +FROM openjdk:17-jdk-slim + +WORKDIR /app + +COPY /build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar + +EXPOSE 8080 +ENTRYPOINT ["java"] +CMD ["-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "-Duser.timezone=Asia/Seoul", "-jar", "haengdong-0.0.1-SNAPSHOT.jar"] diff --git a/server/build.gradle b/server/build.gradle new file mode 100644 index 000000000..4229de130 --- /dev/null +++ b/server/build.gradle @@ -0,0 +1,86 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.3.1' + id 'io.spring.dependency-management' version '1.1.5' + id 'org.asciidoctor.jvm.convert' version '3.3.2' +} + +group = 'server' +version = '0.0.1-SNAPSHOT' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } + asciidoctorExt +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + + implementation 'io.jsonwebtoken:jjwt:0.9.1' + implementation 'javax.xml.bind:jaxb-api:2.3.1' + + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + + runtimeOnly 'com.h2database:h2' + runtimeOnly 'com.mysql:mysql-connector-j' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' + testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' +} + +ext { + snippetsDir = file('build/generated-snippets') +} + +test { + useJUnitPlatform() + outputs.dir snippetsDir +} + +asciidoctor { + inputs.dir snippetsDir + configurations 'asciidoctorExt' + baseDirFollowsSourceFile() + dependsOn test +} + +tasks.resolveMainClassName { + dependsOn 'copyApiDocuments' +} + +tasks.register('copyApiDocuments', Copy) { + dependsOn asciidoctor + from file("build/docs/asciidoc") + into file("build/resources/main/static/docs") +} + +bootJar { + dependsOn copyApiDocuments +} + +jar { + enabled = false +} + +build { + dependsOn copyApiDocuments +} diff --git a/server/docs/24-08-04-erd.sql b/server/docs/24-08-04-erd.sql new file mode 100644 index 000000000..ae2fbc4a5 --- /dev/null +++ b/server/docs/24-08-04-erd.sql @@ -0,0 +1,65 @@ +-- Create tables +CREATE TABLE action +( + event_id BIGINT, + id BIGINT AUTO_INCREMENT, + sequence BIGINT, + PRIMARY KEY (id) +); + +CREATE TABLE bill_action +( + action_id BIGINT UNIQUE, + id BIGINT AUTO_INCREMENT, + price BIGINT, + title VARCHAR(30), + PRIMARY KEY (id) +); + +CREATE TABLE event +( + id BIGINT AUTO_INCREMENT, + name VARCHAR(255), + token VARCHAR(255), + PRIMARY KEY (id) +); + +CREATE TABLE event_step +( + event_id BIGINT, + id BIGINT AUTO_INCREMENT, + sequence BIGINT, + name VARCHAR(255), + PRIMARY KEY (id) +); + +CREATE TABLE member_action +( + action_id BIGINT UNIQUE, + id BIGINT AUTO_INCREMENT, + member_group_id BIGINT, + member_name VARCHAR(255), + status ENUM('IN', 'OUT'), + PRIMARY KEY (id) +); + +-- Add foreign key constraints +ALTER TABLE action + ADD CONSTRAINT FKgf0qmub9va1xbe44nehny31yw + FOREIGN KEY (event_id) + REFERENCES event (id); + +ALTER TABLE bill_action + ADD CONSTRAINT FK54tx517tp0ry6453olkply4us + FOREIGN KEY (action_id) + REFERENCES action (id); + +ALTER TABLE event_step + ADD CONSTRAINT FKe3rkib91cvl0x5w9wqkshmn81 + FOREIGN KEY (event_id) + REFERENCES event (id); + +ALTER TABLE member_action + ADD CONSTRAINT FK5jna51dn8fs2ir52l4uwn517u + FOREIGN KEY (action_id) + REFERENCES action (id); diff --git a/server/docs/24-08-04-erd.svg b/server/docs/24-08-04-erd.svg new file mode 100644 index 000000000..5a4bac225 --- /dev/null +++ b/server/docs/24-08-04-erd.svg @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Do not edit this file with editors other than draw.io --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1993px" height="1581px" viewBox="-0.5 -0.5 1993 1581" content="<mxfile host="app.diagrams.net" modified="2024-07-25T04:17:06.208Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" etag="gR5VLfYLO6MRu5dHcV28" version="24.7.3" type="github"> <diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1"> <mxGraphModel dx="2380" dy="2150" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> <root> <mxCell id="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="8gZzuRhjrYuwNxX9kY4q-98" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-442" y="-590" width="1992" height="1580" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=ERone;startFill=0;endArrow=ERzeroToMany;endFill=0;dashed=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-0" target="8gZzuRhjrYuwNxX9kY4q-37" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=ERone;startFill=0;endArrow=ERzeroToMany;endFill=0;dashed=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-0" target="8gZzuRhjrYuwNxX9kY4q-56" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-0" value="Event" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="40" y="40" width="280" height="120" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-1" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-2" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-3" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-137" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-7" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-8" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-9" value="token" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-138" value="varchar(20)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-4" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-5" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-6" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-139" value="varchar(255)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-37" value="Event_Step" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="40" y="240" width="280" height="150" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-38" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-39" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-40" value="event_step_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-143" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-41" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-42" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-43" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-144" value="varchar(30)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-44" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-45" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-46" value="sequence" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-145" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-48" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-49" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-50" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-146" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-77" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;startArrow=ERone;startFill=0;endArrow=ERone;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-56" target="8gZzuRhjrYuwNxX9kY4q-67" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-91" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;startArrow=ERone;startFill=0;endArrow=ERone;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-56" target="8gZzuRhjrYuwNxX9kY4q-81" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-56" value="Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="414" y="40" width="280" height="120" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-57" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-58" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-59" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-140" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-60" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-61" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-62" value="sequence" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-141" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-63" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-64" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-65" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-142" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-67" value="Bill_Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="414" y="240" width="280" height="150" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-68" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-69" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-70" value="bill_action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-147" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-71" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-72" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-73" value="title" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-148" value="varchar(30)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-78" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-79" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-80" value="price" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-149" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-74" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-75" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-76" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-150" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-81" value="Member_Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="790" y="40" width="280" height="180" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-82" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-83" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-84" value="member_action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-151" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-85" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-86" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-87" value="member_name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-152" value="varchar(20)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-92" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-93" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-94" value="status" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-153" value="varchar(10)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-95" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-96" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-97" value="member_group_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-154" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-88" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="150" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-89" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-90" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-155" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> </root> </mxGraphModel> </diagram> </mxfile> " resource="https://app.diagrams.net/?src=about#Hkunsanglee%2Fcafekiosk-study%2Fmain%2Fsrc%2Fmain%2Fresources%2Fexample2.svg#%7B%22pageId%22%3A%22C5RBs43oDa-KdzZeNtuy%22%7D"><defs/><g><g data-cell-id="WIyWlLk6GJQsqaUBKTNV-0"><g data-cell-id="WIyWlLk6GJQsqaUBKTNV-1"><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-98"><g><rect x="0" y="0" width="1992" height="1580" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-47"><g><path d="M 622 750 L 622 814.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 626 754 L 618 754" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="622" cy="818" rx="3" ry="3" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 626 830 L 622 822 L 618 830 M 622 822 L 622 830" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-66"><g><path d="M 762 690 L 840.5 690" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 766 686 L 766 694" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="844" cy="690" rx="3" ry="3" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 856 686 L 848 690 L 856 694 M 848 690 L 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-0"><g><path d="M 482 660 L 482 630 L 762 630 L 762 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 482 660 L 482 750 L 762 750 L 762 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 482 660 L 762 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 512 660 L 512 690 L 512 720 L 512 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 632 660 L 632 690 L 632 720 L 632 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 622px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Event</div></div></div></foreignObject><text x="622" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Event</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-1"><g><path d="M 482 660 M 762 660 M 762 690 L 482 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-2"><g><rect x="482" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 660 M 512 660 M 512 690 M 482 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="497" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-3"><g><rect x="512" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 660 M 632 660 M 632 690 M 512 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="520" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-137"><g><rect x="632" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 660 M 762 660 M 762 690 M 632 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-7"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-8"><g><rect x="482" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 690 M 512 690 M 512 720 M 482 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-9"><g><rect x="512" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 690 M 632 690 M 632 720 M 512 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">token</div></div></div></foreignObject><text x="520" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">token</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-138"><g><rect x="632" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 690 M 762 690 M 762 720 M 632 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(20)</div></div></div></foreignObject><text x="640" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(20)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-4"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-5"><g><rect x="482" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 720 M 512 720 M 512 750 M 482 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-6"><g><rect x="512" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 720 M 632 720 M 632 750 M 512 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">name</div></div></div></foreignObject><text x="520" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-139"><g><rect x="632" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 720 M 762 720 M 762 750 M 632 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(255)</div></div></div></foreignObject><text x="640" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(255)</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-37"><g><path d="M 482 860 L 482 830 L 762 830 L 762 860" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 482 860 L 482 980 L 762 980 L 762 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 482 860 L 762 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 512 860 L 512 890 L 512 920 L 512 950 L 512 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 632 860 L 632 890 L 632 920 L 632 950 L 632 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 845px; margin-left: 622px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Event_Step</div></div></div></foreignObject><text x="622" y="849" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Event_Step</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-38"><g><path d="M 482 860 M 762 860 M 762 890 L 482 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-39"><g><rect x="482" y="860" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 860 M 512 860 M 512 890 M 482 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 875px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="497" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-40"><g><rect x="512" y="860" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 860 M 632 860 M 632 890 M 512 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 875px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">event_step_id</div></div></div></foreignObject><text x="520" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">event_step_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-143"><g><rect x="632" y="860" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 860 M 762 860 M 762 890 M 632 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 875px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-41"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-42"><g><rect x="482" y="890" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 890 M 512 890 M 512 920 M 482 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-43"><g><rect x="512" y="890" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 890 M 632 890 M 632 920 M 512 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 905px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">name</div></div></div></foreignObject><text x="520" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-144"><g><rect x="632" y="890" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 890 M 762 890 M 762 920 M 632 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 905px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(30)</div></div></div></foreignObject><text x="640" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(30)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-44"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-45"><g><rect x="482" y="920" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 920 M 512 920 M 512 950 M 482 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-46"><g><rect x="512" y="920" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 920 M 632 920 M 632 950 M 512 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 935px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">sequence</div></div></div></foreignObject><text x="520" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">sequence</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-145"><g><rect x="632" y="920" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 920 M 762 920 M 762 950 M 632 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 935px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-48"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-49"><g><rect x="482" y="950" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 950 M 512 950 M 512 980 M 482 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 965px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="497" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-50"><g><rect x="512" y="950" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 950 M 632 950 M 632 980 M 512 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 965px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="520" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-146"><g><rect x="632" y="950" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 950 M 762 950 M 762 980 M 632 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 965px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-77"><g><path d="M 996 750 L 996 830" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 1000 754 L 992 754" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 992 826 L 1000 826" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-91"><g><path d="M 1136 690 L 1184 690 L 1184 720 L 1232 720" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 1140 686 L 1140 694" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1228 724 L 1228 716" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-56"><g><path d="M 856 660 L 856 630 L 1136 630 L 1136 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 856 660 L 856 750 L 1136 750 L 1136 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 856 660 L 1136 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 886 660 L 886 690 L 886 720 L 886 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1006 660 L 1006 690 L 1006 720 L 1006 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 996px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Action</div></div></div></foreignObject><text x="996" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-57"><g><path d="M 856 660 M 1136 660 M 1136 690 L 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-58"><g><rect x="856" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 660 M 886 660 M 886 690 M 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="871" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-59"><g><rect x="886" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 660 M 1006 660 M 1006 690 M 886 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="894" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-140"><g><rect x="1006" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 660 M 1136 660 M 1136 690 M 1006 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-60"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-61"><g><rect x="856" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 690 M 886 690 M 886 720 M 856 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-62"><g><rect x="886" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 690 M 1006 690 M 1006 720 M 886 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">sequence</div></div></div></foreignObject><text x="894" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">sequence</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-141"><g><rect x="1006" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 690 M 1136 690 M 1136 720 M 1006 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-63"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-64"><g><rect x="856" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 720 M 886 720 M 886 750 M 856 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 735px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="871" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-65"><g><rect x="886" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 720 M 1006 720 M 1006 750 M 886 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="894" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-142"><g><rect x="1006" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 720 M 1136 720 M 1136 750 M 1006 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-67"><g><path d="M 856 860 L 856 830 L 1136 830 L 1136 860" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 856 860 L 856 980 L 1136 980 L 1136 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 856 860 L 1136 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 886 860 L 886 890 L 886 920 L 886 950 L 886 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1006 860 L 1006 890 L 1006 920 L 1006 950 L 1006 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 845px; margin-left: 996px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Bill_Action</div></div></div></foreignObject><text x="996" y="849" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Bill_Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-68"><g><path d="M 856 860 M 1136 860 M 1136 890 L 856 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-69"><g><rect x="856" y="860" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 860 M 886 860 M 886 890 M 856 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 875px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="871" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-70"><g><rect x="886" y="860" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 860 M 1006 860 M 1006 890 M 886 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 875px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bill_action_id</div></div></div></foreignObject><text x="894" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bill_action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-147"><g><rect x="1006" y="860" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 860 M 1136 860 M 1136 890 M 1006 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 875px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-71"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-72"><g><rect x="856" y="890" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 890 M 886 890 M 886 920 M 856 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-73"><g><rect x="886" y="890" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 890 M 1006 890 M 1006 920 M 886 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 905px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">title</div></div></div></foreignObject><text x="894" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">title</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-148"><g><rect x="1006" y="890" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 890 M 1136 890 M 1136 920 M 1006 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 905px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(30)</div></div></div></foreignObject><text x="1014" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(30)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-78"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-79"><g><rect x="856" y="920" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 920 M 886 920 M 886 950 M 856 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-80"><g><rect x="886" y="920" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 920 M 1006 920 M 1006 950 M 886 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 935px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">price</div></div></div></foreignObject><text x="894" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">price</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-149"><g><rect x="1006" y="920" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 920 M 1136 920 M 1136 950 M 1006 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 935px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-74"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-75"><g><rect x="856" y="950" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 950 M 886 950 M 886 980 M 856 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 965px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="871" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-76"><g><rect x="886" y="950" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 950 M 1006 950 M 1006 980 M 886 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 965px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="894" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-150"><g><rect x="1006" y="950" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 950 M 1136 950 M 1136 980 M 1006 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 965px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-81"><g><path d="M 1232 660 L 1232 630 L 1512 630 L 1512 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1232 660 L 1232 810 L 1512 810 L 1512 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1232 660 L 1512 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1262 660 L 1262 690 L 1262 720 L 1262 750 L 1262 780 L 1262 810" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1382 660 L 1382 690 L 1382 720 L 1382 750 L 1382 780 L 1382 810" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 1372px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Member_Action</div></div></div></foreignObject><text x="1372" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Member_Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-82"><g><path d="M 1232 660 M 1512 660 M 1512 690 L 1232 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-83"><g><rect x="1232" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 660 M 1262 660 M 1262 690 M 1232 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 1233px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="1247" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-84"><g><rect x="1262" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 660 M 1382 660 M 1382 690 M 1262 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">member_action_id</div></div></div></foreignObject><text x="1270" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">member_action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-151"><g><rect x="1382" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 660 M 1512 660 M 1512 690 M 1382 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-85"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-86"><g><rect x="1232" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 690 M 1262 690 M 1262 720 M 1232 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-87"><g><rect x="1262" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 690 M 1382 690 M 1382 720 M 1262 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">member_name</div></div></div></foreignObject><text x="1270" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">member_name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-152"><g><rect x="1382" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 690 M 1512 690 M 1512 720 M 1382 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(20)</div></div></div></foreignObject><text x="1390" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(20)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-92"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-93"><g><rect x="1232" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 720 M 1262 720 M 1262 750 M 1232 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-94"><g><rect x="1262" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 720 M 1382 720 M 1382 750 M 1262 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">status</div></div></div></foreignObject><text x="1270" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">status</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-153"><g><rect x="1382" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 720 M 1512 720 M 1512 750 M 1382 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(10)</div></div></div></foreignObject><text x="1390" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(10)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-95"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-96"><g><rect x="1232" y="750" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 750 M 1262 750 M 1262 780 M 1232 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-97"><g><rect x="1262" y="750" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 750 M 1382 750 M 1382 780 M 1262 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 765px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">member_group_id</div></div></div></foreignObject><text x="1270" y="769" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">member_group_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-154"><g><rect x="1382" y="750" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 750 M 1512 750 M 1512 780 M 1382 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 765px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="769" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-88"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-89"><g><rect x="1232" y="780" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 780 M 1262 780 M 1262 810 M 1232 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 795px; margin-left: 1233px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="1247" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-90"><g><rect x="1262" y="780" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 780 M 1382 780 M 1382 810 M 1262 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 795px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="1270" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-155"><g><rect x="1382" y="780" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 780 M 1512 780 M 1512 810 M 1382 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 795px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g></g></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/server/gradle/wrapper/gradle-wrapper.jar b/server/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..e6441136f3d4ba8a0da8d277868979cfbc8ad796 GIT binary patch literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 UfUyy3EX0IC28@JalTrWuAK7&_a{vGU literal 0 HcmV?d00001 diff --git a/server/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..a4413138c --- /dev/null +++ b/server/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/server/gradlew b/server/gradlew new file mode 100644 index 000000000..b740cf133 --- /dev/null +++ b/server/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/server/gradlew.bat b/server/gradlew.bat new file mode 100644 index 000000000..25da30dbd --- /dev/null +++ b/server/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/server/settings.gradle b/server/settings.gradle new file mode 100644 index 000000000..dbbee46fb --- /dev/null +++ b/server/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'haengdong' diff --git a/server/src/docs/asciidoc/billAction.adoc b/server/src/docs/asciidoc/billAction.adoc new file mode 100644 index 000000000..dfd7e26db --- /dev/null +++ b/server/src/docs/asciidoc/billAction.adoc @@ -0,0 +1,121 @@ +== 지출 액션 + +=== 지출 액션 생성 + +operation::createBillActions[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"REQUEST_EMPTY", + "message":"지출 금액은 비어 있으면 안됩니다." + }, + { + "code":"REQUEST_EMPTY", + "message":"지출 내역은 비어 있으면 안됩니다." + }, + { + "code":"BILL_ACTION_TITLE_INVALID", + "message":"앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다." + }, + { + "code":"BILL_ACTION_PRICE_INVALID", + "message":"지출 금액은 10,000,000 이하의 자연수여야 합니다." + }, + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_EXPIRED", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_INVALID", + "message":"유효하지 않은 토큰입니다." + } +] +---- + +=== 지출 액션 수정 + +operation::updateBillAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"REQUEST_EMPTY", + "message":"지출 내역 제목은 공백일 수 없습니다." + }, + { + "code":"REQUEST_EMPTY", + "message":"지출 금액은 공백일 수 없습니다." + }, + { + "code":"BILL_ACTION_TITLE_INVALID", + "message":"앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다." + }, + { + "code":"BILL_ACTION_PRICE_INVALID", + "message":"지출 금액은 %,d 이하의 자연수여야 합니다." + }, + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + }, + { + "code":"BILL_ACTION_NOT_FOUND", + "message":"존재하지 않는 지출 액션입니다." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_EXPIRED", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_INVALID", + "message":"유효하지 않은 토큰입니다." + } +] +---- + +=== 지출 액션 삭제 + +operation::deleteBillAction[snippets="path-parameters,http-request,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_EXPIRED", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_INVALID", + "message":"유효하지 않은 토큰입니다." + } +] +---- diff --git a/server/src/docs/asciidoc/billActionDetail.adoc b/server/src/docs/asciidoc/billActionDetail.adoc new file mode 100644 index 000000000..a8f19f21b --- /dev/null +++ b/server/src/docs/asciidoc/billActionDetail.adoc @@ -0,0 +1,93 @@ +== 지출 상세 + +=== 지출 상세 조회 + +operation::findBillActionDetailsTest[snippets="path-parameters,http-request,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code": "EVENT_NOT_FOUND", + "message": "존재하지 않는 행사입니다." + }, + { + "code": "BILL_ACTION_NOT_FOUND", + "message": "존재하지 않는 지출 액션입니다." + }, + { + "code": "BILL_ACTION_DETAIL_NOT_FOUND", + "message": "존재하지 않는 참여자 지출입니다." + }, + { + "code": "TOKEN_NOT_FOUND", + "message": "토큰이 존재하지 않습니다." + }, + { + "code": "TOKEN_EXPIRED", + "message": "만료된 토큰입니다." + }, + { + "code": "TOKEN_INVALID", + "message": "유효하지 않은 토큰입니다." + }, + { + "code": "FORBIDDEN", + "message": "접근할 수 없는 행사입니다." + } +] +---- + +=== 지출 상세 수정 + +operation::updateBillActionDetailsTest[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code": "REQUEST_EMPTY", + "message": "멤버 이름은 공백일 수 없습니다." + }, + { + "code": "REQUEST_EMPTY", + "message": "지출 금액은 공백일 수 없습니다." + }, + { + "code": "EVENT_NOT_FOUND", + "message": "존재하지 않는 행사입니다." + }, + { + "code": "BILL_ACTION_NOT_FOUND", + "message": "존재하지 않는 지출 액션입니다." + }, + { + "code": "BILL_ACTION_DETAIL_NOT_FOUND", + "message": "존재하지 않는 참여자 지출입니다." + }, + { + "code": "BILL_ACTION_PRICE_NOT_MATCHED", + "message": "지출 총액이 일치하지 않습니다." + }, + { + "code": "TOKEN_NOT_FOUND", + "message": "토큰이 존재하지 않습니다." + }, + { + "code": "TOKEN_EXPIRED", + "message": "만료된 토큰입니다." + }, + { + "code": "TOKEN_INVALID", + "message": "유효하지 않은 토큰입니다." + }, + { + "code": "FORBIDDEN", + "message": "접근할 수 없는 행사입니다." + } +] +---- diff --git a/server/src/docs/asciidoc/event.adoc b/server/src/docs/asciidoc/event.adoc new file mode 100644 index 000000000..72511b91b --- /dev/null +++ b/server/src/docs/asciidoc/event.adoc @@ -0,0 +1,205 @@ +== 행사 + +=== 행사 생성 + +operation::createEvent[snippets="http-request,request-body,request-fields,response-body,response-fields,http-response,response-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"REQUEST_EMPTY", + "message":"행사 이름은 공백일 수 없습니다." + }, + { + "code":"EVENT_NAME_LENGTH_INVALID", + "message":"행사 이름은 2자 이상 30자 이하만 입력 가능합니다. 입력한 이름 길이 : 21" + }, + { + "code":"EVENT_NAME_MULTIPLE_BLANK", + "message":"행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : 공백 문자" + }, + { + "code":"EVENT_PASSWORD_INVALID", + "message":"비밀번호는 4자리 숫자만 가능합니다." + } +] +---- + +=== 행사 관리자 로그인 + +operation::eventLogin[snippets="path-parameters,http-request,request-body,request-fields,http-response,response-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + }, + { + "code":"REQUEST_EMPTY", + "message":"비밀번호는 공백일 수 없습니다." + }, + { + "code":"PASSWORD_INVALID", + "message":"비밀번호가 일치하지 않습니다." + } +] +---- + +=== 행사 정보 조회 + +operation::getEvent[snippets="path-parameters,http-request,response-body,response-fields,http-response"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + } +] +---- + +=== 행사 전체 참여자 목록 조회 + +operation::findAllEventMember[snippets="path-parameters,http-request,response-body,response-fields,http-response,response-fields"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + } +] +---- + +=== 행사 전체 액션 이력 조회 + +operation::findActions[snippets="path-parameters,http-request,http-response,response-fields"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + } +] +---- + +=== 행사 참여자 이름 변경 + +operation::updateEventMemberName[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + + { + "code":"MEMBER_NAME_CHANGE_DUPLICATE", + "message":"중복된 참여 인원 이름 변경 요청이 존재합니다." + }, + { + "code":"MEMBER_NOT_EXIST", + "message":"현재 참여하고 있지 않는 인원이 존재합니다." + }, + { + "code":"REQUEST_EMPTY", + "message":"멤버 이름은 공백일 수 없습니다." + }, + { + "code":"MEMBER_NAME_LENGTH_INVALID", + "message":"멤버 이름은 1자 이상 4자 이하만 입력 가능합니다." + }, + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + }, + { + "code":"MEMBER_NAME_DUPLICATE", + "message":"중복된 행사 참여 인원 이름이 존재합니다." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_EXPIRED", + "message":"만료된 토큰입니다." + }, + { + "code":"TOKEN_INVALID", + "message":"유효하지 않은 토큰입니다." + } +] +---- + +=== 행사 참여자 삭제 (특정 참여자의 모든 참여자 액션 삭제) + +operation::deleteAllMemberActionByName[snippets="path-parameters,http-request,http-response,request-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_EXPIRED", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_INVALID", + "message":"유효하지 않은 토큰입니다." + } +] +---- + +=== 행사 어드민 권한 확인 + +operation::authenticateEvent[snippets="http-request,http-response,request-cookies"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code": "EVENT_NOT_FOUND", + "message": "존재하지 않는 행사입니다." + }, + { + "code": "TOKEN_NOT_FOUND", + "message": "토큰이 존재하지 않습니다." + }, + { + "code": "TOKEN_EXPIRED", + "message": "만료된 토큰입니다." + }, + { + "code": "TOKEN_INVALID", + "message": "유효하지 않은 토큰입니다." + }, + { + "code": "FORBIDDEN", + "message": "접근할 수 없는 행사입니다." + } +] +---- diff --git a/server/src/docs/asciidoc/index.adoc b/server/src/docs/asciidoc/index.adoc new file mode 100644 index 000000000..8e1bcd2d0 --- /dev/null +++ b/server/src/docs/asciidoc/index.adoc @@ -0,0 +1,15 @@ +ifndef::snippets[] +:snippets: ../../build/generated-snippets +endif::[] += 행동대장 +:source-highlighter: highlightjs :hardbreaks: +:toc: left :doctype: book :icons: font :toc-title: 전체 API 목록 :toclevels: 2 :sectlinks: +:sectnums: +:sectnumlevels: 2 + + +include::{docdir}/event.adoc[] +include::{docdir}/memberBillReport.adoc[] +include::{docdir}/memberAction.adoc[] +include::{docdir}/billAction.adoc[] +include::{docdir}/billActionDetail.adoc[] diff --git a/server/src/docs/asciidoc/memberAction.adoc b/server/src/docs/asciidoc/memberAction.adoc new file mode 100644 index 000000000..897102c8d --- /dev/null +++ b/server/src/docs/asciidoc/memberAction.adoc @@ -0,0 +1,100 @@ +== 참여자 액션 + +=== 참여자 액션 생성 + +operation::createMemberAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"REQUEST_EMPTY", + "message":"멤버 액션은 공백일 수 없습니다." + }, + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + }, + { + "code":"MEMBER_ACTION_STATUS_INVALID", + "message":"멤버 액션은 IN, OUT만 가능합니다. 입력한 멤버 액션: I_N" + }, + { + "code":"MEMBER_ALREADY_EXIST", + "message":"현재 참여하고 있는 인원이 존재합니다." + }, + { + "code":"MEMBER_NOT_EXIST", + "message":"현재 참여하고 있지 않는 인원이 존재합니다." + }, + { + "code":"MEMBER_NAME_DUPLICATE", + "message":"중복된 이름이 존재합니다. 입력된 이름: 이상, 이상, 감자, 백호" + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_EXPIRED", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_INVALID", + "message":"유효하지 않은 토큰입니다." + } +] +---- + +=== 현재 행사에 참여 중인 (탈주 가능한) 참여자 목록 조회 + +operation::getCurrentMembers[snippets="path-parameters,http-request,http-response,response-fields"] +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + } +] +---- + +=== 참여자 액션 삭제 + +operation::deleteMemberAction[snippets="path-parameters,http-request,http-response,request-cookies"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + }, + { + "code":"ACTION_NOT_FOUND", + "message":"존재하지 않는 액션입니다." + }, + { + "code":"MEMBER_ACTION_NOT_FOUND", + "message":"존재하지 않는 멤버 액션입니다." + }, + { + "code":"TOKEN_NOT_FOUND", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_EXPIRED", + "message":"토큰이 존재하지 않습니다." + }, + { + "code":"TOKEN_INVALID", + "message":"유효하지 않은 토큰입니다." + } +] +---- diff --git a/server/src/docs/asciidoc/memberBillReport.adoc b/server/src/docs/asciidoc/memberBillReport.adoc new file mode 100644 index 000000000..18bd7d3ef --- /dev/null +++ b/server/src/docs/asciidoc/memberBillReport.adoc @@ -0,0 +1,17 @@ +== 정산 + +=== 참여자별 정산 결과 조회 + +operation::getMemberBillReports[snippets="path-parameters,http-request,response-body,response-fields,http-response,http-request"] + +==== [.red]#Exceptions# + +[source,json,options="nowrap"] +---- +[ + { + "code":"EVENT_NOT_FOUND", + "message":"존재하지 않는 행사입니다." + } +] +---- diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java new file mode 100644 index 000000000..4a84c6120 --- /dev/null +++ b/server/src/main/java/server/haengdong/HaengdongApplication.java @@ -0,0 +1,15 @@ +package server.haengdong; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@Slf4j +@SpringBootApplication +public class HaengdongApplication { + + public static void main(String[] args) { + SpringApplication.run(HaengdongApplication.class, args); + } + +} diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java new file mode 100644 index 000000000..bcf5e8b55 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/ActionService.java @@ -0,0 +1,39 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberBillReport; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class ActionService { + + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + private final EventRepository eventRepository; + + public List<MemberBillReportAppResponse> getMemberBillReports(String token) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + List<BillAction> billActions = billActionRepository.findByAction_Event(event); + List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); + + MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); + + return memberBillReport.getReports().entrySet().stream() + .map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue())) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/application/AuthService.java b/server/src/main/java/server/haengdong/application/AuthService.java new file mode 100644 index 000000000..d9352ad53 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/AuthService.java @@ -0,0 +1,41 @@ +package server.haengdong.application; + + +import java.util.Map; +import server.haengdong.domain.TokenProvider; +import server.haengdong.exception.AuthenticationException; +import server.haengdong.exception.HaengdongErrorCode; + +public class AuthService { + + private static final String TOKEN_NAME = "eventToken"; + private static final String CLAIM_SUB = "sub"; + + private final TokenProvider tokenProvider; + + public AuthService(TokenProvider tokenProvider) { + this.tokenProvider = tokenProvider; + } + + public String createToken(String eventId) { + Map<String, Object> payload = Map.of(CLAIM_SUB, eventId); + + return tokenProvider.createToken(payload); + } + + public String findEventIdByToken(String token) { + validateToken(token); + Map<String, Object> payload = tokenProvider.getPayload(token); + return (String) payload.get(CLAIM_SUB); + } + + private void validateToken(String token) { + if (!tokenProvider.validateToken(token)) { + throw new AuthenticationException(HaengdongErrorCode.TOKEN_INVALID); + } + } + + public String getTokenName() { + return TOKEN_NAME; + } +} diff --git a/server/src/main/java/server/haengdong/application/BillActionDetailService.java b/server/src/main/java/server/haengdong/application/BillActionDetailService.java new file mode 100644 index 000000000..55d39aac0 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/BillActionDetailService.java @@ -0,0 +1,76 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.BillActionDetailUpdateAppRequest; +import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class BillActionDetailService { + + private final BillActionRepository billActionRepository; + + public BillActionDetailsAppResponse findBillActionDetails(String token, Long actionId) { + BillAction billAction = billActionRepository.findByAction_Id(actionId) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); + validateToken(token, billAction); + + List<BillActionDetail> billActionDetails = billAction.getBillActionDetails(); + return BillActionDetailsAppResponse.of(billActionDetails); + } + + @Transactional + public void updateBillActionDetails(String token, Long actionId, BillActionDetailsUpdateAppRequest request) { + BillAction billAction = billActionRepository.findByAction_Id(actionId) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); + + List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests = request.billActionDetailUpdateAppRequests(); + + validateToken(token, billAction); + validateTotalPrice(billActionDetailUpdateAppRequests, billAction); + + List<BillActionDetail> billActionDetails = billAction.getBillActionDetails(); + + for (BillActionDetailUpdateAppRequest updateRequest : billActionDetailUpdateAppRequests) { + BillActionDetail detailToUpdate = billActionDetails.stream() + .filter(detail -> detail.isSameName(updateRequest.name())) + .findFirst() + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_DETAIL_NOT_FOUND)); + + detailToUpdate.updatePrice(updateRequest.price()); + detailToUpdate.updateIsFixed(updateRequest.isFixed()); + } + } + + private void validateToken(String token, BillAction billAction) { + Event event = billAction.getEvent(); + if (event.isTokenMismatch(token)) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND); + } + } + + private void validateTotalPrice(List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests, + BillAction billAction) { + Long requestsPriceSum = calculateUpdatePriceSum(billActionDetailUpdateAppRequests); + if (!billAction.isSamePrice(requestsPriceSum)) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_PRICE_NOT_MATCHED); + } + } + + private Long calculateUpdatePriceSum(List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests) { + return billActionDetailUpdateAppRequests.stream() + .map(BillActionDetailUpdateAppRequest::price) + .reduce(0L, Long::sum); + } +} diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java new file mode 100644 index 000000000..dae36a2e7 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/BillActionService.java @@ -0,0 +1,80 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.BillActionAppRequest; +import server.haengdong.application.request.BillActionUpdateAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class BillActionService { + + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + private final ActionRepository actionRepository; + private final EventRepository eventRepository; + + @Transactional + public void saveAllBillAction(String eventToken, List<BillActionAppRequest> requests) { + Event event = getEvent(eventToken); + Action action = createStartAction(event); + List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); + CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); + + for (BillActionAppRequest request : requests) { + BillAction billAction = request.toBillAction(action, currentMembers); + billActionRepository.save(billAction); + action = action.next(); + } + } + + private Action createStartAction(Event event) { + return actionRepository.findLastByEvent(event) + .map(Action::next) + .orElse(Action.createFirst(event)); + } + + @Transactional + public void updateBillAction(String token, Long actionId, BillActionUpdateAppRequest request) { + BillAction billAction = billActionRepository.findByAction_Id(actionId) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); + + validateToken(token, billAction); + + billAction.update(request.title(), request.price()); + } + + private void validateToken(String token, BillAction billAction) { + Event event = billAction.getEvent(); + if (event.isTokenMismatch(token)) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND); + } + } + + @Transactional + public void deleteBillAction(String token, Long actionId) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + + billActionRepository.deleteByAction_EventAndActionId(event, actionId); + } + + private Event getEvent(String eventToken) { + return eventRepository.findByToken(eventToken) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + } +} diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java new file mode 100644 index 000000000..834c0e10a --- /dev/null +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -0,0 +1,165 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.request.EventLoginAppRequest; +import server.haengdong.application.request.MemberNameUpdateAppRequest; +import server.haengdong.application.request.MemberNamesUpdateAppRequest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.event.EventTokenProvider; +import server.haengdong.exception.AuthenticationException; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class EventService { + + private final EventRepository eventRepository; + private final EventTokenProvider eventTokenProvider; + private final BillActionRepository billActionRepository; + private final MemberActionRepository memberActionRepository; + + @Transactional + public EventAppResponse saveEvent(EventAppRequest request) { + String token = eventTokenProvider.createToken(); + Event event = request.toEvent(token); + eventRepository.save(event); + + return EventAppResponse.of(event); + } + + public EventDetailAppResponse findEvent(String token) { + Event event = getEvent(token); + + return EventDetailAppResponse.of(event); + } + + public List<ActionAppResponse> findActions(String token) { + Event event = getEvent(token); + + List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() + .sorted(Comparator.comparing(BillAction::getSequence)).toList(); + List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event).stream() + .sorted(Comparator.comparing(MemberAction::getSequence)).toList(); + + return getActionAppResponses(billActions, memberActions); + } + + private List<ActionAppResponse> getActionAppResponses( + List<BillAction> billActions, + List<MemberAction> memberActions + ) { + int billActionIndex = 0; + int memberActionIndex = 0; + List<ActionAppResponse> actionAppResponses = new ArrayList<>(); + + while (billActionIndex < billActions.size() && memberActionIndex < memberActions.size()) { + BillAction billAction = billActions.get(billActionIndex); + MemberAction memberAction = memberActions.get(memberActionIndex); + if (billAction.getSequence() < memberAction.getSequence()) { + actionAppResponses.add(ActionAppResponse.of(billAction)); + billActionIndex++; + } else { + actionAppResponses.add(ActionAppResponse.of(memberAction)); + memberActionIndex++; + } + } + while (billActionIndex < billActions.size()) { + BillAction billAction = billActions.get(billActionIndex++); + actionAppResponses.add(ActionAppResponse.of(billAction)); + } + while (memberActionIndex < memberActions.size()) { + MemberAction memberAction = memberActions.get(memberActionIndex++); + actionAppResponses.add(ActionAppResponse.of(memberAction)); + } + + return actionAppResponses; + } + + public MembersAppResponse findAllMembers(String token) { + Event event = getEvent(token); + + List<String> memberNames = memberActionRepository.findAllUniqueMemberByEvent(event); + + return new MembersAppResponse(memberNames); + } + + @Transactional + public void updateMember(String token, MemberNamesUpdateAppRequest request) { + Event event = getEvent(token); + List<MemberNameUpdateAppRequest> members = request.members(); + + validateBeforeNames(members, event); + validateAfterNames(members, event); + + members.forEach(member -> updateMemberName(event, member.before(), member.after())); + } + + private void validateBeforeNames(List<MemberNameUpdateAppRequest> members, Event event) { + List<String> beforeNames = members.stream() + .map(MemberNameUpdateAppRequest::before) + .toList(); + if (beforeNames.size() != Set.copyOf(beforeNames).size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); + } + beforeNames.forEach(beforeName -> validateBeforeMemberNameExist(event, beforeName)); + } + + private void validateBeforeMemberNameExist(Event event, String beforeName) { + boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, beforeName); + if (!isMemberNameExist) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NOT_EXIST); + } + } + + private void validateAfterNames(List<MemberNameUpdateAppRequest> members, Event event) { + List<String> afterNames = members.stream() + .map(MemberNameUpdateAppRequest::after) + .toList(); + if (afterNames.size() != Set.copyOf(afterNames).size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); + } + afterNames.forEach(afterName -> validateAfterMemberNameNotExist(event, afterName)); + } + + private void validateAfterMemberNameNotExist(Event event, String afterName) { + boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, afterName); + if (isMemberNameExist) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); + } + } + + private void updateMemberName(Event event, String beforeName, String afterName) { + memberActionRepository.findAllByAction_EventAndMemberName(event, beforeName) + .forEach(memberAction -> memberAction.updateMemberName(afterName)); + } + + public void validatePassword(EventLoginAppRequest request) throws HaengdongException { + Event event = getEvent(request.token()); + if (event.isPasswordMismatch(request.password())) { + throw new AuthenticationException(HaengdongErrorCode.PASSWORD_INVALID); + } + } + + private Event getEvent(String token) { + return eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + } +} diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java new file mode 100644 index 000000000..c0a171642 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/MemberActionFactory.java @@ -0,0 +1,62 @@ +package server.haengdong.application; + +import java.util.ArrayList; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.action.MemberGroupIdProvider; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Component +public class MemberActionFactory { + + private final MemberGroupIdProvider memberGroupIdProvider; + + public List<MemberAction> createMemberActions( + MemberActionsSaveAppRequest request, + CurrentMembers currentMembers, + Action action + ) { + validateMemberNames(request); + validateActions(request, currentMembers); + + Long memberGroupId = memberGroupIdProvider.createGroupId(); + List<MemberAction> createdMemberActions = new ArrayList<>(); + List<MemberActionSaveAppRequest> actions = request.actions(); + for (MemberActionSaveAppRequest appRequest : actions) { + MemberAction memberAction = appRequest.toMemberAction(action, memberGroupId); + createdMemberActions.add(memberAction); + action = action.next(); + } + + return createdMemberActions; + } + + private void validateMemberNames(MemberActionsSaveAppRequest request) { + List<String> memberNames = request.actions().stream() + .map(MemberActionSaveAppRequest::name) + .toList(); + + long uniqueCount = memberNames.stream().distinct().count(); + if (uniqueCount != memberNames.size()) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); + } + } + + private void validateActions(MemberActionsSaveAppRequest request, CurrentMembers currentMembers) { + List<MemberActionSaveAppRequest> actions = request.actions(); + + for (MemberActionSaveAppRequest action : actions) { + MemberActionStatus memberActionStatus = MemberActionStatus.of(action.status()); + currentMembers.validate(action.name(), memberActionStatus); + } + } +} diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java new file mode 100644 index 000000000..245de8cef --- /dev/null +++ b/server/src/main/java/server/haengdong/application/MemberActionService.java @@ -0,0 +1,100 @@ +package server.haengdong.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.ActionRepository; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Service +public class MemberActionService { + + private final MemberActionFactory memberActionFactory; + private final MemberActionRepository memberActionRepository; + private final EventRepository eventRepository; + private final ActionRepository actionRepository; + private final BillActionRepository billActionRepository; + + @Transactional + public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { + Event event = findEvent(token); + + List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); + CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); + Action action = createStartAction(event); + List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, currentMembers, action); + memberActionRepository.saveAll(memberActions); + } + + private Action createStartAction(Event event) { + return actionRepository.findLastByEvent(event) + .map(Action::next) + .orElse(Action.createFirst(event)); + } + + public List<CurrentMemberAppResponse> getCurrentMembers(String token) { + Event event = findEvent(token); + List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); + CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); + + return currentMembers.getMembers() + .stream() + .map(CurrentMemberAppResponse::new) + .toList(); + } + + private Event findEvent(String token) { + return eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + } + + @Transactional + public void deleteMember(String token, String memberName) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + + memberActionRepository.deleteAllByEventAndMemberName(event, memberName); + + List<BillAction> billActions = billActionRepository.findByAction_Event(event); + billActions.forEach(billAction -> resetBillAction(event, billAction)); + } + + @Transactional + public void deleteMemberAction(String token, Long actionId) { + Event event = eventRepository.findByToken(token) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); + Action action = actionRepository.findByIdAndEvent(actionId, event) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.ACTION_NOT_FOUND)); + MemberAction memberAction = memberActionRepository.findByAction(action) + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.MEMBER_ACTION_NOT_FOUND)); + + memberActionRepository.deleteAllByMemberNameAndMinSequence(memberAction.getMemberName(), + memberAction.getSequence()); + + List<BillAction> billActions = billActionRepository.findByEventAndGreaterThanSequence(event, + action.getSequence()); + billActions.forEach(billAction -> resetBillAction(event, billAction)); + } + + private void resetBillAction(Event event, BillAction billAction) { + List<MemberAction> memberActions = memberActionRepository.findByEventAndSequence(event, + billAction.getSequence()); + CurrentMembers currentMembers = CurrentMembers.of(memberActions); + + billAction.resetBillActionDetails(currentMembers); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java new file mode 100644 index 000000000..21eb17d4a --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java @@ -0,0 +1,15 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.CurrentMembers; + +public record BillActionAppRequest( + String title, + Long price +) { + + public BillAction toBillAction(Action action, CurrentMembers currentMembers) { + return BillAction.create(action, title, price, currentMembers); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java new file mode 100644 index 000000000..e514aee81 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java @@ -0,0 +1,8 @@ +package server.haengdong.application.request; + +public record BillActionDetailUpdateAppRequest( + String name, + Long price, + boolean isFixed +) { +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java new file mode 100644 index 000000000..1fe19798e --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java @@ -0,0 +1,8 @@ +package server.haengdong.application.request; + +import java.util.List; + +public record BillActionDetailsUpdateAppRequest( + List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests +) { +} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java new file mode 100644 index 000000000..a90e3dd42 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java @@ -0,0 +1,7 @@ +package server.haengdong.application.request; + +public record BillActionUpdateAppRequest( + String title, + Long price +) { +} diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java new file mode 100644 index 000000000..20ec16d88 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java @@ -0,0 +1,10 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.event.Event; + +public record EventAppRequest(String name, String password) { + + public Event toEvent(String token) { + return new Event(name, password, token); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java new file mode 100644 index 000000000..947b5ef39 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java @@ -0,0 +1,4 @@ +package server.haengdong.application.request; + +public record EventLoginAppRequest(String token, String password) { +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java new file mode 100644 index 000000000..f7f8d8fc2 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java @@ -0,0 +1,12 @@ +package server.haengdong.application.request; + +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; + +public record MemberActionSaveAppRequest(String name, String status) { + + public MemberAction toMemberAction(Action action, Long memberGroupId) { + return new MemberAction(action, name, MemberActionStatus.of(status), memberGroupId); + } +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java new file mode 100644 index 000000000..650b908df --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java @@ -0,0 +1,6 @@ +package server.haengdong.application.request; + +import java.util.List; + +public record MemberActionsSaveAppRequest(List<MemberActionSaveAppRequest> actions) { +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java new file mode 100644 index 000000000..d629d3a02 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java @@ -0,0 +1,7 @@ +package server.haengdong.application.request; + +public record MemberNameUpdateAppRequest( + String before, + String after +) { +} diff --git a/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java new file mode 100644 index 000000000..cd0c00544 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java @@ -0,0 +1,8 @@ +package server.haengdong.application.request; + +import java.util.List; + +public record MemberNamesUpdateAppRequest( + List<MemberNameUpdateAppRequest> members +) { +} diff --git a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java new file mode 100644 index 000000000..0c2c12611 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java @@ -0,0 +1,61 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionStatus; + +public record ActionAppResponse( + Long actionId, + String name, + Long price, + Long sequence, + boolean isFixed, + ActionType actionType +) { + + public ActionAppResponse(Long actionId, String name, Long price, Long sequence, ActionType actionType) { + this(actionId, name, price, sequence, false, actionType); + } + + public static ActionAppResponse of(BillAction billAction) { + return new ActionAppResponse( + billAction.getAction().getId(), + billAction.getTitle(), + billAction.getPrice(), + billAction.getSequence(), + billAction.isFixed(), + ActionAppResponse.ActionType.BILL + ); + } + + public static ActionAppResponse of(MemberAction memberAction) { + MemberActionStatus status = memberAction.getStatus(); + + return new ActionAppResponse( + memberAction.getAction().getId(), + memberAction.getMemberName(), + null, + memberAction.getSequence(), + false, + ActionAppResponse.ActionType.of(status) + ); + } + + public String actionTypeName() { + return actionType.name(); + } + + public enum ActionType { + BILL, + IN, + OUT, + ; + + private static ActionType of(MemberActionStatus memberActionStatus) { + if (MemberActionStatus.IN == memberActionStatus) { + return IN; + } + return OUT; + } + } +} diff --git a/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java new file mode 100644 index 000000000..3efc7ac9d --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java @@ -0,0 +1,18 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.BillActionDetail; + +public record BillActionDetailAppResponse( + String name, + Long price, + boolean isFixed +) { + + public static BillActionDetailAppResponse of(BillActionDetail billActionDetail) { + return new BillActionDetailAppResponse( + billActionDetail.getMemberName(), + billActionDetail.getPrice(), + billActionDetail.isFixed() + ); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java b/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java new file mode 100644 index 000000000..061f07816 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java @@ -0,0 +1,14 @@ +package server.haengdong.application.response; + +import java.util.List; +import java.util.stream.Collectors; +import server.haengdong.domain.action.BillActionDetail; + +public record BillActionDetailsAppResponse(List<BillActionDetailAppResponse> billActionDetailAppResponses) { + + public static BillActionDetailsAppResponse of(List<BillActionDetail> billActionDetails) { + return billActionDetails.stream() + .map(BillActionDetailAppResponse::of) + .collect(Collectors.collectingAndThen(Collectors.toList(), BillActionDetailsAppResponse::new)); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java new file mode 100644 index 000000000..6c682d3e9 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.action.MemberAction; + +public record CurrentMemberAppResponse(String name) { + + public static CurrentMemberAppResponse of(MemberAction memberAction) { + return new CurrentMemberAppResponse(memberAction.getMemberName()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java new file mode 100644 index 000000000..f331d0011 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.event.Event; + +public record EventAppResponse(String token) { + + public static EventAppResponse of(Event event) { + return new EventAppResponse(event.getToken()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java new file mode 100644 index 000000000..6e38826d4 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.application.response; + +import server.haengdong.domain.event.Event; + +public record EventDetailAppResponse(String eventName) { + + public static EventDetailAppResponse of(Event event) { + return new EventDetailAppResponse(event.getName()); + } +} diff --git a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java new file mode 100644 index 000000000..21b6cef56 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java @@ -0,0 +1,4 @@ +package server.haengdong.application.response; + +public record MemberBillReportAppResponse(String name, Long price) { +} diff --git a/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java b/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java new file mode 100644 index 000000000..be8378b37 --- /dev/null +++ b/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java @@ -0,0 +1,8 @@ +package server.haengdong.application.response; + +import java.util.List; + +public record MembersAppResponse( + List<String> memberNames +) { +} diff --git a/server/src/main/java/server/haengdong/config/AdminInterceptor.java b/server/src/main/java/server/haengdong/config/AdminInterceptor.java new file mode 100644 index 000000000..a0542ed46 --- /dev/null +++ b/server/src/main/java/server/haengdong/config/AdminInterceptor.java @@ -0,0 +1,51 @@ +package server.haengdong.config; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import server.haengdong.application.AuthService; +import server.haengdong.exception.AuthenticationException; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.infrastructure.auth.AuthenticationExtractor; + +@Slf4j +public class AdminInterceptor implements HandlerInterceptor { + + private final AuthService authService; + private final AuthenticationExtractor authenticationExtractor; + + public AdminInterceptor(AuthService authService, AuthenticationExtractor authenticationExtractor) { + this.authService = authService; + this.authenticationExtractor = authenticationExtractor; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + String requestURI = request.getRequestURI(); + + if (requestURI.endsWith("/login")) { + return true; // 요청을 계속 진행하도록 허용 + } + + HttpMethod method = HttpMethod.valueOf(request.getMethod()); + if (HttpMethod.GET.equals(method) || HttpMethod.OPTIONS.equals(method)) { + return true; + } + + validateToken(request); + + return true; + } + + private void validateToken(HttpServletRequest request) { + String token = authenticationExtractor.extract(request, authService.getTokenName()); + String tokenEventId = authService.findEventIdByToken(token); + String eventId = request.getRequestURI().split("/")[3]; + if (!tokenEventId.equals(eventId)) { + log.warn("[행사 접근 불가] Cookie EventId = {}, URL EventId = {}", tokenEventId, eventId); + throw new AuthenticationException(HaengdongErrorCode.FORBIDDEN); + } + } +} diff --git a/server/src/main/java/server/haengdong/config/RequestServletFilter.java b/server/src/main/java/server/haengdong/config/RequestServletFilter.java new file mode 100644 index 000000000..b1afdb6f8 --- /dev/null +++ b/server/src/main/java/server/haengdong/config/RequestServletFilter.java @@ -0,0 +1,23 @@ +package server.haengdong.config; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; +import org.springframework.stereotype.Component; +import org.springframework.web.util.ContentCachingRequestWrapper; + +@Component +public class RequestServletFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper((HttpServletRequest) request); + + chain.doFilter(wrappedRequest, response); + } +} diff --git a/server/src/main/java/server/haengdong/config/WebMvcConfig.java b/server/src/main/java/server/haengdong/config/WebMvcConfig.java new file mode 100644 index 000000000..d1caa176f --- /dev/null +++ b/server/src/main/java/server/haengdong/config/WebMvcConfig.java @@ -0,0 +1,66 @@ +package server.haengdong.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import server.haengdong.application.AuthService; +import server.haengdong.domain.TokenProvider; +import server.haengdong.infrastructure.auth.AuthenticationExtractor; +import server.haengdong.infrastructure.auth.JwtTokenProvider; +import server.haengdong.infrastructure.auth.TokenProperties; + +@RequiredArgsConstructor +@EnableConfigurationProperties(TokenProperties.class) +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + + private final TokenProperties tokenProperties; + + @Value("${cors.max-age}") + private Long maxAge; + + @Value("${cors.allowed-origins}") + private String[] allowedOrigins; + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins(allowedOrigins) + .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") + .allowedHeaders("*") + .allowCredentials(true) + .maxAge(maxAge); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(adminInterceptor()) + .addPathPatterns("/api/**") + .excludePathPatterns("/api/events"); + } + + @Bean + public AdminInterceptor adminInterceptor() { + return new AdminInterceptor(authService(), authenticationExtractor()); + } + + @Bean + public AuthService authService() { + return new AuthService(tokenProvider()); + } + + @Bean + public TokenProvider tokenProvider() { + return new JwtTokenProvider(tokenProperties); + } + + @Bean + public AuthenticationExtractor authenticationExtractor() { + return new AuthenticationExtractor(); + } +} diff --git a/server/src/main/java/server/haengdong/domain/TokenProvider.java b/server/src/main/java/server/haengdong/domain/TokenProvider.java new file mode 100644 index 000000000..28e7956c3 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/TokenProvider.java @@ -0,0 +1,12 @@ +package server.haengdong.domain; + +import java.util.Map; + +public interface TokenProvider { + + String createToken(Map<String, Object> payload); + + Map<String, Object> getPayload(String token); + + boolean validateToken(String token); +} diff --git a/server/src/main/java/server/haengdong/domain/action/Action.java b/server/src/main/java/server/haengdong/domain/action/Action.java new file mode 100644 index 000000000..11f91fc38 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/Action.java @@ -0,0 +1,42 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.domain.event.Event; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Action { + + private static final long FIRST_SEQUENCE = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Event event; + + private Long sequence; + + public Action(Event event, Long sequence) { + this.event = event; + this.sequence = sequence; + } + + public static Action createFirst(Event event) { + return new Action(event, FIRST_SEQUENCE); + } + + public Action next() { + return new Action(event, sequence + 1); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java new file mode 100644 index 000000000..2fde0ffa6 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java @@ -0,0 +1,23 @@ +package server.haengdong.domain.action; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface ActionRepository extends JpaRepository<Action, Long> { + + @Query(""" + SELECT a + FROM Action a + WHERE a.event = :event + ORDER BY a.sequence DESC + LIMIT 1 + """) + Optional<Action> findLastByEvent(@Param("event") Event event); + + Optional<Action> findByIdAndEvent(Long id, Event event); +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java new file mode 100644 index 000000000..943b40ce5 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillAction.java @@ -0,0 +1,156 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class BillAction implements Comparable<BillAction> { + + public static final int MIN_TITLE_LENGTH = 1; + public static final int MAX_TITLE_LENGTH = 30; + public static final long MIN_PRICE = 1L; + public static final long MAX_PRICE = 10_000_000L; + private static final long DEFAULT_PRICE = 0L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + private Action action; + + @Column(length = MAX_TITLE_LENGTH) + private String title; + + private Long price; + + @OneToMany(mappedBy = "billAction", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + private List<BillActionDetail> billActionDetails = new ArrayList<>(); + + public BillAction(Action action, String title, Long price) { + validateTitle(title); + validatePrice(price); + this.action = action; + this.title = title.trim(); + this.price = price; + } + + private void validateTitle(String title) { + int titleLength = title.trim().length(); + if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_TITLE_INVALID); + } + } + + private void validatePrice(Long price) { + if (price < MIN_PRICE || price > MAX_PRICE) { + throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_PRICE_INVALID); + } + } + + public static BillAction create(Action action, String title, Long price, CurrentMembers currentMembers) { + BillAction billAction = new BillAction(action, title, price); + billAction.resetBillActionDetails(currentMembers); + return billAction; + } + + public void resetBillActionDetails(CurrentMembers currentMembers) { + this.billActionDetails.clear(); + Iterator<Long> priceIterator = distributePrice(currentMembers.size()).iterator(); + + for (String member : currentMembers.getMembers()) { + BillActionDetail billActionDetail = new BillActionDetail(this, member, priceIterator.next(), false); + this.billActionDetails.add(billActionDetail); + } + } + + private void resetBillActionDetails() { + Iterator<Long> priceIterator = distributePrice(billActionDetails.size()).iterator(); + + billActionDetails.forEach(billActionDetail -> { + billActionDetail.updatePrice(priceIterator.next()); + billActionDetail.updateIsFixed(false); + }); + } + + private List<Long> distributePrice(int memberCount) { + if (memberCount == 0) { + return new ArrayList<>(); + } + long eachPrice = price / memberCount; + long remainder = price % memberCount; + + List<Long> results = Stream.generate(() -> eachPrice) + .limit(memberCount - 1) + .collect(Collectors.toList()); + results.add(eachPrice + remainder); + return results; + } + + public void update(String title, Long price) { + validateTitle(title); + validatePrice(price); + this.title = title.trim(); + this.price = price; + resetBillActionDetails(); + } + + public void addDetails(List<BillActionDetail> billActionDetails) { + billActionDetails.forEach(this::addDetail); + } + + private void addDetail(BillActionDetail billActionDetail) { + this.billActionDetails.add(billActionDetail); + billActionDetail.setBillAction(this); + } + + public boolean isFixed() { + return billActionDetails.stream() + .anyMatch(BillActionDetail::isFixed); + } + + public boolean isSamePrice(Long price) { + return this.price.equals(price); + } + + public Long findPriceByMemberName(String memberName) { + return billActionDetails.stream() + .filter(billActionDetail -> billActionDetail.hasMemberName(memberName)) + .map(BillActionDetail::getPrice) + .findFirst() + .orElse(DEFAULT_PRICE); + } + + public Long getSequence() { + return action.getSequence(); + } + + public Event getEvent() { + return action.getEvent(); + } + + @Override + public int compareTo(BillAction o) { + return Long.compare(this.getSequence(), o.getSequence()); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java new file mode 100644 index 000000000..ad13e6ab2 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java @@ -0,0 +1,57 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class BillActionDetail { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private BillAction billAction; + + private String memberName; + + private Long price; + + private boolean isFixed; + + public BillActionDetail(BillAction billAction, String memberName, Long price, boolean isFixed) { + this.billAction = billAction; + this.memberName = memberName; + this.price = price; + this.isFixed = isFixed; + } + + public void updatePrice(Long price) { + this.price = price; + } + + public void updateIsFixed(boolean isFixed) { + this.isFixed = isFixed; + } + + public boolean hasMemberName(String memberName) { + return this.memberName.equals(memberName); + } + + public boolean isSameName(String memberName) { + return this.memberName.equals(memberName); + } + + public void setBillAction(BillAction billAction) { + this.billAction = billAction; + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java new file mode 100644 index 000000000..d1d7cfe0f --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java @@ -0,0 +1,17 @@ +package server.haengdong.domain.action; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface BillActionDetailRepository extends JpaRepository<BillActionDetail, Long> { + + @Query(""" + select bd + from BillActionDetail bd + where bd.billAction = :billAction + """) + List<BillActionDetail> findAllByBillAction(BillAction billAction); +} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java new file mode 100644 index 000000000..817a63bf8 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java @@ -0,0 +1,27 @@ +package server.haengdong.domain.action; + +import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface BillActionRepository extends JpaRepository<BillAction, Long> { + + @EntityGraph(attributePaths = {"action"}) + List<BillAction> findByAction_Event(Event event); + + void deleteByAction_EventAndActionId(Event event, Long actionId); + + Optional<BillAction> findByAction_Id(Long actionId); + + @Query(""" + select ba + from BillAction ba + where ba.action.event = :event and ba.action.sequence > :sequence + """) + List<BillAction> findByEventAndGreaterThanSequence(Event event, Long sequence); +} diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java new file mode 100644 index 000000000..ba380aae5 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java @@ -0,0 +1,81 @@ +package server.haengdong.domain.action; + +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +public class CurrentMembers { + + private final Set<String> members; + + public CurrentMembers() { + this(new HashSet<>()); + } + + protected CurrentMembers(Set<String> members) { + this.members = members; + } + + public static CurrentMembers of(List<MemberAction> memberActions) { + List<MemberAction> sortedMemberActions = getSortedMemberActions(memberActions); + Set<String> members = new HashSet<>(); + for (MemberAction memberAction : sortedMemberActions) { + String member = memberAction.getMemberName(); + if (memberAction.isSameStatus(MemberActionStatus.IN)) { + members.add(member); + continue; + } + members.remove(member); + } + + return new CurrentMembers(members); + } + + private static List<MemberAction> getSortedMemberActions(List<MemberAction> memberActions) { + return memberActions.stream() + .sorted(Comparator.comparing(MemberAction::getSequence)) + .toList(); + } + + public CurrentMembers addMemberAction(MemberAction memberAction) { + String memberName = memberAction.getMemberName(); + + Set<String> currentMembers = new HashSet<>(members); + + if (memberAction.isIn()) { + currentMembers.add(memberName); + } else { + currentMembers.remove(memberName); + } + return new CurrentMembers(currentMembers); + } + + public void validate(String memberName, MemberActionStatus memberActionStatus) { + if (memberActionStatus == MemberActionStatus.IN && members.contains(memberName)) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_ALREADY_EXIST); + } + if (memberActionStatus == MemberActionStatus.OUT && !members.contains(memberName)) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NOT_EXIST); + } + } + + public boolean isEmpty() { + return members.isEmpty(); + } + + public boolean isNotEmpty() { + return !members.isEmpty(); + } + + public int size() { + return members.size(); + } + + public Set<String> getMembers() { + return Collections.unmodifiableSet(members); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java new file mode 100644 index 000000000..3faf65bde --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberAction.java @@ -0,0 +1,76 @@ +package server.haengdong.domain.action; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class MemberAction implements Comparable<MemberAction> { + + public static final int MIN_NAME_LENGTH = 1; + public static final int MAX_NAME_LENGTH = 4; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + private Action action; + + private String memberName; + + @Enumerated(EnumType.STRING) + private MemberActionStatus status; + + private Long memberGroupId; + + public MemberAction(Action action, String memberName, MemberActionStatus status, Long memberGroupId) { + validateMemberName(memberName); + this.action = action; + this.memberName = memberName; + this.status = status; + this.memberGroupId = memberGroupId; + } + + private void validateMemberName(String memberName) { + int memberLength = memberName.length(); + if (memberLength < MIN_NAME_LENGTH || memberLength > MAX_NAME_LENGTH) { + throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_LENGTH_INVALID); + } + } + + public void updateMemberName(String memberName) { + validateMemberName(memberName); + this.memberName = memberName; + } + + public boolean isIn() { + return status == MemberActionStatus.IN; + } + + public boolean isSameStatus(MemberActionStatus memberActionStatus) { + return status == memberActionStatus; + } + + public Long getSequence() { + return action.getSequence(); + } + + @Override + public int compareTo(MemberAction o) { + return Long.compare(this.getSequence(), o.getSequence()); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java new file mode 100644 index 000000000..324ff9797 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java @@ -0,0 +1,53 @@ +package server.haengdong.domain.action; + +import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; + +@Repository +public interface MemberActionRepository extends JpaRepository<MemberAction, Long> { + + @Query("select m from MemberAction m join fetch m.action where m.action.event = :event") + List<MemberAction> findAllByEvent(@Param("event") Event event); + + @Query(""" + select distinct m.memberName + from MemberAction m + where m.action.event = :event + """) + List<String> findAllUniqueMemberByEvent(Event event); + + @Modifying + @Query(""" + delete + from MemberAction m + where m.memberName = :memberName and m.action.event = :event + """) + void deleteAllByEventAndMemberName(Event event, String memberName); + + Optional<MemberAction> findByAction(Action action); + + @Modifying + @Query(""" + delete + from MemberAction m + where m.memberName = :memberName and m.action.sequence >= :sequence + """) + void deleteAllByMemberNameAndMinSequence(String memberName, Long sequence); + + List<MemberAction> findAllByAction_EventAndMemberName(Event event, String memberName); + + boolean existsByAction_EventAndMemberName(Event event, String updatedMemberName); + + @Query(""" + select ma + from MemberAction ma + where ma.action.event = :event and ma.action.sequence < :sequence + """) + List<MemberAction> findByEventAndSequence(Event event, Long sequence); +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java new file mode 100644 index 000000000..76c5a66d4 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java @@ -0,0 +1,19 @@ +package server.haengdong.domain.action; + +import java.util.Arrays; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +public enum MemberActionStatus { + IN, + OUT, + ; + + public static MemberActionStatus of(String status) { + return Arrays.stream(MemberActionStatus.values()) + .filter(s -> s.name().equals(status)) + .findFirst() + .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.MEMBER_ACTION_STATUS_INVALID, + String.format(HaengdongErrorCode.MEMBER_ACTION_STATUS_INVALID.getMessage(), status))); + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java new file mode 100644 index 000000000..7a707b9d8 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java @@ -0,0 +1,75 @@ +package server.haengdong.domain.action; + +import static java.util.stream.Collectors.toMap; + +import java.util.List; +import java.util.Map; +import java.util.PriorityQueue; +import java.util.function.Function; +import lombok.Getter; + +@Getter +public class MemberBillReport { + + private final Map<String, Long> reports; + + private MemberBillReport(Map<String, Long> reports) { + this.reports = reports; + } + + public static MemberBillReport createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { + PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); + PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); + + Map<String, Long> memberBillReports = initReports(memberActions); + CurrentMembers currentMembers = new CurrentMembers(); + while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { + if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { + MemberAction memberAction = sortedMemberActions.poll(); + currentMembers = currentMembers.addMemberAction(memberAction); + continue; + } + addBillAction(sortedBillActions, currentMembers, memberBillReports); + } + + while (!sortedBillActions.isEmpty()) { + addBillAction(sortedBillActions, currentMembers, memberBillReports); + } + + return new MemberBillReport(memberBillReports); + } + + private static Map<String, Long> initReports(List<MemberAction> memberActions) { + return memberActions.stream() + .map(MemberAction::getMemberName) + .distinct() + .collect(toMap(Function.identity(), i -> 0L)); + } + + private static boolean isMemberActionTurn( + PriorityQueue<MemberAction> memberActions, + PriorityQueue<BillAction> billActions + ) { + MemberAction memberAction = memberActions.peek(); + BillAction billAction = billActions.peek(); + + return memberAction.getSequence() < billAction.getSequence(); + } + + private static void addBillAction( + PriorityQueue<BillAction> sortedBillActions, + CurrentMembers currentMembers, + Map<String, Long> memberBillReports + ) { + BillAction billAction = sortedBillActions.poll(); + if (currentMembers.isEmpty()) { + return; + } + + for (String currentMember : currentMembers.getMembers()) { + Long currentPrice = billAction.findPriceByMemberName(currentMember); + Long price = memberBillReports.get(currentMember) + currentPrice; + memberBillReports.put(currentMember, price); + } + } +} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java new file mode 100644 index 000000000..9e32bd733 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java @@ -0,0 +1,11 @@ +package server.haengdong.domain.action; + +import org.springframework.stereotype.Component; + +@Component +public class MemberGroupIdProvider { + + public Long createGroupId() { + return System.currentTimeMillis(); + } +} diff --git a/server/src/main/java/server/haengdong/domain/event/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java new file mode 100644 index 000000000..bb5d53dbc --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/Event.java @@ -0,0 +1,70 @@ +package server.haengdong.domain.event; + +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.Column; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class Event { + + public static final int MIN_NAME_LENGTH = 1; + public static final int MAX_NAME_LENGTH = 20; + private static final String SPACES = " "; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String name; + + @Embedded + @AttributeOverride(name = "value", column = @Column(name = "password")) + private Password password; + + private String token; + + public Event(String name, String password, String token) { + validateName(name); + this.name = name; + this.password = new Password(password); + this.token = token; + } + + private void validateName(String name) { + int nameLength = name.trim().length(); + if (nameLength < MIN_NAME_LENGTH || MAX_NAME_LENGTH < nameLength) { + throw new HaengdongException(HaengdongErrorCode.EVENT_NAME_LENGTH_INVALID, + String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", + MIN_NAME_LENGTH, + MAX_NAME_LENGTH, + name.length())); + } + if (isBlankContinuous(name)) { + throw new HaengdongException(HaengdongErrorCode.EVENT_NAME_CONSECUTIVE_SPACES, + String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", name)); + } + } + + private boolean isBlankContinuous(String name) { + return name.contains(SPACES); + } + + public boolean isTokenMismatch(String token) { + return !this.token.equals(token); + } + + public boolean isPasswordMismatch(String rawPassword) { + return !password.matches(rawPassword); + } +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java new file mode 100644 index 000000000..09526125e --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventRepository.java @@ -0,0 +1,11 @@ +package server.haengdong.domain.event; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EventRepository extends JpaRepository<Event, Long> { + + Optional<Event> findByToken(String token); +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventStep.java b/server/src/main/java/server/haengdong/domain/event/EventStep.java new file mode 100644 index 000000000..297abdb66 --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventStep.java @@ -0,0 +1,28 @@ +package server.haengdong.domain.event; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +public class EventStep { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Event event; + + private String name; + + private Long sequence; +} diff --git a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java new file mode 100644 index 000000000..6450f0dcf --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java @@ -0,0 +1,12 @@ +package server.haengdong.domain.event; + +import java.util.UUID; +import org.springframework.stereotype.Component; + +@Component +public class EventTokenProvider { + + public String createToken() { + return UUID.randomUUID().toString(); + } +} diff --git a/server/src/main/java/server/haengdong/domain/event/Password.java b/server/src/main/java/server/haengdong/domain/event/Password.java new file mode 100644 index 000000000..375849dbf --- /dev/null +++ b/server/src/main/java/server/haengdong/domain/event/Password.java @@ -0,0 +1,52 @@ +package server.haengdong.domain.event; + +import jakarta.persistence.Embeddable; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; + +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Embeddable +public class Password { + + public static final int PASSWORD_LENGTH = 4; + private static final Pattern PASSWORD_PATTERN = Pattern.compile(String.format("^\\d{%d}$", PASSWORD_LENGTH)); + private static final String HASH_ALGORITHM = "SHA-256"; + + private String value; + + public Password(String password) { + validatePassword(password); + this.value = encode(password); + } + + private void validatePassword(String password) { + Matcher matcher = PASSWORD_PATTERN.matcher(password); + if (!matcher.matches()) { + throw new HaengdongException(HaengdongErrorCode.EVENT_PASSWORD_FORMAT_INVALID); + } + } + + private String encode(String rawPassword) { + try { + MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM); + byte[] hashedPassword = digest.digest(rawPassword.getBytes()); + return Base64.getEncoder().encodeToString(hashedPassword); + } catch (NoSuchAlgorithmException e) { + throw new IllegalArgumentException("해시 알고리즘이 존재하지 않습니다."); + } + } + + public boolean matches(String rawPassword) { + String hashedPassword = encode(rawPassword); + return value.equals(hashedPassword); + } +} diff --git a/server/src/main/java/server/haengdong/exception/AuthenticationException.java b/server/src/main/java/server/haengdong/exception/AuthenticationException.java new file mode 100644 index 000000000..2efcb16e7 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/AuthenticationException.java @@ -0,0 +1,19 @@ +package server.haengdong.exception; + +import lombok.Getter; + +@Getter +public class AuthenticationException extends RuntimeException { + + private final HaengdongErrorCode errorCode; + private final String message; + + public AuthenticationException(HaengdongErrorCode errorCode) { + this(errorCode, errorCode.getMessage()); + } + + public AuthenticationException(HaengdongErrorCode errorCode, String message) { + this.errorCode = errorCode; + this.message = message; + } +} diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java new file mode 100644 index 000000000..d0a2b01a0 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/ErrorResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.exception; + +public record ErrorResponse( + HaengdongErrorCode errorCode, + String message +) { + + public static ErrorResponse of(HaengdongErrorCode errorCode) { + return new ErrorResponse(errorCode, errorCode.getMessage()); + } + + public static ErrorResponse of(HaengdongErrorCode errorCode, String message) { + return new ErrorResponse(errorCode, message); + } +} diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java new file mode 100644 index 000000000..0cee7cb4c --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java @@ -0,0 +1,90 @@ +package server.haengdong.exception; + +import jakarta.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.IOException; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.resource.NoResourceFoundException; + +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler { + + private static final String LOG_FORMAT = """ + \n\t{ + "RequestURI": "{} {}", + "RequestBody": {}, + "ErrorMessage": "{}" + \t} + """; + + @ExceptionHandler(AuthenticationException.class) + public ResponseEntity<ErrorResponse> authenticationException(HttpServletRequest req, AuthenticationException e) { + log.warn(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(ErrorResponse.of(e.getErrorCode())); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ResponseEntity<ErrorResponse> noResourceException(HttpRequestMethodNotSupportedException e) { + log.warn(e.getMessage(), e); + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.REQUEST_METHOD_NOT_SUPPORTED)); + } + + @ExceptionHandler(NoResourceFoundException.class) + public ResponseEntity<ErrorResponse> noResourceException(NoResourceFoundException e) { + log.warn(e.getMessage(), e); + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.NO_RESOURCE_REQUEST)); + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + public ResponseEntity<ErrorResponse> httpMessageNotReadableException(HttpMessageNotReadableException e) { + log.warn(e.getMessage(), e); + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.MESSAGE_NOT_READABLE)); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + log.warn(e.getMessage(), e); + String errorMessage = e.getFieldErrors().stream() + .map(error -> error.getField() + " " + error.getDefaultMessage()) + .collect(Collectors.joining(", ")); + + return ResponseEntity.badRequest() + .body(ErrorResponse.of(HaengdongErrorCode.REQUEST_EMPTY, errorMessage)); + } + + @ExceptionHandler(HaengdongException.class) + public ResponseEntity<ErrorResponse> haengdongException(HttpServletRequest req, HaengdongException e) { + log.warn(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); + return ResponseEntity.badRequest() + .body(ErrorResponse.of(e.getErrorCode())); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity<ErrorResponse> handleException(HttpServletRequest req, Exception e) { + log.error(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); + return ResponseEntity.internalServerError() + .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR)); + } + + private String getRequestBody(HttpServletRequest req) { + try (BufferedReader reader = req.getReader()) { + return reader.lines().collect(Collectors.joining(System.lineSeparator() + "\t")); + } catch (IOException e) { + log.error("Failed to read request body", e); + return ""; + } + } +} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java new file mode 100644 index 000000000..475d16c11 --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java @@ -0,0 +1,69 @@ +package server.haengdong.exception; + +import lombok.Getter; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.Password; + +@Getter +public enum HaengdongErrorCode { + + /* Domain */ + + EVENT_NOT_FOUND("존재하지 않는 행사입니다."), + EVENT_NAME_LENGTH_INVALID(String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다.", + Event.MIN_NAME_LENGTH, + Event.MAX_NAME_LENGTH)), + EVENT_NAME_CONSECUTIVE_SPACES("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s"), + EVENT_PASSWORD_FORMAT_INVALID(String.format("비밀번호는 %d자리 숫자만 가능합니다.", Password.PASSWORD_LENGTH)), + + ACTION_NOT_FOUND("존재하지 않는 액션입니다."), + + MEMBER_NAME_LENGTH_INVALID(String.format("멤버 이름은 %d자 이상 %d자 이하만 입력 가능합니다.", + MemberAction.MIN_NAME_LENGTH, + MemberAction.MAX_NAME_LENGTH)), + MEMBER_NAME_DUPLICATE("중복된 행사 참여 인원 이름이 존재합니다."), + MEMBER_NOT_EXIST("현재 참여하고 있지 않는 인원이 존재합니다."), + MEMBER_ALREADY_EXIST("현재 참여하고 있는 인원이 존재합니다."), + MEMBER_NAME_CHANGE_DUPLICATE("중복된 참여 인원 이름 변경 요청이 존재합니다."), + + MEMBER_ACTION_NOT_FOUND("존재하지 않는 멤버 액션입니다."), + MEMBER_ACTION_STATUS_INVALID("멤버 액션은 IN, OUT만 가능합니다. 입력한 멤버 액션: %s"), + + BILL_ACTION_NOT_FOUND("존재하지 않는 지출 액션입니다."), + BILL_ACTION_TITLE_INVALID(String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", + BillAction.MIN_TITLE_LENGTH, + BillAction.MAX_TITLE_LENGTH)), + BILL_ACTION_PRICE_INVALID(String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", BillAction.MAX_PRICE)), + BILL_ACTION_DETAIL_NOT_FOUND("존재하지 않는 참여자 지출입니다."), + BILL_ACTION_PRICE_NOT_MATCHED("지출 총액이 일치하지 않습니다."), + + /* Authentication */ + + PASSWORD_INVALID("비밀번호가 일치하지 않습니다."), + + TOKEN_NOT_FOUND("토큰이 존재하지 않습니다."), + TOKEN_EXPIRED("만료된 토큰입니다."), + TOKEN_INVALID("유효하지 않은 토큰입니다."), + + FORBIDDEN("접근할 수 없는 행사입니다."), + + /* Request Validation */ + + REQUEST_EMPTY("입력 값은 공백일 수 없습니다.") + + /* System */, + + MESSAGE_NOT_READABLE("읽을 수 없는 요청입니다."), + REQUEST_METHOD_NOT_SUPPORTED("지원하지 않는 요청 메서드입니다."), + NO_RESOURCE_REQUEST("존재하지 않는 자원입니다."), + INTERNAL_SERVER_ERROR("서버 내부에서 에러가 발생했습니다."), + ; + + private final String message; + + HaengdongErrorCode(String message) { + this.message = message; + } +} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongException.java b/server/src/main/java/server/haengdong/exception/HaengdongException.java new file mode 100644 index 000000000..b86fe4ffc --- /dev/null +++ b/server/src/main/java/server/haengdong/exception/HaengdongException.java @@ -0,0 +1,19 @@ +package server.haengdong.exception; + +import lombok.Getter; + +@Getter +public class HaengdongException extends RuntimeException { + + private final HaengdongErrorCode errorCode; + private final String message; + + public HaengdongException(HaengdongErrorCode errorCode) { + this(errorCode, errorCode.getMessage()); + } + + public HaengdongException(HaengdongErrorCode errorCode, String message) { + this.errorCode = errorCode; + this.message = message; + } +} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java b/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java new file mode 100644 index 000000000..4972de48a --- /dev/null +++ b/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java @@ -0,0 +1,23 @@ +package server.haengdong.infrastructure.auth; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import java.util.Arrays; +import server.haengdong.exception.AuthenticationException; +import server.haengdong.exception.HaengdongErrorCode; + +public class AuthenticationExtractor { + + public String extract(HttpServletRequest request, String cookieName) { + Cookie[] cookies = request.getCookies(); + if (cookies == null) { + throw new AuthenticationException(HaengdongErrorCode.TOKEN_NOT_FOUND); + } + + return Arrays.stream(cookies) + .filter(cookie -> cookieName.equals(cookie.getName())) + .findFirst() + .orElseThrow(() -> new AuthenticationException(HaengdongErrorCode.TOKEN_NOT_FOUND)) + .getValue(); + } +} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java b/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java new file mode 100644 index 000000000..18f867601 --- /dev/null +++ b/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java @@ -0,0 +1,15 @@ +package server.haengdong.infrastructure.auth; + +import java.time.Duration; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("cookie") +public record CookieProperties( + boolean httpOnly, + boolean secure, + String domain, + String path, + String sameSite, + Duration maxAge +) { +} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java b/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java new file mode 100644 index 000000000..df9ec6a81 --- /dev/null +++ b/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java @@ -0,0 +1,54 @@ +package server.haengdong.infrastructure.auth; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import server.haengdong.domain.TokenProvider; + +public class JwtTokenProvider implements TokenProvider { + + private final TokenProperties tokenProperties; + + public JwtTokenProvider(TokenProperties tokenProperties) { + this.tokenProperties = tokenProperties; + } + + @Override + public String createToken(Map<String, Object> payload) { + Claims claims = Jwts.claims(new HashMap<>(payload)); + Date now = new Date(); + Date validity = new Date(now.getTime() + tokenProperties.expireLength()); + + return Jwts.builder() + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(validity) + .signWith(SignatureAlgorithm.HS256, tokenProperties.secretKey()) + .compact(); + } + + @Override + public Map<String, Object> getPayload(String token) { + return Jwts.parser() + .setSigningKey(tokenProperties.secretKey()) + .parseClaimsJws(token) + .getBody(); + } + + @Override + public boolean validateToken(String token) { + try { + Jws<Claims> claims = Jwts.parser().setSigningKey(tokenProperties.secretKey()).parseClaimsJws(token); + + return !claims.getBody().getExpiration().before(new Date()); + } catch (JwtException | IllegalArgumentException e) { + return false; + } + } +} + diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java b/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java new file mode 100644 index 000000000..11dedcdbf --- /dev/null +++ b/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java @@ -0,0 +1,7 @@ +package server.haengdong.infrastructure.auth; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties("security.jwt.token") +public record TokenProperties(String secretKey, Long expireLength) { +} diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java new file mode 100644 index 000000000..657cb567e --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/ActionController.java @@ -0,0 +1,26 @@ +package server.haengdong.presentation; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.ActionService; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.presentation.response.MemberBillReportsResponse; + +@RequiredArgsConstructor +@RestController +public class ActionController { + + private final ActionService actionService; + + @GetMapping("/api/events/{eventId}/actions/reports") + public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("eventId") String token) { + List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); + + return ResponseEntity.ok() + .body(MemberBillReportsResponse.of(memberBillReports)); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java new file mode 100644 index 000000000..56e99337d --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/BillActionController.java @@ -0,0 +1,55 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.BillActionService; +import server.haengdong.presentation.request.BillActionUpdateRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +@RequiredArgsConstructor +@RestController +public class BillActionController { + + private final BillActionService billActionService; + + @PostMapping("/api/events/{eventId}/bill-actions") + public ResponseEntity<Void> saveAllBillAction( + @PathVariable("eventId") String token, + @Valid @RequestBody BillActionsSaveRequest request + ) { + billActionService.saveAllBillAction(token, request.toAppRequests()); + + return ResponseEntity.ok() + .build(); + } + + @PutMapping("/api/events/{eventId}/bill-actions/{actionId}") + public ResponseEntity<Void> updateBillAction( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId, + @Valid @RequestBody BillActionUpdateRequest request + ) { + billActionService.updateBillAction(token, actionId, request.toAppResponse()); + + return ResponseEntity.ok() + .build(); + } + + @DeleteMapping("/api/events/{eventId}/bill-actions/{actionId}") + public ResponseEntity<Void> deleteBillAction( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId + ) { + billActionService.deleteBillAction(token, actionId); + + return ResponseEntity.ok() + .build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java b/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java new file mode 100644 index 000000000..5602e6777 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java @@ -0,0 +1,42 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.BillActionDetailService; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; +import server.haengdong.presentation.response.BillActionDetailsResponse; + +@RequiredArgsConstructor +@RestController +public class BillActionDetailController { + + private final BillActionDetailService billActionDetailService; + + @GetMapping("/api/events/{eventId}/bill-actions/{actionId}/fixed") + public ResponseEntity<BillActionDetailsResponse> findBillActionDetails( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId + ) { + BillActionDetailsAppResponse appResponse = billActionDetailService.findBillActionDetails(token, actionId); + + return ResponseEntity.ok(BillActionDetailsResponse.of(appResponse)); + } + + @PutMapping("/api/events/{eventId}/bill-actions/{actionId}/fixed") + public ResponseEntity<Void> updateBillActionDetails( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId, + @Valid @RequestBody BillActionDetailsUpdateRequest request + ) { + billActionDetailService.updateBillActionDetails(token, actionId, request.toAppRequest()); + + return ResponseEntity.ok().build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java new file mode 100644 index 000000000..34261042f --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/EventController.java @@ -0,0 +1,120 @@ +package server.haengdong.presentation; + +import jakarta.validation.Valid; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseCookie; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.AuthService; +import server.haengdong.application.EventService; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.infrastructure.auth.CookieProperties; +import server.haengdong.presentation.request.EventLoginRequest; +import server.haengdong.presentation.request.EventSaveRequest; +import server.haengdong.presentation.request.MemberNamesUpdateRequest; +import server.haengdong.presentation.response.ActionsResponse; +import server.haengdong.presentation.response.EventDetailResponse; +import server.haengdong.presentation.response.EventResponse; +import server.haengdong.presentation.response.MembersResponse; +import server.haengdong.presentation.response.StepsResponse; + +@Slf4j +@RequiredArgsConstructor +@EnableConfigurationProperties(CookieProperties.class) +@RestController +public class EventController { + + private final EventService eventService; + private final AuthService authService; + private final CookieProperties cookieProperties; + + @PostMapping("/api/events") + public ResponseEntity<EventResponse> saveEvent(@Valid @RequestBody EventSaveRequest request) { + EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); + + String jwtToken = authService.createToken(eventResponse.eventId()); + + ResponseCookie responseCookie = createResponseCookie(jwtToken); + return ResponseEntity.ok() + .header(HttpHeaders.SET_COOKIE, responseCookie.toString()) + .body(eventResponse); + } + + @GetMapping("/api/events/{eventId}") + public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") String token) { + EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); + + return ResponseEntity.ok(eventDetailResponse); + } + + @GetMapping("/api/events/{eventId}/actions") + public ResponseEntity<StepsResponse> findActions(@PathVariable("eventId") String token) { + StepsResponse stepsResponse = StepsResponse.of(eventService.findActions(token)); + + return ResponseEntity.ok(stepsResponse); + } + + @GetMapping("/api/events/{eventId}/actions/v2") + public ResponseEntity<ActionsResponse> findActions2(@PathVariable("eventId") String token) { + List<ActionAppResponse> actions = eventService.findActions(token); + ActionsResponse actionsResponse = ActionsResponse.of(actions); + + return ResponseEntity.ok(actionsResponse); + } + + @GetMapping("/api/events/{eventId}/members") + public ResponseEntity<MembersResponse> findAllMembers(@PathVariable("eventId") String token) { + MembersResponse response = MembersResponse.of(eventService.findAllMembers(token)); + + return ResponseEntity.ok(response); + } + + @PutMapping("/api/events/{eventId}/members/nameChange") + public ResponseEntity<Void> updateMember( + @PathVariable("eventId") String token, + @Valid @RequestBody MemberNamesUpdateRequest request + ) { + eventService.updateMember(token, request.toAppRequest()); + + return ResponseEntity.ok().build(); + } + + @PostMapping("/api/events/{eventId}/login") + public ResponseEntity<Void> loginEvent( + @PathVariable("eventId") String token, + @Valid @RequestBody EventLoginRequest request + ) { + eventService.validatePassword(request.toAppRequest(token)); + String jwtToken = authService.createToken(token); + + ResponseCookie responseCookie = createResponseCookie(jwtToken); + return ResponseEntity.ok() + .header(HttpHeaders.SET_COOKIE, responseCookie.toString()) + .build(); + } + + @PostMapping("/api/events/{eventId}/auth") + public ResponseEntity<Void> authenticate(@PathVariable("eventId") String token) { + return ResponseEntity.ok().build(); + } + + private ResponseCookie createResponseCookie(String token) { + return ResponseCookie.from(authService.getTokenName(), token) + .httpOnly(cookieProperties.httpOnly()) + .secure(cookieProperties.secure()) + .domain(cookieProperties.domain()) + .path(cookieProperties.path()) + .sameSite(cookieProperties.sameSite()) + .maxAge(cookieProperties.maxAge()) + .build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java new file mode 100644 index 000000000..1703245f7 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/MemberActionController.java @@ -0,0 +1,60 @@ +package server.haengdong.presentation; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import server.haengdong.application.MemberActionService; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.presentation.request.MemberActionsSaveRequest; +import server.haengdong.presentation.response.CurrentMembersResponse; + +@RequiredArgsConstructor +@RestController +public class MemberActionController { + + private final MemberActionService memberActionService; + + @PostMapping("/api/events/{eventId}/member-actions") + public ResponseEntity<Void> saveMemberAction( + @PathVariable("eventId") String token, + @RequestBody MemberActionsSaveRequest request + ) { + memberActionService.saveMemberAction(token, request.toAppRequest()); + + return ResponseEntity.ok().build(); + } + + @GetMapping("/api/events/{eventId}/members/current") + public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("eventId") String token) { + List<CurrentMemberAppResponse> currentMembers = memberActionService.getCurrentMembers(token); + + return ResponseEntity.ok() + .body(CurrentMembersResponse.of(currentMembers)); + } + + @DeleteMapping("/api/events/{eventId}/members/{memberName}") + public ResponseEntity<Void> deleteMember( + @PathVariable("eventId") String token, + @PathVariable("memberName") String memberName + ) { + memberActionService.deleteMember(token, memberName); + + return ResponseEntity.ok().build(); + } + + @DeleteMapping("/api/events/{eventId}/member-actions/{actionId}") + public ResponseEntity<Void> deleteMemberAction( + @PathVariable("eventId") String token, + @PathVariable("actionId") Long actionId + ) { + memberActionService.deleteMemberAction(token, actionId); + + return ResponseEntity.ok().build(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java new file mode 100644 index 000000000..21c4bd60f --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java @@ -0,0 +1,21 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import server.haengdong.application.request.BillActionDetailUpdateAppRequest; + +public record BillActionDetailUpdateRequest( + + @NotBlank(message = "맴버 이름은 공백일 수 없습니다.") + String name, + + @NotNull(message = "지출 금액은 공백일 수 없습니다.") + Long price, + + @NotNull(message = "지출 금액은 공백일 수 없습니다.") + boolean isFixed +) { + public BillActionDetailUpdateAppRequest toAppRequest() { + return new BillActionDetailUpdateAppRequest(this.name, this.price, this.isFixed); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java new file mode 100644 index 000000000..fafbb8fd7 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java @@ -0,0 +1,16 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; + +public record BillActionDetailsUpdateRequest( + @Valid @NotEmpty List<BillActionDetailUpdateRequest> members +) { + public BillActionDetailsUpdateAppRequest toAppRequest() { + return new BillActionDetailsUpdateAppRequest(members.stream() + .map(BillActionDetailUpdateRequest::toAppRequest) + .toList()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java new file mode 100644 index 000000000..a47ff8316 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java @@ -0,0 +1,19 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import server.haengdong.application.request.BillActionAppRequest; + +public record BillActionSaveRequest( + + @NotBlank(message = "지출 내역 제목은 공백일 수 없습니다.") + String title, + + @NotNull(message = "지출 금액은 공백일 수 없습니다.") + Long price +) { + + public BillActionAppRequest toAppRequest() { + return new BillActionAppRequest(title, price); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java new file mode 100644 index 000000000..680006816 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import server.haengdong.application.request.BillActionUpdateAppRequest; + +public record BillActionUpdateRequest( + + @NotBlank(message = "지출 내역 제목은 공백일 수 없습니다.") + String title, + + @NotNull(message = "지출 금액은 공백일 수 없습니다.") + Long price +) { + public BillActionUpdateAppRequest toAppResponse() { + return new BillActionUpdateAppRequest(title, price); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java new file mode 100644 index 000000000..6727d4cf1 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import server.haengdong.application.request.BillActionAppRequest; + +public record BillActionsSaveRequest( + + @Valid @NotEmpty List<BillActionSaveRequest> actions +) { + + public List<BillActionAppRequest> toAppRequests() { + return actions.stream() + .map(BillActionSaveRequest::toAppRequest) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java new file mode 100644 index 000000000..a1286e903 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java @@ -0,0 +1,14 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import server.haengdong.application.request.EventLoginAppRequest; + +public record EventLoginRequest( + + @NotBlank(message = "비밀번호는 공백일 수 없습니다.") + String password +) { + public EventLoginAppRequest toAppRequest(String token) { + return new EventLoginAppRequest(token, password); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java new file mode 100644 index 000000000..6bd7cd006 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import server.haengdong.application.request.EventAppRequest; + +public record EventSaveRequest( + + @NotBlank(message = "행사 이름은 공백일 수 없습니다.") + String eventName, + + @NotBlank(message = "비밀번호는 공백일 수 없습니다.") + String password +) { + + public EventAppRequest toAppRequest() { + return new EventAppRequest(eventName, password); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java new file mode 100644 index 000000000..41e95cc3c --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java @@ -0,0 +1,25 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; + +public record MemberActionsSaveRequest( + + @NotEmpty + List<String> members, + + @NotBlank(message = "멤버 액션은 공백일 수 없습니다.") + String status +) { + + public MemberActionsSaveAppRequest toAppRequest() { + List<MemberActionSaveAppRequest> appRequests = members.stream() + .map(name -> new MemberActionSaveAppRequest(name, status)) + .toList(); + + return new MemberActionsSaveAppRequest(appRequests); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java new file mode 100644 index 000000000..3cd2294ca --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.constraints.NotBlank; +import server.haengdong.application.request.MemberNameUpdateAppRequest; + +public record MemberNameUpdateRequest( + + @NotBlank(message = "멤버 이름은 공백일 수 없습니다.") + String before, + + @NotBlank(message = "멤버 이름은 공백일 수 없습니다.") + String after +) { + + public MemberNameUpdateAppRequest toAppRequest() { + return new MemberNameUpdateAppRequest(before, after); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java new file mode 100644 index 000000000..872aa55de --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java @@ -0,0 +1,17 @@ +package server.haengdong.presentation.request; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import java.util.List; +import server.haengdong.application.request.MemberNamesUpdateAppRequest; + +public record MemberNamesUpdateRequest( + @Valid @NotEmpty List<MemberNameUpdateRequest> members +) { + + public MemberNamesUpdateAppRequest toAppRequest() { + return new MemberNamesUpdateAppRequest(members.stream() + .map(MemberNameUpdateRequest::toAppRequest) + .toList()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java new file mode 100644 index 000000000..ea26ea769 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java @@ -0,0 +1,26 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.ActionAppResponse; + +public record ActionResponse( + Long actionId, + String name, + Long price, + Long sequence, + boolean isFixed +) { + + public ActionResponse(Long actionId, String name, Long price, Long sequence) { + this(actionId, name, price, sequence, false); + } + + public static ActionResponse of(ActionAppResponse actionAppResponse) { + return new ActionResponse( + actionAppResponse.actionId(), + actionAppResponse.name(), + actionAppResponse.price(), + actionAppResponse.sequence(), + actionAppResponse.isFixed() + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java new file mode 100644 index 000000000..ea46c5bd9 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java @@ -0,0 +1,22 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.ActionAppResponse; + +public record ActionResponse2( + Long actionId, + String name, + Long price, + Long sequence, + String type +) { + + public static ActionResponse2 of(ActionAppResponse actionAppResponse) { + return new ActionResponse2( + actionAppResponse.actionId(), + actionAppResponse.name(), + actionAppResponse.price(), + actionAppResponse.sequence(), + actionAppResponse.actionType().name() + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java new file mode 100644 index 000000000..c8ae780e3 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java @@ -0,0 +1,14 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.ActionAppResponse; + +public record ActionsResponse( + List<ActionResponse2> actions +) { + public static ActionsResponse of(List<ActionAppResponse> actions) { + return new ActionsResponse(actions.stream() + .map(ActionResponse2::of) + .toList()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java new file mode 100644 index 000000000..10f71b82e --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java @@ -0,0 +1,18 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.BillActionDetailAppResponse; + +public record BillActionDetailResponse( + String name, + Long price, + boolean isFixed +) { + + public static BillActionDetailResponse of(BillActionDetailAppResponse billActionDetailAppResponse) { + return new BillActionDetailResponse( + billActionDetailAppResponse.name(), + billActionDetailAppResponse.price(), + billActionDetailAppResponse.isFixed() + ); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java new file mode 100644 index 000000000..182e76db6 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java @@ -0,0 +1,16 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import java.util.stream.Collectors; +import server.haengdong.application.response.BillActionDetailsAppResponse; + +public record BillActionDetailsResponse( + List<BillActionDetailResponse> members +) { + + public static BillActionDetailsResponse of(BillActionDetailsAppResponse billActionDetailsAppResponse) { + return billActionDetailsAppResponse.billActionDetailAppResponses().stream() + .map(BillActionDetailResponse::of) + .collect(Collectors.collectingAndThen(Collectors.toList(), BillActionDetailsResponse::new)); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java new file mode 100644 index 000000000..289cca4fa --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.CurrentMemberAppResponse; + +public record CurrentMembersResponse(List<String> memberNames) { + + public static CurrentMembersResponse of(List<CurrentMemberAppResponse> currentMembers) { + List<String> responses = currentMembers.stream() + .map(CurrentMemberAppResponse::name) + .toList(); + + return new CurrentMembersResponse(responses); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java new file mode 100644 index 000000000..c18694393 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.EventDetailAppResponse; + +public record EventDetailResponse(String eventName) { + + public static EventDetailResponse of(EventDetailAppResponse response) { + return new EventDetailResponse(response.eventName()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java new file mode 100644 index 000000000..506f5e814 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.EventAppResponse; + +public record EventResponse(String eventId) { + + public static EventResponse of(EventAppResponse eventAppResponse) { + return new EventResponse(eventAppResponse.token()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java new file mode 100644 index 000000000..0ea409202 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java @@ -0,0 +1,10 @@ +package server.haengdong.presentation.response; + +import server.haengdong.application.response.MemberBillReportAppResponse; + +public record MemberBillReportResponse(String name, Long price) { + + public static MemberBillReportResponse of(MemberBillReportAppResponse memberBillReportAppResponse) { + return new MemberBillReportResponse(memberBillReportAppResponse.name(), memberBillReportAppResponse.price()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java new file mode 100644 index 000000000..d350c4009 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java @@ -0,0 +1,15 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.MemberBillReportAppResponse; + +public record MemberBillReportsResponse(List<MemberBillReportResponse> reports) { + + public static MemberBillReportsResponse of(List<MemberBillReportAppResponse> memberBillReports) { + List<MemberBillReportResponse> reports = memberBillReports.stream() + .map(MemberBillReportResponse::of) + .toList(); + + return new MemberBillReportsResponse(reports); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java new file mode 100644 index 000000000..0947d9e02 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java @@ -0,0 +1,13 @@ +package server.haengdong.presentation.response; + +import java.util.List; +import server.haengdong.application.response.MembersAppResponse; + +public record MembersResponse( + List<String> memberNames +) { + + public static MembersResponse of(MembersAppResponse response) { + return new MembersResponse(response.memberNames()); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java new file mode 100644 index 000000000..55dd62c58 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java @@ -0,0 +1,27 @@ +package server.haengdong.presentation.response; + +import java.util.ArrayList; +import java.util.List; +import server.haengdong.application.response.ActionAppResponse; + +public record StepResponse( + String stepName, + String type, + List<String> members, + List<ActionResponse> actions +) { + public static StepResponse of(String stepName, List<String> members, List<ActionAppResponse> actions) { + return new StepResponse( + stepName, + actions.get(0).actionTypeName(), + new ArrayList<>(members), + toActionsResponse(actions) + ); + } + + private static List<ActionResponse> toActionsResponse(List<ActionAppResponse> actions) { + return actions.stream() + .map(ActionResponse::of) + .toList(); + } +} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java new file mode 100644 index 000000000..5f7573d67 --- /dev/null +++ b/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java @@ -0,0 +1,56 @@ +package server.haengdong.presentation.response; + +import java.util.ArrayList; +import java.util.List; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.ActionAppResponse.ActionType; + +public record StepsResponse(List<StepResponse> steps) { + + public static StepsResponse of(List<ActionAppResponse> actions) { + List<StepResponse> steps = new ArrayList<>(); + List<String> currentMembers = new ArrayList<>(); + List<List<ActionAppResponse>> groups = createGroups(actions); + + int billStepCount = 0; + for (List<ActionAppResponse> group : groups) { + changeCurrentMembers(group, currentMembers); + if (group.get(0).actionType() == ActionType.BILL) { + billStepCount++; + } + StepResponse stepResponse = StepResponse.of(billStepCount + "차", currentMembers, group); + steps.add(stepResponse); + } + return new StepsResponse(steps); + } + + private static List<List<ActionAppResponse>> createGroups(List<ActionAppResponse> actions) { + List<List<ActionAppResponse>> groups = new ArrayList<>(); + + for (ActionAppResponse action : actions) { + if (groups.isEmpty() || isActionTypeChange(action, groups)) { + groups.add(new ArrayList<>()); + } + groups.get(groups.size() - 1).add(action); + } + + return groups; + } + + private static boolean isActionTypeChange(ActionAppResponse action, List<List<ActionAppResponse>> groups) { + List<ActionAppResponse> currentGroup = groups.get(groups.size() - 1); + return currentGroup.get(0).actionType() != action.actionType(); + } + + private static void changeCurrentMembers(List<ActionAppResponse> group, List<String> currentMembers) { + for (ActionAppResponse action : group) { + if (action.actionType() == ActionType.IN) { + currentMembers.add(action.name()); + continue; + } + if (action.actionType() == ActionType.OUT) { + currentMembers.remove(action.name()); + } + } + } +} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml new file mode 100644 index 000000000..2ae503547 --- /dev/null +++ b/server/src/main/resources/application.yml @@ -0,0 +1,66 @@ +spring: + datasource: + driver-class-name: org.h2.Driver + url: jdbc:h2:mem:database + username: sa + password: + + h2: + console: + enabled: true + path: /h2-console + + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + format_sql: true + jdbc.time_zone: Asia/Seoul + show-sql: true + +cors: + max-age: 3600 + allowed-origins: http://localhost:3000, https://haengdong.pro, https://dev.haengdong.pro, https://app.haengdong.pro + +security: + jwt: + token: + secret-key: skdmeejEKJdkDjklDlkj123DKLJ3kDkeDkDKQMEOD1D90D8dE + expire-length: 604800000 # 1주일 + +cookie: + http-only: false + secure: false + path: / + same-site: none + max-age: 7D + +management: + endpoints: + web: + exposure: + include: health, metrics, logfile + +server: + servlet: + encoding: + charset: UTF-8 + enabled: true + force: true + +--- + +spring: + config: + import: classpath:config/application-prod.yml + activate: + on-profile: prod + +--- + +spring: + config: + import: classpath:config/application-dev.yml + activate: + on-profile: dev diff --git a/server/src/main/resources/config b/server/src/main/resources/config new file mode 160000 index 000000000..fa4270674 --- /dev/null +++ b/server/src/main/resources/config @@ -0,0 +1 @@ +Subproject commit fa42706743e6eb3f4fd8c34618614eff8ae94b3d diff --git a/server/src/main/resources/logback-spring.xml b/server/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..283b966a3 --- /dev/null +++ b/server/src/main/resources/logback-spring.xml @@ -0,0 +1,97 @@ +<configuration> + <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <!-- 콘솔에 로그 출력 형식 --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="ERROR-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>ERROR</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>logs/spring-boot-application-error.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>logs/spring-boot-application-error.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <encoder> + <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="WARN-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>WARN</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>logs/spring-boot-application-warn.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>logs/spring-boot-application-warn.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <encoder> + <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="INFO-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>INFO</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>logs/spring-boot-application-info.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>logs/spring-boot-application-info.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <encoder> + <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <appender name="DEBUG-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <filter class="ch.qos.logback.classic.filter.LevelFilter"> + <level>DEBUG</level> + <onMatch>ACCEPT</onMatch> + <onMismatch>DENY</onMismatch> + </filter> + <file>logs/spring-boot-application-debug.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>logs/spring-boot-application-debug.%d{yyyy-MM-dd}.log</fileNamePattern> + <maxHistory>30</maxHistory> + </rollingPolicy> + <encoder> + <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> + <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> + </encoder> + </appender> + + <springProfile name="default"> + <root level="INFO"> + <appender-ref ref="CONSOLE"/> + </root> + </springProfile> + + <springProfile name="dev"> + <root level="INFO"> + <appender-ref ref="ERROR-ROLLING"/> + <appender-ref ref="WARN-ROLLING"/> + <appender-ref ref="INFO-ROLLING"/> + <appender-ref ref="DEBUG-ROLLING"/> + </root> + </springProfile> + + <springProfile name="prod"> + <root level="ERROR"> + <appender-ref ref="ERROR-ROLLING"/> + </root> + </springProfile> +</configuration> diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java new file mode 100644 index 000000000..ee979b278 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/ActionServiceTest.java @@ -0,0 +1,91 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; +import static server.haengdong.support.fixture.Fixture.BILL_ACTION; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class ActionServiceTest extends ServiceTestSupport { + + @Autowired + private ActionService actionService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @DisplayName("참여자별 정산 현황을 조회한다.") + @Test + void getMemberBillReports() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(savedEvent, 1L), "소하", IN, 1L), + new MemberAction(new Action(savedEvent, 2L), "감자", IN, 1L), + new MemberAction(new Action(savedEvent, 3L), "쿠키", IN, 1L), + new MemberAction(new Action(savedEvent, 5L), "감자", OUT, 2L) + ); + List<BillAction> billActions = List.of( + new BillAction(new Action(savedEvent, 4L), "뽕족", 60_000L), + new BillAction(new Action(savedEvent, 7L), "인생네컷", 20_000L) + ); + billActions.get(0).addDetails( + List.of( + new BillActionDetail(BILL_ACTION, "소하", 10_000L, false), + new BillActionDetail(BILL_ACTION, "감자", 40_000L, true), + new BillActionDetail(BILL_ACTION, "쿠키", 10_000L, false) + ) + ); + billActions.get(1).addDetails( + List.of( + new BillActionDetail(BILL_ACTION, "소하", 5_000L, true), + new BillActionDetail(BILL_ACTION, "쿠키", 15_000L, true) + ) + ); + memberActionRepository.saveAll(memberActions); + billActionRepository.saveAll(billActions); + + List<MemberBillReportAppResponse> responses = actionService.getMemberBillReports(event.getToken()); + + assertThat(responses) + .hasSize(3) + .extracting(MemberBillReportAppResponse::name, MemberBillReportAppResponse::price) + .containsExactlyInAnyOrder( + tuple("감자", 40_000L), + tuple("쿠키", 25_000L), + tuple("소하", 15_000L) + ); + } + + @DisplayName("존재하지 않는 이벤트의 참여자별 정산 현황을 조회하는 경우 예외가 발생한다.") + @Test + void getMemberBillReports1() { + assertThatThrownBy(() -> actionService.getMemberBillReports("invalid token")) + .isInstanceOf(HaengdongException.class) + .hasMessage(HaengdongErrorCode.EVENT_NOT_FOUND.getMessage()); + } +} diff --git a/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java new file mode 100644 index 000000000..7074ce846 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java @@ -0,0 +1,111 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.tuple; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.request.BillActionDetailUpdateAppRequest; +import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; +import server.haengdong.application.response.BillActionDetailAppResponse; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionDetailRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class BillActionDetailServiceTest extends ServiceTestSupport { + + @Autowired + private BillActionDetailService billActionDetailService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private BillActionDetailRepository billActionDetailRepository; + + @DisplayName("참여자별 지출 금액을 조회한다.") + @Test + void findBillActionDetailsTest() { + Event event1 = Fixture.EVENT1; + eventRepository.save(event1); + Action action = new Action(event1, 1L); + BillAction billAction = new BillAction(action, "뽕족", 10000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 6000L, true); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 4000L, true); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); + + BillActionDetailsAppResponse response = billActionDetailService.findBillActionDetails( + event1.getToken(), action.getId()); + + assertThat(response.billActionDetailAppResponses()).hasSize(2) + .extracting(BillActionDetailAppResponse::name, BillActionDetailAppResponse::price) + .containsExactly( + tuple("토다리", 6000L), + tuple("쿠키", 4000L) + ); + } + + @DisplayName("지출 금액 수정 요청의 총합이 지출 금액과 일치하지 않으면 예외가 발생한다.") + @Test + void updateBillActionDetailsTest1() { + Event event1 = Fixture.EVENT1; + eventRepository.save(event1); + Action action = new Action(event1, 1L); + BillAction billAction = new BillAction(action, "뽕족", 10000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 5000L, false); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 5000L, false); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); + + BillActionDetailsUpdateAppRequest request = new BillActionDetailsUpdateAppRequest(List.of( + new BillActionDetailUpdateAppRequest("토다리", 3000L, true), + new BillActionDetailUpdateAppRequest("쿠키", 4000L, true) + )); + assertThatCode( + () -> billActionDetailService.updateBillActionDetails(event1.getToken(), action.getId(), request)) + .isInstanceOf(HaengdongException.class) + .hasMessage("지출 총액이 일치하지 않습니다."); + } + + @DisplayName("지출 고정 금액을 수정한다.") + @Test + void updateBillActionDetailsTest2() { + Event event1 = Fixture.EVENT1; + eventRepository.save(event1); + Action action = new Action(event1, 1L); + BillAction billAction = new BillAction(action, "뽕족", 10000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 5000L, false); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 5000L, false); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); + + BillActionDetailsUpdateAppRequest request = new BillActionDetailsUpdateAppRequest(List.of( + new BillActionDetailUpdateAppRequest("토다리", 3000L, true), + new BillActionDetailUpdateAppRequest("쿠키", 7000L, true) + )); + billActionDetailService.updateBillActionDetails(event1.getToken(), action.getId(), request); + + List<BillActionDetail> results = billActionDetailRepository.findAll(); + + assertThat(results).hasSize(2) + .extracting(BillActionDetail::getMemberName, BillActionDetail::getPrice) + .containsExactly( + tuple("토다리", 3000L), + tuple("쿠키", 7000L) + ); + } +} diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java new file mode 100644 index 000000000..39e52f80c --- /dev/null +++ b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java @@ -0,0 +1,229 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; +import static org.junit.jupiter.api.Assertions.assertAll; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.request.BillActionAppRequest; +import server.haengdong.application.request.BillActionUpdateAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionDetailRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class BillActionServiceTest extends ServiceTestSupport { + + @Autowired + private BillActionService billActionService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private BillActionDetailRepository billActionDetailRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @DisplayName("지출 내역을 생성한다.") + @Test + void saveAllBillAction() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "백호", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "망쵸", MemberActionStatus.IN, 2L); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + + List<BillActionAppRequest> requests = List.of( + new BillActionAppRequest("뽕족", 10_000L), + new BillActionAppRequest("인생맥주", 15_000L) + ); + + billActionService.saveAllBillAction(event.getToken(), requests); + + List<BillAction> actions = billActionRepository.findByAction_Event(savedEvent); + + assertThat(actions).extracting(BillAction::getTitle, BillAction::getPrice, BillAction::getSequence) + .containsExactlyInAnyOrder( + tuple("뽕족", 10_000L, 3L), + tuple("인생맥주", 15_000L, 4L) + ); + } + + @DisplayName("지출 내역을 생성하면 지출 상세 내역이 생성된다.") + @Test + void saveAllBillActionTest1() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "백호", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "망쵸", MemberActionStatus.IN, 2L); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + + List<BillActionAppRequest> request = List.of( + new BillActionAppRequest("뽕족", 10_000L), + new BillActionAppRequest("인생맥주", 15_000L) + ); + + billActionService.saveAllBillAction(event.getToken(), request); + + List<BillActionDetail> billActionDetails = billActionDetailRepository.findAll(); + + assertThat(billActionDetails) + .hasSize(4) + .extracting("memberName", "price") + .containsExactlyInAnyOrder( + tuple("백호", 5_000L), + tuple("망쵸", 5_000L), + tuple("백호", 7_500L), + tuple("망쵸", 7_500L) + ); + } + + @DisplayName("이벤트가 존재하지 않으면 지출 내역을 생성할 수 없다.") + @Test + void saveAllBillAction1() { + List<BillActionAppRequest> requests = List.of( + new BillActionAppRequest("뽕족", 10_000L), + new BillActionAppRequest("인생맥주", 15_000L) + ); + + assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("지출 액션을 수정한다.") + @Test + void updateBillAction() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + Action action = Action.createFirst(savedEvent); + BillAction billAction = new BillAction(action, "뽕족", 10_000L); + BillAction savedBillAction = billActionRepository.save(billAction); + + Long actionId = savedBillAction.getAction().getId(); + BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); + + billActionService.updateBillAction(event.getToken(), actionId, request); + + BillAction updatedBillAction = billActionRepository.findById(savedBillAction.getId()).get(); + + assertAll( + () -> assertThat(updatedBillAction.getTitle()).isEqualTo("인생맥주"), + () -> assertThat(updatedBillAction.getPrice()).isEqualTo(20_000L) + ); + } + + @DisplayName("행사에 속하지 않은 지출 액션은 수정할 수 없다.") + @Test + void updateBillAction1() { + Event event1 = Fixture.EVENT1; + Event event2 = Fixture.EVENT2; + Event savedEvent1 = eventRepository.save(event1); + Event savedEvent2 = eventRepository.save(event2); + Action action1 = Action.createFirst(savedEvent1); + Action action2 = Action.createFirst(savedEvent2); + BillAction billAction1 = new BillAction(action1, "뽕족", 10_000L); + BillAction billAction2 = new BillAction(action2, "뽕족", 10_000L); + BillAction savedBillAction1 = billActionRepository.save(billAction1); + billActionRepository.save(billAction2); + + Long actionId = savedBillAction1.getAction().getId(); + BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); + + assertThatThrownBy(() -> billActionService.updateBillAction(event2.getToken(), actionId, request)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("지출 내역 금액을 변경하면 지출 디테일이 초기화 된다.") + @Test + void updateBillAction2() { + Event event = Fixture.EVENT1; + Event savedEvent = eventRepository.save(event); + Action action = Action.createFirst(savedEvent); + BillAction billAction = new BillAction(action, "뽕족", 10_000L); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "감자", 3000L, true); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "고구마", 2000L, true); + BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "당근", 3000L, true); + BillActionDetail billActionDetail4 = new BillActionDetail(billAction, "양파", 2000L, true); + billAction.addDetails(List.of(billActionDetail1, billActionDetail2, billActionDetail3, billActionDetail4)); + BillAction savedBillAction = billActionRepository.save(billAction); + + Long actionId = savedBillAction.getAction().getId(); + BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); + + billActionService.updateBillAction(event.getToken(), actionId, request); + + BillAction updatedBillAction = billActionRepository.findById(savedBillAction.getId()).get(); + List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(updatedBillAction); + + assertThat(billActionDetails).hasSize(4) + .extracting("memberName", "price") + .containsExactlyInAnyOrder( + tuple("감자", 5000L), + tuple("고구마", 5000L), + tuple("당근", 5000L), + tuple("양파", 5000L) + ); + } + + @DisplayName("지출 내역을 삭제한다.") + @Test + void deleteBillAction() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + BillAction billAction = new BillAction(new Action(event, 1L), "커피", 50_900L); + billActionRepository.save(billAction); + Long actionId = billAction.getAction().getId(); + + billActionService.deleteBillAction(event.getToken(), actionId); + + assertThat(billActionRepository.findById(billAction.getId())).isEmpty(); + } + + @DisplayName("지출 내역을 삭제하면 지출 상세도 삭제된다.") + @Test + void deleteBillActionTest1() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "백호", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "망쵸", MemberActionStatus.IN, 2L); + BillAction billAction = new BillAction(new Action(event, 3L), "커피", 50_900L); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "백호", 25_450L, false); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "망쵸", 25_450L, false); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + billActionRepository.save(billAction); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); + Long actionId = billAction.getAction().getId(); + + billActionService.deleteBillAction(event.getToken(), actionId); + + assertThat(billActionDetailRepository.findAll()).isEmpty(); + } + + @DisplayName("지출 내역 삭제 시 행사가 존재하지 않으면 예외가 발생한다.") + @Test + void deleteBillAction1() { + assertThatThrownBy(() -> billActionService.deleteBillAction("소하망쵸", 1L)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java new file mode 100644 index 000000000..407fa1457 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/EventServiceTest.java @@ -0,0 +1,231 @@ +package server.haengdong.application; + + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.BDDMockito.given; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.request.MemberNameUpdateAppRequest; +import server.haengdong.application.request.MemberNamesUpdateAppRequest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.domain.event.EventTokenProvider; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class EventServiceTest extends ServiceTestSupport { + + @Autowired + private EventService eventService; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private MemberActionRepository memberActionRepository; + + @MockBean + private EventTokenProvider eventTokenProvider; + + @DisplayName("행사를 생성한다") + @Test + void saveEventTest() { + EventAppRequest request = new EventAppRequest("test", "1234"); + given(eventTokenProvider.createToken()).willReturn("TOKEN"); + + EventAppResponse response = eventService.saveEvent(request); + + assertThat(response.token()).isEqualTo("TOKEN"); + } + + @DisplayName("토큰으로 행사를 조회한다.") + @Test + void findEventTest() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + + EventDetailAppResponse eventDetailAppResponse = eventService.findEvent(event.getToken()); + + assertThat(eventDetailAppResponse.eventName()).isEqualTo(event.getName()); + } + + @DisplayName("행사에 속한 모든 액션을 조회한다.") + @Test + void findActionsTest() { + Event event = Fixture.EVENT1; + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", IN, 1L); + Action action1 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "쿠키", IN, 1L); + Action action2 = new Action(event, 3L); + BillAction billAction = new BillAction(action2, "뽕나무쟁이족발", 30000L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction, memberAction1)); + billActionRepository.save(billAction); + + List<ActionAppResponse> actionAppResponses = eventService.findActions(event.getToken()); + + assertThat(actionAppResponses).hasSize(3) + .extracting(ActionAppResponse::actionId, + ActionAppResponse::name, + ActionAppResponse::price, + ActionAppResponse::sequence, + ActionAppResponse::actionTypeName) + .containsExactly( + tuple(1L, "토다리", null, 1L, "IN"), + tuple(2L, "쿠키", null, 2L, "IN"), + tuple(3L, "뽕나무쟁이족발", 30000L, 3L, "BILL") + ); + } + + @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") + @Test + void findAllMembersTest() { + Event event = Fixture.EVENT1; + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + Action action3 = new Action(event, 3L); + Action action4 = new Action(event, 4L); + BillAction billAction = new BillAction(action3, "뽕나무쟁이족발", 30000L); + MemberAction memberAction1 = new MemberAction(action1, "토다리", IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "쿠키", IN, 1L); + MemberAction memberAction3 = new MemberAction(action4, "쿠키", OUT, 1L); + eventRepository.save(event); + billActionRepository.save(billAction); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MembersAppResponse membersAppResponse = eventService.findAllMembers(event.getToken()); + + assertThat(membersAppResponse.memberNames()).containsExactlyInAnyOrder("토다리", "쿠키"); + } + + @DisplayName("행사 참여 인원들의 이름을 변경한다.") + @Test + void updateMember() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); + MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "쿠키", OUT, 3L); + MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "쿠키", IN, 4L); + MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "쿠키", OUT, 5L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of( + memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6 + )); + + eventService.updateMember(event.getToken(), new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), + new MemberNameUpdateAppRequest("토다리", "토쟁이") + ))); + + List<MemberAction> foundMemberActions = memberActionRepository.findAllByEvent(event); + assertThat(foundMemberActions) + .extracting(MemberAction::getId, MemberAction::getMemberName) + .contains( + tuple(memberAction1.getId(), "토쟁이"), + tuple(memberAction2.getId(), "쿡쿡"), + tuple(memberAction3.getId(), "웨디"), + tuple(memberAction4.getId(), "쿡쿡"), + tuple(memberAction5.getId(), "쿡쿡"), + tuple(memberAction6.getId(), "쿡쿡") + ); + } + + @DisplayName("이미 존재하는 인원의 이름으로 변경할 수 없다.") + @Test + void updateMember1() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), + new MemberNameUpdateAppRequest("웨디", "토다리") + )); + + assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("존재하지 않는 인원은 변경할 수 없다.") + @Test + void updateMember2() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("쿡쿡", "토쟁이"), + new MemberNameUpdateAppRequest("웨디", "말복") + )); + + assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("변경 전 참여 인원 이름이 중복될 수 없다.") + @Test + void updateMember3() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), + new MemberNameUpdateAppRequest("쿠키", "토쟁이") + )); + + assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("변경 후 참여 인원 이름이 중복될 수 없다.") + @Test + void updateMember4() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); + eventRepository.save(event); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); + + MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( + new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), + new MemberNameUpdateAppRequest("토다리", "쿡쿡") + )); + + assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java new file mode 100644 index 000000000..c04f06026 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java @@ -0,0 +1,223 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.CurrentMembers; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class MemberActionFactoryTest extends ServiceTestSupport { + + @Autowired + private MemberActionFactory memberActionFactory; + + @Autowired + private MemberActionRepository memberActionRepository; + + @Autowired + private EventRepository eventRepository; + + @DisplayName("이전 멤버 액션이 시퀀스 기준으로 정렬되지 않은 상태에서 새로운 멤버 액션 요청을 검증한다.") + @Test + void createMemberActionsTest() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action1 = new Action(event, 1L); + Action action2 = new Action(event, 2L); + MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); + MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); + memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + + List<MemberAction> unorderedMemberActions = List.of(memberAction2, memberAction1); + CurrentMembers currentMembers = CurrentMembers.of(unorderedMemberActions); + Action startAction = new Action(event, 3L); + + assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("인원 변동 액션을 생성한다.") + @Test + void createMemberActionsTest1() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest memberActionsSaveAppRequest = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + Action startAction = new Action(event, 2L); + + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + List<MemberAction> memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, + currentMembers, startAction + ); + + assertThat(memberActions).hasSize(1) + .extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus) + .containsExactly( + tuple(startAction, "토다리", MemberActionStatus.OUT) + ); + } + + @DisplayName("현재 행사에 참여 중인 경우에 퇴장할 수 있다.") + @Test + void createMemberActionsTest2() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") + @Test + void createMemberActionsTest3() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action1 = new Action(event, 1L); + MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction1); + Action action2 = new Action(event, 2L); + MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); + memberActionRepository.save(memberAction2); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("토다리", "IN"))); + Action startAction = new Action(event, 3L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction1, memberAction2)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장한 적 없는 경우에 입장할 수 있다.") + @Test + void createMemberActionsTest4() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") + @Test + void createMemberActionTest5() { + Event event = eventRepository.save(Fixture.EVENT1); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "OUT"))); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of()); + + assertThatCode( + () -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("행사에 이미 참여 중인 경우 다시 입장할 수 없다.") + @Test + void createMemberActionTest6() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("한 명의 사용자는 동시에 여러 번 입장할 수 없다.") + @Test + void createMemberActionTest7() { + Event event = eventRepository.save(Fixture.EVENT1); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of( + new MemberActionSaveAppRequest("쿠키", "IN"), + new MemberActionSaveAppRequest("쿠키", "IN") + )); + Action startAction = new Action(event, 1L); + CurrentMembers currentMembers = CurrentMembers.of(List.of()); + + assertThatCode( + () -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("한 명의 사용자는 동시에 여러 번 퇴장할 수 없다.") + @Test + void createMemberActionTest8() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of( + new MemberActionSaveAppRequest("쿠키", "OUT"), + new MemberActionSaveAppRequest("쿠키", "OUT") + )); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("한 명의 사용자는 입장과 퇴장을 동시에 할 수 없다.") + @Test + void createMemberActionTest9() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); + memberActionRepository.save(memberAction); + + MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( + List.of( + new MemberActionSaveAppRequest("쿠키", "IN"), + new MemberActionSaveAppRequest("쿠키", "OUT") + )); + Action startAction = new Action(event, 2L); + CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); + + assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java new file mode 100644 index 000000000..b6d29444c --- /dev/null +++ b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java @@ -0,0 +1,251 @@ +package server.haengdong.application; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.groups.Tuple.tuple; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import server.haengdong.application.request.MemberActionSaveAppRequest; +import server.haengdong.application.request.MemberActionsSaveAppRequest; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetail; +import server.haengdong.domain.action.BillActionDetailRepository; +import server.haengdong.domain.action.BillActionRepository; +import server.haengdong.domain.action.MemberAction; +import server.haengdong.domain.action.MemberActionRepository; +import server.haengdong.domain.action.MemberActionStatus; +import server.haengdong.domain.event.Event; +import server.haengdong.domain.event.EventRepository; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class MemberActionServiceTest extends ServiceTestSupport { + + @Autowired + private MemberActionService memberActionService; + + @Autowired + private MemberActionRepository memberActionRepository; + + @Autowired + private EventRepository eventRepository; + + @Autowired + private BillActionRepository billActionRepository; + + @Autowired + private BillActionDetailRepository billActionDetailRepository; + + @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다.") + @Test + void saveMemberActionTest() { + Event event = eventRepository.save(Fixture.EVENT1); + Action action = new Action(event, 1L); + MemberAction memberAction = new MemberAction(action, "망쵸", IN, 1L); + memberActionRepository.save(memberAction); + + assertThatCode(() -> memberActionService.saveMemberAction(event.getToken(), new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("망쵸", "OUT"))))) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") + @Test + void saveMemberActionTest1() { + Event event = eventRepository.save(Fixture.EVENT1); + Action actionOne = new Action(event, 1L); + MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", IN, 1L); + memberActionRepository.save(memberActionOne); + + Action actionTwo = new Action(event, 2L); + MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", OUT, 1L); + memberActionRepository.save(memberActionTwo); + + assertThatCode(() -> memberActionService.saveMemberAction(event.getToken(), new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("망쵸", "IN"))))) + .doesNotThrowAnyException(); + } + + @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") + @Test + void saveMemberActionTest2() { + MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( + List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); + + assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("이벤트가 없으면 현재 참여 인원을 조회할 수 없다.") + @Test + void getCurrentMembers() { + assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") + @Test + void deleteMember() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "참여자", IN, 1L); + MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "토다리", IN, 1L); + MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "쿠키", IN, 1L); + MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "소하", IN, 1L); + MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "웨디", IN, 1L); + MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "참여자", OUT, 1L); + memberActionRepository.saveAll( + List.of(memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6)); + + Event event2 = Fixture.EVENT2; + eventRepository.save(event2); + Action action2 = Action.createFirst(event2); + MemberAction anotherMemberAction = new MemberAction(action2, "참여자", IN, 1L); + memberActionRepository.save(anotherMemberAction); + + memberActionService.deleteMember(event.getToken(), "참여자"); + + List<MemberAction> memberActions = memberActionRepository.findAll(); + + assertThat(memberActions).hasSize(5) + .extracting("memberName", "status") + .containsExactly( + tuple("토다리", IN), + tuple("쿠키", IN), + tuple("소하", IN), + tuple("웨디", IN), + tuple("참여자", IN) + ); + } + + @DisplayName("이벤트에 속한 멤버을 삭제하면 전체 지출 내역 디테일이 초기화된다.") + @Test + void deleteMember1() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); + Action targetAction = new Action(event, 2L); + MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); + MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); + MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); + MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "감자", IN, 5L); + memberActionRepository.saveAll( + List.of(memberAction1, + memberAction2, + memberAction3, + memberAction4, + memberAction5 + ) + ); + BillAction billAction = new BillAction(new Action(event, 6L), "뽕족", 100_000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "쿠키", 40_000L, true); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "웨디", 30_000L, false); + BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "감자", 30_000L, false); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2, billActionDetail3)); + List<BillActionDetail> allByBillAction = billActionDetailRepository.findAllByBillAction(billAction); + System.out.println("allByBillAction = " + allByBillAction.isEmpty()); + + memberActionService.deleteMember(event.getToken(), "쿠키"); + + List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(billAction); + + assertThat(billActionDetails).hasSize(2) + .extracting("memberName", "price") + .containsExactlyInAnyOrder( + tuple("웨디", 50_000L), + tuple("감자", 50_000L) + ); + } + + @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") + @Test + void deleteMemberAction() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); + Action targetAction = new Action(event, 2L); + MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); + MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); + MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); + MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "토다리", IN, 5L); + MemberAction memberAction6 = createMemberAction(new Action(event, 6L), "토다리", OUT, 6L); + MemberAction memberAction7 = createMemberAction(new Action(event, 7L), "쿠키", OUT, 7L); + memberActionRepository.saveAll( + List.of(memberAction1, + memberAction2, + memberAction3, + memberAction4, + memberAction5, + memberAction6, + memberAction7) + ); + + memberActionService.deleteMemberAction(event.getToken(), targetAction.getId()); + List<MemberAction> memberActions = memberActionRepository.findAll(); + + assertThat(memberActions).hasSize(4) + .extracting("id", "memberName", "status") + .containsExactly( + tuple(memberAction1.getId(), "토다리", IN), + tuple(memberAction3.getId(), "쿠키", IN), + tuple(memberAction4.getId(), "웨디", IN), + tuple(memberAction7.getId(), "쿠키", OUT) + ); + } + + @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후 지출 내역 디테일이 초기화된다.") + @Test + void deleteMemberAction1() { + Event event = Fixture.EVENT1; + eventRepository.save(event); + MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); + Action targetAction = new Action(event, 2L); + MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); + MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); + MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); + MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "감자", IN, 5L); + memberActionRepository.saveAll( + List.of(memberAction1, + memberAction2, + memberAction3, + memberAction4, + memberAction5 + ) + ); + BillAction billAction = new BillAction(new Action(event, 6L), "뽕족", 100_000L); + billActionRepository.save(billAction); + BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "쿠키", 40_000L, true); + BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "웨디", 30_000L, false); + BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "감자", 30_000L, false); + billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2, billActionDetail3)); + + memberActionService.deleteMemberAction(event.getToken(), targetAction.getId()); + List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(billAction); + + assertThat(billActionDetails).hasSize(4) + .extracting("memberName", "price") + .containsExactlyInAnyOrder( + tuple("토다리", 25_000L), + tuple("쿠키", 25_000L), + tuple("웨디", 25_000L), + tuple("감자", 25_000L) + ); + } + + private MemberAction createMemberAction( + Action action, + String memberName, + MemberActionStatus memberActionStatus, + long memberGroupId + ) { + return new MemberAction(action, memberName, memberActionStatus, memberGroupId); + } +} diff --git a/server/src/test/java/server/haengdong/application/ServiceTestSupport.java b/server/src/test/java/server/haengdong/application/ServiceTestSupport.java new file mode 100644 index 000000000..b0e2db0a6 --- /dev/null +++ b/server/src/test/java/server/haengdong/application/ServiceTestSupport.java @@ -0,0 +1,11 @@ +package server.haengdong.application; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import server.haengdong.support.extension.DatabaseCleanerExtension; + +@ExtendWith(DatabaseCleanerExtension.class) +@SpringBootTest(webEnvironment= WebEnvironment.NONE) +abstract class ServiceTestSupport { +} diff --git a/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java new file mode 100644 index 000000000..39c2d0bb8 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java @@ -0,0 +1,70 @@ +package server.haengdong.docs; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import server.haengdong.application.ActionService; +import server.haengdong.application.response.MemberBillReportAppResponse; +import server.haengdong.presentation.ActionController; + +class ActionControllerDocsTest extends RestDocsSupport { + + private final ActionService actionService = mock(ActionService.class); + + @Override + protected Object initController() { + return new ActionController(actionService); + } + + @DisplayName("참여자별 정산 현황을 조회한다.") + @Test + void getMemberBillReports() throws Exception { + List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( + new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); + + given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/actions/reports", "망쵸토큰") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))) + .andDo( + document("getMemberBillReports", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + responseFields( + fieldWithPath("reports").type(JsonFieldType.ARRAY).description("전체 정산 현황 목록"), + fieldWithPath("reports[0].name").type(JsonFieldType.STRING) + .description("참여자 이름"), + fieldWithPath("reports[0].price").type(JsonFieldType.NUMBER) + .description("참여자 정산 금액") + )) + ); + } +} diff --git a/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java new file mode 100644 index 000000000..7ed6fe6c4 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java @@ -0,0 +1,128 @@ +package server.haengdong.docs; + +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.application.BillActionService; +import server.haengdong.presentation.BillActionController; +import server.haengdong.presentation.request.BillActionSaveRequest; +import server.haengdong.presentation.request.BillActionUpdateRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +class BillActionControllerDocsTest extends RestDocsSupport { + + private final BillActionService billActionService = mock(BillActionService.class); + + @Override + protected Object initController() { + return new BillActionController(billActionService); + } + + @DisplayName("지출 내역을 생성한다.") + @Test + void saveAllBillAction() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("뽕족", 10_000L), + new BillActionSaveRequest("인생맥주", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "쿠키토큰"; + + mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) + .contentType(MediaType.APPLICATION_JSON) + .cookie(EVENT_COOKIE) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo(document("createBillActions", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + requestCookies( + cookieWithName("eventToken").description("행사 관리자 토큰") + ), + requestFields( + fieldWithPath("actions").description("생성할 지출 액션 목록"), + fieldWithPath("actions[0].title").description("생성할 지출 액션의 제목"), + fieldWithPath("actions[0].price").description("생성할 지출 액션의 금액") + ) + )); + } + + @DisplayName("지출 액션을 수정한다.") + @Test + void updateBillAction() throws Exception { + BillActionUpdateRequest request = new BillActionUpdateRequest("뽕족", 10_000L); + + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "웨디토큰"; + + mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1L) + .cookie(EVENT_COOKIE) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo(document("updateBillAction", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID"), + parameterWithName("actionId").description("지출 액션 ID") + ), + requestCookies( + cookieWithName("eventToken").description("행사 관리자 토큰") + ), + requestFields( + fieldWithPath("title").description("수정할 지출 액션의 제목"), + fieldWithPath("price").description("수정할 지출 액션의 금액") + ) + )); + } + + @DisplayName("지출 내역을 삭제한다.") + @Test + void deleteBillAction() throws Exception { + String eventId = "토다리토큰"; + + mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1) + .cookie(EVENT_COOKIE) + ) + .andDo(print()) + .andExpect(status().isOk()) + .andDo(document("deleteBillAction", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID"), + parameterWithName("actionId").description("지출 액션 ID") + ), + requestCookies( + cookieWithName("eventToken").description("행사 관리자 토큰") + ) + )); + } +} diff --git a/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java new file mode 100644 index 000000000..f492195f3 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java @@ -0,0 +1,127 @@ +package server.haengdong.docs; + +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import server.haengdong.application.BillActionDetailService; +import server.haengdong.application.response.BillActionDetailAppResponse; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.presentation.BillActionDetailController; +import server.haengdong.presentation.request.BillActionDetailUpdateRequest; +import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; + +public class BillActionDetailControllerDocsTest extends RestDocsSupport { + + private final BillActionDetailService billActionDetailService = mock(BillActionDetailService.class); + + @Override + protected Object initController() { + return new BillActionDetailController(billActionDetailService); + } + + @DisplayName("참여자별 지출 금액을 조회한다.") + @Test + void findBillActionDetailsTest() throws Exception { + BillActionDetailsAppResponse appResponse = new BillActionDetailsAppResponse( + List.of(new BillActionDetailAppResponse("토다리", 1000L, false))); + given(billActionDetailService.findBillActionDetails(anyString(), anyLong())) + .willReturn(appResponse); + + mockMvc.perform(get("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.members").isArray()) + .andExpect(jsonPath("$.members[0].name").value("토다리")) + .andExpect(jsonPath("$.members[0].price").value(1000L)) + .andExpect(jsonPath("$.members[0].isFixed").value(false)) + .andDo( + document("findBillActionDetailsTest", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID"), + parameterWithName("actionId").description("액션 ID") + ), requestCookies( + cookieWithName("eventToken").description("행사 관리자 토큰") + ), responseFields( + fieldWithPath("members").type(JsonFieldType.ARRAY) + .description("전체 정산 수정 요청 목록"), + fieldWithPath("members[0].name").type(JsonFieldType.STRING) + .description("참여자 이름"), + fieldWithPath("members[0].price").type(JsonFieldType.NUMBER) + .description("참여자 정산 금액"), + fieldWithPath("members[0].isFixed").type(JsonFieldType.BOOLEAN) + .description("참여자 정산 금액 수정 여부") + ) + ) + ); + } + + @DisplayName("참여자별 지출 금액을 수정한다.") + @Test + void updateBillActionDetailsTest() throws Exception { + List<BillActionDetailUpdateRequest> billActionDetailUpdateRequests = List.of( + new BillActionDetailUpdateRequest("소하", 10000L, true), + new BillActionDetailUpdateRequest("웨디", 20000L, true) + ); + BillActionDetailsUpdateRequest request = new BillActionDetailsUpdateRequest( + billActionDetailUpdateRequests); + + String json = objectMapper.writeValueAsString(request); + + mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) + .cookie(EVENT_COOKIE) + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("updateBillActionDetailsTest", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID"), + parameterWithName("actionId").description("액션 ID") + ), + requestCookies( + cookieWithName("eventToken").description("행사 관리자 토큰") + ), + requestFields( + fieldWithPath("members").type(JsonFieldType.ARRAY) + .description("전체 정산 수정 요청 목록"), + fieldWithPath("members[0].name").type(JsonFieldType.STRING) + .description("참여자 이름"), + fieldWithPath("members[0].price").type(JsonFieldType.NUMBER) + .description("참여자 정산 금액"), + fieldWithPath("members[0].isFixed").type(JsonFieldType.BOOLEAN) + .description("참여자 정산 금액 수정 여부") + ) + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java new file mode 100644 index 000000000..88de2a3a6 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java @@ -0,0 +1,381 @@ +package server.haengdong.docs; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.cookies.CookieDocumentation.responseCookies; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; + +import java.time.Duration; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import server.haengdong.application.AuthService; +import server.haengdong.application.EventService; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.ActionAppResponse.ActionType; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; +import server.haengdong.infrastructure.auth.CookieProperties; +import server.haengdong.presentation.EventController; +import server.haengdong.presentation.request.EventLoginRequest; +import server.haengdong.presentation.request.EventSaveRequest; +import server.haengdong.presentation.request.MemberNameUpdateRequest; +import server.haengdong.presentation.request.MemberNamesUpdateRequest; + +public class EventControllerDocsTest extends RestDocsSupport { + + private final EventService eventService = mock(EventService.class); + private final AuthService authService = mock(AuthService.class); + private final CookieProperties cookieProperties = new CookieProperties( + true, true, "domain", "path", "none", Duration.ofDays(7) + ); + + @Override + protected Object initController() { + return new EventController(eventService, authService, cookieProperties); + } + + @DisplayName("이벤트를 생성한다.") + @Test + void saveEvent() throws Exception { + EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리", "0987"); + String requestBody = objectMapper.writeValueAsString(eventSaveRequest); + String eventId = "쿠키 토큰"; + EventAppResponse eventAppResponse = new EventAppResponse(eventId); + given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); + given(authService.createToken(eventId)).willReturn("jwtToken"); + given(authService.getTokenName()).willReturn("eventToken"); + + mockMvc.perform(post("/api/events") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(cookie().value("eventToken", "jwtToken")) + .andExpect(jsonPath("$.eventId").value("쿠키 토큰")) + .andDo( + document("createEvent", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestFields( + fieldWithPath("eventName").type(JsonFieldType.STRING).description("행사 이름"), + fieldWithPath("password").type(JsonFieldType.STRING).description("행사 비밀 번호") + ), + responseFields( + fieldWithPath("eventId").type(JsonFieldType.STRING) + .description("행사 ID") + ), + responseCookies( + cookieWithName("eventToken").description("행사 관리자용 토큰") + ) + ) + ); + } + + @DisplayName("토큰으로 행사를 조회한다.") + @Test + void findEventTest() throws Exception { + String eventId = "망쵸토큰"; + EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); + given(eventService.findEvent(eventId)).willReturn(eventDetailAppResponse); + + mockMvc.perform(get("/api/events/{eventId}", eventId)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.eventName").value("행동대장 회식")) + .andDo( + document("getEvent", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + responseFields( + fieldWithPath("eventName").type(JsonFieldType.STRING).description("행사 이름") + ) + ) + ); + } + + @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") + @Test + void findAllMembersTest() throws Exception { + MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("토다리", "쿠키")); + given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); + + mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames").isArray()) + .andExpect(jsonPath("$.memberNames[0]").value("토다리")) + .andExpect(jsonPath("$.memberNames[1]").value("쿠키")) + .andDo( + document("findAllEventMember", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + responseFields( + fieldWithPath("memberNames").type(JsonFieldType.ARRAY) + .description("행사 참여자 목록") + ) + ) + ); + } + + @DisplayName("행사 참여 인원의 이름을 수정한다.") + @Test + void updateMember() throws Exception { + String token = "TOKEN"; + MemberNamesUpdateRequest memberNameUpdateRequest = new MemberNamesUpdateRequest(List.of( + new MemberNameUpdateRequest("토다링", "토쟁이"), + new MemberNameUpdateRequest("감자", "고구마") + )); + + String requestBody = objectMapper.writeValueAsString(memberNameUpdateRequest); + + mockMvc.perform(put("/api/events/{eventId}/members/nameChange", token) + .cookie(EVENT_COOKIE) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("updateEventMemberName", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + requestCookies( + cookieWithName("eventToken").description("행사 관리자 토큰") + ), + requestFields( + fieldWithPath("members").type(JsonFieldType.ARRAY).description("수정할 참여자 목록"), + fieldWithPath("members[].before").type(JsonFieldType.STRING) + .description("수정 전 참여자 이름"), + fieldWithPath("members[].after").type(JsonFieldType.STRING) + .description("수정 후 참여자 이름") + ) + ) + ); + } + + @DisplayName("행사 어드민이 로그인한다.") + @Test + void loginEvent() throws Exception { + String token = "TOKEN"; + EventLoginRequest eventLoginRequest = new EventLoginRequest("1234"); + String requestBody = objectMapper.writeValueAsString(eventLoginRequest); + given(authService.createToken(token)).willReturn("jwtToken"); + given(authService.getTokenName()).willReturn("eventToken"); + + mockMvc.perform(post("/api/events/{eventId}/login", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(cookie().value("eventToken", "jwtToken")) + .andExpect(status().isOk()) + .andDo( + document("eventLogin", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + requestFields( + fieldWithPath("password").type(JsonFieldType.STRING) + .description("행사 비밀 번호") + ), + responseCookies( + cookieWithName("eventToken").description("행사 관리자용 토큰") + ) + ) + ); + } + + @DisplayName("행사 전체 액션 이력 조회") + @Test + void findActions() throws Exception { + String token = "TOKEN"; + List<ActionAppResponse> actionAppResponses = List.of( + new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), + new ActionAppResponse(2L, "족발", 100L, 2L, ActionType.BILL), + new ActionAppResponse(3L, "인생네컷", 1000L, 3L, ActionType.BILL), + new ActionAppResponse(4L, "망쵸", null, 4L, ActionType.OUT) + ); + given(eventService.findActions(token)).willReturn(actionAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/actions", token) + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.steps[0].type").value(equalTo("IN"))) + .andExpect(jsonPath("$.steps[0].stepName").value(equalTo("0차"))) + .andExpect(jsonPath("$.steps[0].members[0]").value(equalTo("망쵸"))) + .andExpect(jsonPath("$.steps[0].actions[0].actionId").value(equalTo(1))) + .andExpect(jsonPath("$.steps[0].actions[0].name").value(equalTo("망쵸"))) + .andExpect(jsonPath("$.steps[0].actions[0].price").value(equalTo(null))) + .andExpect(jsonPath("$.steps[0].actions[0].sequence").value(equalTo(1))) + + .andExpect(jsonPath("$.steps[1].type").value(equalTo("BILL"))) + .andExpect(jsonPath("$.steps[1].stepName").value(equalTo("1차"))) + .andExpect(jsonPath("$.steps[1].members[0]").value(equalTo("망쵸"))) + .andExpect(jsonPath("$.steps[1].actions[0].actionId").value(equalTo(2))) + .andExpect(jsonPath("$.steps[1].actions[0].name").value(equalTo("족발"))) + .andExpect(jsonPath("$.steps[1].actions[0].price").value(equalTo(100))) + .andExpect(jsonPath("$.steps[1].actions[0].sequence").value(equalTo(2))) + + .andExpect(jsonPath("$.steps[1].actions[1].actionId").value(equalTo(3))) + .andExpect(jsonPath("$.steps[1].actions[1].name").value(equalTo("인생네컷"))) + .andExpect(jsonPath("$.steps[1].actions[1].price").value(equalTo(1000))) + .andExpect(jsonPath("$.steps[1].actions[1].sequence").value(equalTo(3))) + + .andExpect(jsonPath("$.steps[2].type").value(equalTo("OUT"))) + .andExpect(jsonPath("$.steps[2].stepName").value(equalTo("1차"))) + .andExpect(jsonPath("$.steps[2].actions[0].actionId").value(equalTo(4))) + .andExpect(jsonPath("$.steps[2].actions[0].name").value(equalTo("망쵸"))) + .andExpect(jsonPath("$.steps[2].actions[0].price").value(equalTo(null))) + .andExpect(jsonPath("$.steps[2].actions[0].sequence").value(equalTo(4))) + + .andDo( + document("findActions", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + responseFields( + fieldWithPath("steps[].stepName").type(JsonFieldType.STRING) + .description("스탭 이름"), + fieldWithPath("steps[].type").type(JsonFieldType.STRING) + .description("액션 유형 [BILL, IN, OUT]"), + fieldWithPath("steps[].members").type(JsonFieldType.ARRAY) + .description("해당 step에 참여한 참여자 목록"), + fieldWithPath("steps[].actions[].actionId").type(JsonFieldType.NUMBER) + .description("액션 ID"), + fieldWithPath("steps[].actions[].name").type(JsonFieldType.STRING) + .description("참여자 액션일 경우 참여자 이름, 지출 액션일 경우 지출 내역 이름"), + fieldWithPath("steps[].actions[].price").type(JsonFieldType.NUMBER).optional() + .description("참여자 액션일 경우 null, 지출 액션일 경우 지출 금액"), + fieldWithPath("steps[].actions[].sequence").type(JsonFieldType.NUMBER) + .description("액션 순서"), + fieldWithPath("steps[].actions[].isFixed").type(JsonFieldType.BOOLEAN) + .description("지출 내역의 멤버별 고정 지출 금액 생성 여부") + ) + ) + ); + } + + @DisplayName("행사 전체 액션 이력 조회 v2") + @Test + void findActions2() throws Exception { + String token = "TOKEN"; + List<ActionAppResponse> actionAppResponses = List.of( + new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), + new ActionAppResponse(2L, "족발", 100L, 2L, ActionType.BILL), + new ActionAppResponse(3L, "인생네컷", 1000L, 3L, ActionType.BILL), + new ActionAppResponse(4L, "망쵸", null, 4L, ActionType.OUT) + ); + given(eventService.findActions(token)).willReturn(actionAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/actions/v2", token) + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.actions[0].actionId").value(equalTo(1))) + .andExpect(jsonPath("$.actions[0].name").value(equalTo("망쵸"))) + .andExpect(jsonPath("$.actions[0].price").value(equalTo(null))) + .andExpect(jsonPath("$.actions[0].sequence").value(equalTo(1))) + .andExpect(jsonPath("$.actions[0].type").value(equalTo("IN"))) + + .andExpect(jsonPath("$.actions[1].actionId").value(equalTo(2))) + .andExpect(jsonPath("$.actions[1].name").value(equalTo("족발"))) + .andExpect(jsonPath("$.actions[1].price").value(equalTo(100))) + .andExpect(jsonPath("$.actions[1].sequence").value(equalTo(2))) + .andExpect(jsonPath("$.actions[1].type").value(equalTo("BILL"))) + + .andExpect(jsonPath("$.actions[2].actionId").value(equalTo(3))) + .andExpect(jsonPath("$.actions[2].name").value(equalTo("인생네컷"))) + .andExpect(jsonPath("$.actions[2].price").value(equalTo(1000))) + .andExpect(jsonPath("$.actions[2].sequence").value(equalTo(3))) + .andExpect(jsonPath("$.actions[2].type").value(equalTo("BILL"))) + + .andExpect(jsonPath("$.actions[3].actionId").value(equalTo(4))) + .andExpect(jsonPath("$.actions[3].name").value(equalTo("망쵸"))) + .andExpect(jsonPath("$.actions[3].price").value(equalTo(null))) + .andExpect(jsonPath("$.actions[3].sequence").value(equalTo(4))) + .andExpect(jsonPath("$.actions[3].type").value(equalTo("OUT"))) + + .andDo( + document("findActions", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + responseFields( + fieldWithPath("actions[].actionId").type(JsonFieldType.NUMBER) + .description("액션 ID"), + fieldWithPath("actions[].name").type(JsonFieldType.STRING) + .description("참여자 액션일 경우 참여자 이름, 지출 액션일 경우 지출 내역 이름"), + fieldWithPath("actions[].price").type(JsonFieldType.NUMBER).optional() + .description("참여자 액션일 경우 null, 지출 액션일 경우 지출 금액"), + fieldWithPath("actions[].sequence").type(JsonFieldType.NUMBER) + .description("액션 순서"), + fieldWithPath("actions[].type").type(JsonFieldType.STRING) + .description("액션 타입") + ) + ) + ); + } + + @DisplayName("행사 어드민 권한을 확인한다.") + @Test + void authenticateTest() throws Exception { + String token = "TOKEN"; + mockMvc.perform(post("/api/events/{eventId}/auth", token) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + + .andDo( + document("authenticateEvent", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + requestCookies( + cookieWithName("eventToken").description("행사 관리자 토큰").optional() + ) + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java new file mode 100644 index 000000000..afd766c8f --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java @@ -0,0 +1,157 @@ +package server.haengdong.docs; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; +import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import server.haengdong.application.MemberActionService; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.presentation.MemberActionController; +import server.haengdong.presentation.request.MemberActionsSaveRequest; + +public class MemberActionControllerDocsTest extends RestDocsSupport { + + private final MemberActionService memberActionService = mock(MemberActionService.class); + + @Override + protected Object initController() { + return new MemberActionController(memberActionService); + } + + @DisplayName("참여자 행동을 추가한다.") + @Test + void saveMemberActionTest() throws Exception { + MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( + List.of("웨디", "소하", "토다리", "쿠키"), "IN"); + + String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); + + mockMvc.perform(post("/api/events/{eventId}/member-actions", "망쵸토큰") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("createMemberAction", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + requestCookies( + cookieWithName("eventToken").description("토큰 토큰") + ), + requestFields( + fieldWithPath("members").type(JsonFieldType.ARRAY) + .description("액션 대상 참여자 목록"), + fieldWithPath("status").type(JsonFieldType.STRING) + .description("참여자 액션 상태 [IN(늦참), OUT(탈주)]") + ) + ) + ); + } + + @DisplayName("현재 참여 인원을 조회합니다.") + @Test + void getCurrentMembers() throws Exception { + List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( + new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); + + given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/members/current", "망쵸토큰") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames[0]").value(equalTo("소하"))) + .andExpect(jsonPath("$.memberNames[1]").value(equalTo("토다리"))) + .andDo( + document("getCurrentMembers", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID") + ), + responseFields( + fieldWithPath("memberNames").type(JsonFieldType.ARRAY) + .description("현재 탈주 가능한 참여 인원 이름 목록") + ) + ) + ); + } + + @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") + @Test + void deleteMemberAction() throws Exception { + String eventId = "망쵸토큰"; + Long actionId = 2L; + + mockMvc.perform(delete("/api/events/{eventId}/member-actions/{actionId}", eventId, actionId) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("deleteMemberAction", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID"), + parameterWithName("actionId").description("액션 ID") + ), + requestCookies( + cookieWithName("eventToken").description("행사 관리자용 토큰") + ) + ) + ); + } + + @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") + @Test + void deleteMember() throws Exception { + String eventId = "망쵸토큰"; + String memberName = "행동대장"; + + mockMvc.perform(delete("/api/events/{eventId}/members/{memberName}", eventId, memberName) + .cookie(EVENT_COOKIE)) + .andDo(print()) + .andExpect(status().isOk()) + .andDo( + document("deleteAllMemberActionByName", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("eventId").description("행사 ID"), + parameterWithName("memberName").description("행사 참여자 이름") + ), + requestCookies( + cookieWithName("eventToken").description("행사 관리자용 토큰") + ) + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/docs/RestDocsSupport.java b/server/src/test/java/server/haengdong/docs/RestDocsSupport.java new file mode 100644 index 000000000..3e6901ba8 --- /dev/null +++ b/server/src/test/java/server/haengdong/docs/RestDocsSupport.java @@ -0,0 +1,28 @@ +package server.haengdong.docs; + +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.restdocs.RestDocumentationContextProvider; +import org.springframework.restdocs.RestDocumentationExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +@ExtendWith({RestDocumentationExtension.class}) +abstract class RestDocsSupport { + + protected MockMvc mockMvc; + + protected ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp(RestDocumentationContextProvider restDocumentation) { + this.mockMvc = MockMvcBuilders.standaloneSetup(initController()) + .apply(documentationConfiguration(restDocumentation)) + .build(); + } + + protected abstract Object initController(); +} diff --git a/server/src/test/java/server/haengdong/domain/action/ActionTest.java b/server/src/test/java/server/haengdong/domain/action/ActionTest.java new file mode 100644 index 000000000..6ff25479c --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/ActionTest.java @@ -0,0 +1,31 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; +import server.haengdong.support.fixture.Fixture; + +class ActionTest { + + @DisplayName("액션의 초기 순서번호는 1이다.") + @Test + void createFirst() { + Event event = Fixture.EVENT1; + Action action = Action.createFirst(event); + + assertThat(action.getSequence()).isOne(); + } + + @DisplayName("현재 액션의 다음 액션의 순서는 1만큼 증가한다.") + @Test + void next() { + Event event = Fixture.EVENT1; + Action action = new Action(event, 2L); + + Action nextAction = action.next(); + + assertThat(nextAction.getSequence()).isEqualTo(3L); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java new file mode 100644 index 000000000..ba1ab36f2 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java @@ -0,0 +1,89 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; +import static server.haengdong.support.fixture.Fixture.BILL_ACTION; +import static server.haengdong.support.fixture.Fixture.EVENT1; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongException; + +class BillActionTest { + + @DisplayName("지출 내역 제목의 앞뒤 공백을 제거한 길이가 1 ~ 30자가 아니면 지출을 생성할 수 없다.") + @ParameterizedTest + @ValueSource(strings = {"", " ", "1234567890123456789012345678901"}) + void validateTitle(String title) { + Event event = EVENT1; + Action action = new Action(event, 1L); + Long price = 100L; + + assertThatThrownBy(() -> new BillAction(action, title, price)) + .isInstanceOf(HaengdongException.class) + .hasMessage("앞뒤 공백을 제거한 지출 내역 제목은 1 ~ 30자여야 합니다."); + } + + @DisplayName("금액이 10,000,000 이하의 자연수가 아니면 지출을 생성할 수 없다.") + @ParameterizedTest + @ValueSource(longs = {0, 10_000_001, 20_000_000}) + void validatePrice(long price) { + Event event = EVENT1; + Action action = new Action(event, 1L); + String title = "title"; + + assertThatThrownBy(() -> new BillAction(action, title, price)) + .isInstanceOf(HaengdongException.class) + .hasMessage("지출 금액은 10,000,000 이하의 자연수여야 합니다."); + } + + @DisplayName("지출 내역을 올바르게 생성한다.") + @Test + void createBillAction() { + Event event = EVENT1; + Action action = new Action(event, 1L); + String title = "title"; + Long price = 1_000L; + + BillAction billAction = new BillAction(action, title, price); + + assertAll( + () -> assertThat(billAction.getAction()).isEqualTo(action), + () -> assertThat(billAction.getTitle()).isEqualTo(title), + () -> assertThat(billAction.getPrice()).isEqualTo(price) + ); + } + + @DisplayName("지출 액션에 멤버별 고정 금액이 설정되어 있는지 확인한다.") + @Test + void isFixed1() { + BillAction fixedBillAction = new BillAction(new Action(EVENT1, 1L), "인생네컷", 2_000L); + + List<BillActionDetail> unfixedBillActionDetails = List.of( + new BillActionDetail(BILL_ACTION, "감자", 1_000L, false), + new BillActionDetail(BILL_ACTION, "고구마", 1_000L, false) + ); + fixedBillAction.addDetails(unfixedBillActionDetails); + + assertThat(fixedBillAction.isFixed()).isEqualTo(false); + } + + @DisplayName("지출 액션에 멤버별 고정 금액이 설정되어 있는지 확인한다.") + @Test + void isFixed2() { + BillAction fixedBillAction = new BillAction(new Action(EVENT1, 1L), "인생네컷", 5_000L); + + List<BillActionDetail> unfixedBillActionDetails = List.of( + new BillActionDetail(BILL_ACTION, "감자", 4_000L, true), + new BillActionDetail(BILL_ACTION, "고구마", 1_000L, true) + ); + fixedBillAction.addDetails(unfixedBillActionDetails); + + assertThat(fixedBillAction.isFixed()).isEqualTo(true); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java new file mode 100644 index 000000000..93148abd3 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java @@ -0,0 +1,97 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; + +import java.util.List; +import java.util.Set; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; +import server.haengdong.exception.HaengdongException; +import server.haengdong.support.fixture.Fixture; + +class CurrentMembersTest { + + @DisplayName("인원 변동 이력으로 현재 참여 인원을 계산한다.") + @Test + void of() { + Event event = Fixture.EVENT1; + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(event, 1L), "망쵸", IN, 1L), + new MemberAction(new Action(event, 2L), "백호", IN, 1L), + new MemberAction(new Action(event, 3L), "백호", OUT, 1L), + new MemberAction(new Action(event, 4L), "웨디", IN, 1L) + ); + + CurrentMembers currentMembers = CurrentMembers.of(memberActions); + + assertThat(currentMembers.getMembers()) + .containsExactlyInAnyOrder("망쵸", "웨디"); + } + + @DisplayName("인원 변동 액션의 상태가 IN이면 현재 인원에 추가한다.") + @Test + void addMemberAction1() { + CurrentMembers currentMembers = new CurrentMembers(); + Event event = Fixture.EVENT1; + MemberAction memberAction = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); + + CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction); + Set<String> members = addedCurrentMembers.getMembers(); + + assertThat(members).hasSize(1) + .containsExactly("웨디"); + } + + @DisplayName("인원 변동 액션의 상태가 OUT이면 현재 인원에서 제외한다.") + @Test + void addMemberAction2() { + Event event = Fixture.EVENT1; + MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); + CurrentMembers currentMembers = new CurrentMembers().addMemberAction(memberAction1); + MemberAction memberAction2 = new MemberAction(new Action(event, 1L), "웨디", OUT, 1L); + + CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction2); + + assertThat(addedCurrentMembers.getMembers()).hasSize(0); + } + + @DisplayName("현재 참여중인 인원은 나갈 수 있다.") + @Test + void validate1() { + CurrentMembers currentMembers = new CurrentMembers(Set.of("토다리")); + + assertThatCode(() -> currentMembers.validate("토다리", OUT)) + .doesNotThrowAnyException(); + } + + @DisplayName("현재 참여중이지 않은 인원은 들어올 수 있다.") + @Test + void validate2() { + CurrentMembers currentMembers = new CurrentMembers(Set.of("쿠키")); + + assertThatCode(() -> currentMembers.validate("토다리", IN)) + .doesNotThrowAnyException(); + } + + @DisplayName("현재 참여중인 인원은 들어올 수 없다.") + @Test + void validate3() { + CurrentMembers currentMembers = new CurrentMembers(Set.of("토다리")); + + assertThatCode(() -> currentMembers.validate("토다리", IN)) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("현재 참여중이지 않은 인원은 나갈 수 없다.") + @Test + void validate4() { + CurrentMembers currentMembers = new CurrentMembers(Set.of("쿠키")); + + assertThatCode(() -> currentMembers.validate("토다리", OUT)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java new file mode 100644 index 000000000..02070a537 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java @@ -0,0 +1,56 @@ +package server.haengdong.domain.action; + +import static org.assertj.core.api.Assertions.assertThat; +import static server.haengdong.domain.action.MemberActionStatus.IN; +import static server.haengdong.domain.action.MemberActionStatus.OUT; +import static server.haengdong.support.fixture.Fixture.BILL_ACTION; + +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.domain.event.Event; +import server.haengdong.support.fixture.Fixture; + +class MemberBillReportTest { + + @DisplayName("액션 목록으로 참가자 정산 리포트를 생성한다.") + @Test + void createByActions() { + Event event = Fixture.EVENT1; + List<BillAction> billActions = List.of( + new BillAction(new Action(event, 4L), "뽕족", 60_000L), + new BillAction(new Action(event, 7L), "인생네컷", 20_000L) + ); + billActions.get(0).addDetails( + List.of( + new BillActionDetail(BILL_ACTION, "소하", 10_000L, false), + new BillActionDetail(BILL_ACTION, "감자", 40_000L, true), + new BillActionDetail(BILL_ACTION, "쿠키", 10_000L, false) + ) + ); + billActions.get(1).addDetails( + List.of( + new BillActionDetail(BILL_ACTION, "소하", 5_000L, true), + new BillActionDetail(BILL_ACTION, "쿠키", 15_000L, true) + ) + ); + List<MemberAction> memberActions = List.of( + new MemberAction(new Action(event, 1L), "소하", IN, 1L), + new MemberAction(new Action(event, 2L), "감자", IN, 1L), + new MemberAction(new Action(event, 3L), "쿠키", IN, 1L), + new MemberAction(new Action(event, 5L), "감자", OUT, 2L) + ); + + MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); + + assertThat(memberBillReport.getReports()) + .containsAllEntriesOf( + Map.of( + "감자", 40_000L, + "쿠키", 25_000L, + "소하", 15_000L + ) + ); + } +} diff --git a/server/src/test/java/server/haengdong/domain/event/EventTest.java b/server/src/test/java/server/haengdong/domain/event/EventTest.java new file mode 100644 index 000000000..12c0c0569 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/event/EventTest.java @@ -0,0 +1,65 @@ +package server.haengdong.domain.event; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.exception.HaengdongException; + +class EventTest { + + @DisplayName("공백 문자가 연속되지 않고, 이름이 2자 이상 20자 이하인 행사를 생성하면 예외가 발생하지 않는다.") + @ParameterizedTest + @ValueSource(strings = {"12", "12345678901234567890", "공 백", " 공백", "공백 ", " 공 백 "}) + void createSuccessTest(String eventName) { + assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) + .doesNotThrowAnyException(); + } + + @DisplayName("공백 문자가 연속되면 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {" 공백", "공백 ", "공백 연속", "공 백"}) + void createFailTest1(String eventName) { + assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class) + .hasMessage(String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", eventName)); + } + + @DisplayName("이름이 1자 미만이거나 20자 초과인 경우 예외가 발생한다.") + @ParameterizedTest + @ValueSource(strings = {"", " ", "123456789012345678901"}) + void createFilTest2(String eventName) { + assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class) + .hasMessage(String.format("행사 이름은 1자 이상 20자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", eventName.length())); + } + + @DisplayName("비밀번호는 4자리 숫자 입니다.") + @ParameterizedTest + @ValueSource(strings = {"1", "12", "123", "12345", "adgd"}) + void validatePassword(String password) { + assertThatCode(() -> new Event("이름", password, "TEST_TOKEN")) + .isInstanceOf(HaengdongException.class); + } + + @DisplayName("비밀번호가 다른지 검증한다.") + @Test + void isNotSamePassword() { + String rawPassword = "1234"; + Event event = new Event("이름", rawPassword, "TEST_TOKEN"); + + assertThat(event.isPasswordMismatch(rawPassword)).isFalse(); + } + + @DisplayName("비밀번호가 다른지 검증한다.") + @Test + void isNotSamePassword1() { + String rawPassword = "1234"; + Event event = new Event("이름", "5678", "TEST_TOKEN"); + + assertThat(event.isPasswordMismatch(rawPassword)).isTrue(); + } +} diff --git a/server/src/test/java/server/haengdong/domain/event/PasswordTest.java b/server/src/test/java/server/haengdong/domain/event/PasswordTest.java new file mode 100644 index 000000000..c504d3aa2 --- /dev/null +++ b/server/src/test/java/server/haengdong/domain/event/PasswordTest.java @@ -0,0 +1,19 @@ +package server.haengdong.domain.event; + +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import server.haengdong.exception.HaengdongException; + +class PasswordTest { + + @DisplayName("비밀번호는 4자리 숫자 입니다.") + @ParameterizedTest + @ValueSource(strings = {"1", "12", "123", "12345", "adgd"}) + void validatePassword(String rawPassword) { + assertThatCode(() -> new Password(rawPassword)) + .isInstanceOf(HaengdongException.class); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java new file mode 100644 index 000000000..1de5889b5 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java @@ -0,0 +1,36 @@ +package server.haengdong.presentation; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import server.haengdong.application.response.MemberBillReportAppResponse; + +class ActionControllerTest extends ControllerTestSupport { + + @DisplayName("참여자별 정산 현황을 조회한다.") + @Test + void getMemberBillReports() throws Exception { + List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( + new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); + + given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/actions/reports", "망쵸토큰") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) + .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java new file mode 100644 index 000000000..4420e369c --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java @@ -0,0 +1,97 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.exception.HaengdongErrorCode; +import server.haengdong.exception.HaengdongException; +import server.haengdong.presentation.request.BillActionSaveRequest; +import server.haengdong.presentation.request.BillActionUpdateRequest; +import server.haengdong.presentation.request.BillActionsSaveRequest; + +class BillActionControllerTest extends ControllerTestSupport { + + @DisplayName("지출 내역을 생성한다.") + @Test + void saveAllBillAction() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("뽕족", 10_000L), + new BillActionSaveRequest("인생맥주", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "쿠키토큰"; + + mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("title이 비어 있는 경우 지출 내역을 생성할 수 없다.") + @Test + void saveAllBillAction1() throws Exception { + BillActionsSaveRequest request = new BillActionsSaveRequest( + List.of( + new BillActionSaveRequest("", 10_000L), + new BillActionSaveRequest("인생맥주", 10_000L) + ) + ); + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "소하토큰"; + + mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isBadRequest()); + } + + @DisplayName("지출 액션을 수정한다.") + @Test + void updateBillAction() throws Exception { + BillActionUpdateRequest request = new BillActionUpdateRequest("뽕족", 10_000L); + + String requestBody = objectMapper.writeValueAsString(request); + String eventId = "웨디토큰"; + + mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("지출 내역을 삭제한다.") + @Test + void deleteBillAction() throws Exception { + String eventId = "토다리토큰"; + + mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("존재하지 않는 행사에 대한 지출 내역을 삭제할 수 없다.") + @Test + void deleteBillAction1() throws Exception { + String eventId = "이상해토큰"; + doThrow(new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)) + .when(billActionService).deleteBillAction(any(String.class), any(Long.class)); + + mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1)) + .andDo(print()) + .andExpect(status().isBadRequest()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java new file mode 100644 index 000000000..6b595ee27 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java @@ -0,0 +1,56 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.application.response.BillActionDetailAppResponse; +import server.haengdong.application.response.BillActionDetailsAppResponse; +import server.haengdong.presentation.request.BillActionDetailUpdateRequest; +import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; + +class BillActionDetailControllerTest extends ControllerTestSupport { + + @DisplayName("참여자별 지출 금액을 조회한다.") + @Test + void findBillActionDetails() throws Exception { + BillActionDetailsAppResponse appResponse = new BillActionDetailsAppResponse( + List.of(new BillActionDetailAppResponse("토다리", 1000L, false))); + given(billActionDetailService.findBillActionDetails(anyString(), anyLong())) + .willReturn(appResponse); + + mockMvc.perform(get("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.members").isArray()) + .andExpect(jsonPath("$.members[0].name").value("토다리")) + .andExpect(jsonPath("$.members[0].price").value(1000L)); + } + + @DisplayName("참여자별 지출 금액을 수정한다.") + @Test + void updateBillActionDetailsTest() throws Exception { + List<BillActionDetailUpdateRequest> billActionDetailUpdateRequests = List.of( + new BillActionDetailUpdateRequest("소하", 10000L, true), + new BillActionDetailUpdateRequest("웨디", 20000L, true) + ); + BillActionDetailsUpdateRequest request = new BillActionDetailsUpdateRequest( + billActionDetailUpdateRequests); + + String json = objectMapper.writeValueAsString(request); + + mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(json)) + .andDo(print()) + .andExpect(status().isOk()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java b/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java new file mode 100644 index 000000000..46489b1a5 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java @@ -0,0 +1,53 @@ +package server.haengdong.presentation; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import server.haengdong.application.ActionService; +import server.haengdong.application.AuthService; +import server.haengdong.application.BillActionDetailService; +import server.haengdong.application.BillActionService; +import server.haengdong.application.EventService; +import server.haengdong.application.MemberActionService; + +@WebMvcTest( + controllers = { + EventController.class, + ActionController.class, + BillActionController.class, + MemberActionController.class, + BillActionDetailController.class + }, + excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {WebMvcConfigurer.class})} +) +abstract class ControllerTestSupport { + + @Autowired + protected MockMvc mockMvc; + + @Autowired + protected ObjectMapper objectMapper; + + @MockBean + protected EventService eventService; + + @MockBean + protected AuthService authService; + + @MockBean + protected ActionService actionService; + + @MockBean + protected MemberActionService memberActionService; + + @MockBean + protected BillActionService billActionService; + + @MockBean + protected BillActionDetailService billActionDetailService; +} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java new file mode 100644 index 000000000..fcfe48d01 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java @@ -0,0 +1,111 @@ +package server.haengdong.presentation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.application.request.EventAppRequest; +import server.haengdong.application.response.EventAppResponse; +import server.haengdong.application.response.EventDetailAppResponse; +import server.haengdong.application.response.MembersAppResponse; +import server.haengdong.presentation.request.EventLoginRequest; +import server.haengdong.presentation.request.EventSaveRequest; +import server.haengdong.presentation.request.MemberNameUpdateRequest; +import server.haengdong.presentation.request.MemberNamesUpdateRequest; + + +class EventControllerTest extends ControllerTestSupport { + + @DisplayName("이벤트를 생성한다.") + @Test + void saveEvent() throws Exception { + EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리", "0987"); + String requestBody = objectMapper.writeValueAsString(eventSaveRequest); + String eventId = "망쵸토큰"; + EventAppResponse eventAppResponse = new EventAppResponse(eventId); + given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); + given(authService.createToken(eventId)).willReturn("jwtToken"); + given(authService.getTokenName()).willReturn("eventToken"); + + mockMvc.perform(post("/api/events") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(cookie().value("eventToken", "jwtToken")) + .andExpect(jsonPath("$.eventId").value("망쵸토큰")); + } + + @DisplayName("토큰으로 행사를 조회한다.") + @Test + void findEventTest() throws Exception { + String eventId = "망쵸토큰"; + EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); + given(eventService.findEvent(eventId)).willReturn(eventDetailAppResponse); + + mockMvc.perform(get("/api/events/{eventId}", eventId)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.eventName").value("행동대장 회식")); + } + + @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") + @Test + void findAllMembersTest() throws Exception { + MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("토다리", "쿠키")); + given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); + + mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames").isArray()) + .andExpect(jsonPath("$.memberNames[0]").value("토다리")) + .andExpect(jsonPath("$.memberNames[1]").value("쿠키")); + } + + @DisplayName("행사 참여 인원의 이름을 수정한다.") + @Test + void updateMember() throws Exception { + String token = "TOKEN"; + MemberNamesUpdateRequest memberNameUpdateRequest = new MemberNamesUpdateRequest(List.of( + new MemberNameUpdateRequest("토다링", "토쟁이"), + new MemberNameUpdateRequest("감자", "고구마") + )); + + String requestBody = objectMapper.writeValueAsString(memberNameUpdateRequest); + + mockMvc.perform(put("/api/events/{eventId}/members/nameChange", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("행사 어드민이 로그인한다.") + @Test + void loginEvent() throws Exception { + String token = "TOKEN"; + EventLoginRequest eventLoginRequest = new EventLoginRequest("1234"); + String requestBody = objectMapper.writeValueAsString(eventLoginRequest); + given(authService.createToken(token)).willReturn("jwtToken"); + given(authService.getTokenName()).willReturn("eventToken"); + + mockMvc.perform(post("/api/events/{eventId}/login", token) + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(cookie().value("eventToken", "jwtToken")) + .andExpect(status().isOk()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java new file mode 100644 index 000000000..f50c70a17 --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java @@ -0,0 +1,74 @@ +package server.haengdong.presentation; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import server.haengdong.application.response.CurrentMemberAppResponse; +import server.haengdong.presentation.request.MemberActionsSaveRequest; + +class MemberActionControllerTest extends ControllerTestSupport { + + @DisplayName("참여자 행동을 추가한다.") + @Test + void saveMemberActionTest() throws Exception { + MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( + List.of("웨디", "소하", "토다리", "쿠키"), "IN"); + + String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); + + mockMvc.perform(post("/api/events/{eventId}/member-actions", "망쵸토큰") + .contentType(MediaType.APPLICATION_JSON) + .content(requestBody)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("현재 참여 인원을 조회합니다.") + @Test + void getCurrentMembers() throws Exception { + List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( + new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); + + given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); + + mockMvc.perform(get("/api/events/{eventId}/members/current", "망쵸토큰") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.memberNames[0]").value(equalTo("소하"))) + .andExpect(jsonPath("$.memberNames[1]").value(equalTo("토다리"))); + } + + @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") + @Test + void deleteMemberAction() throws Exception { + String eventId = "망쵸토큰"; + Long actionId = 2L; + + mockMvc.perform(delete("/api/events/{eventId}/member-actions/{actionId}", eventId, actionId)) + .andDo(print()) + .andExpect(status().isOk()); + } + + @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") + @Test + void deleteMember() throws Exception { + String eventId = "망쵸토큰"; + String memberName = "행동대장"; + + mockMvc.perform(delete("/api/events/{eventId}/members/{memberName}", eventId, memberName)) + .andDo(print()) + .andExpect(status().isOk()); + } +} diff --git a/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java b/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java new file mode 100644 index 000000000..051fcae0f --- /dev/null +++ b/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java @@ -0,0 +1,63 @@ +package server.haengdong.presentation.response; + + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import server.haengdong.application.response.ActionAppResponse; +import server.haengdong.application.response.ActionAppResponse.ActionType; + +class StepsResponseTest { + + @DisplayName("이웃한 같은 타입의 액션들을 그룹화 하여 응답객체를 생성한다.") + @Test + void of() { + List<ActionAppResponse> actions = List.of( + new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), + new ActionAppResponse(2L, "백호", null, 2L, ActionType.IN), + new ActionAppResponse(3L, "감자탕", 10_000L, 3L, ActionType.BILL), + new ActionAppResponse(4L, "인생네컷", 10_000L, 4L, ActionType.BILL), + new ActionAppResponse(5L, "소하", null, 5L, ActionType.IN), + new ActionAppResponse(6L, "웨디", null, 6L, ActionType.IN), + new ActionAppResponse(7L, "망쵸", null, 7L, ActionType.OUT), + new ActionAppResponse(8L, "백호", null, 8L, ActionType.OUT), + new ActionAppResponse(9L, "노래방", 20_000L, 9L, ActionType.BILL) + ); + + StepsResponse stepsResponse = StepsResponse.of(actions); + + StepsResponse expected = new StepsResponse( + List.of( + new StepResponse("0차", "IN", List.of("망쵸", "백호"), List.of( + new ActionResponse(1L, "망쵸", null, 1L), + new ActionResponse(2L, "백호", null, 2L) + )), + new StepResponse("1차", "BILL", List.of("망쵸", "백호"), List.of( + new ActionResponse(3L, "감자탕", 10_000L, 3L), + new ActionResponse(4L, "인생네컷", 10_000L, 4L) + )), + new StepResponse("1차", "IN", List.of("망쵸", "백호", "소하", "웨디"), List.of( + new ActionResponse(5L, "소하", null, 5L), + new ActionResponse(6L, "웨디", null, 6L) + )), + new StepResponse("1차", "OUT", List.of("소하", "웨디"), List.of( + new ActionResponse(7L, "망쵸", null, 7L), + new ActionResponse(8L, "백호", null, 8L) + )), + new StepResponse("2차", "BILL", List.of("소하", "웨디"), List.of( + new ActionResponse(9L, "노래방", 20_000L, 9L) + )) + ) + ); + assertThat(stepsResponse).isEqualTo(expected); + } + + @DisplayName("액션이 없으면 빈 스탭들이 만들어진다.") + @Test + void ofEmpty() { + StepsResponse stepsResponse = StepsResponse.of(List.of()); + assertThat(stepsResponse.steps()).isEmpty(); + } +} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java new file mode 100644 index 000000000..346e81d2d --- /dev/null +++ b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java @@ -0,0 +1,52 @@ +package server.haengdong.support.extension; + +import jakarta.annotation.PostConstruct; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import java.util.List; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +class DatabaseCleaner { + + private static final String REFERENTIAL_FORMAT = "set referential_integrity %b;"; + private static final String TRUNCATE_FORMAT = "truncate table %s restart identity;"; + + @PersistenceContext + private EntityManager em; + private String truncateTablesQuery; + + @PostConstruct + public void createTruncateQuery() { + List<String> tableNames = getTableNames(); + StringBuilder stringBuilder = new StringBuilder(); + + for (String tableName : tableNames) { + String truncateQuery = String.format(TRUNCATE_FORMAT, tableName); + stringBuilder.append(truncateQuery); + } + truncateTablesQuery = stringBuilder.toString(); + } + + private List<String> getTableNames() { + String sql = """ + select table_name + from information_schema.tables + where table_schema = 'PUBLIC' + """; + return em.createNativeQuery(sql).getResultList(); + } + + @Transactional + public void clear() { + em.clear(); + truncate(); + } + + private void truncate() { + em.createNativeQuery(String.format(REFERENTIAL_FORMAT, false)).executeUpdate(); + em.createNativeQuery(truncateTablesQuery).executeUpdate(); + em.createNativeQuery(String.format(REFERENTIAL_FORMAT, true)).executeUpdate(); + } +} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java new file mode 100644 index 000000000..653ecadb3 --- /dev/null +++ b/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java @@ -0,0 +1,19 @@ +package server.haengdong.support.extension; + +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +public class DatabaseCleanerExtension implements AfterEachCallback { + + @Override + public void afterEach(ExtensionContext context) { + DatabaseCleaner databaseCleaner = getDataCleaner(context); + databaseCleaner.clear(); + } + + private DatabaseCleaner getDataCleaner(ExtensionContext extensionContext) { + return SpringExtension.getApplicationContext(extensionContext) + .getBean(DatabaseCleaner.class); + } +} diff --git a/server/src/test/java/server/haengdong/support/fixture/Fixture.java b/server/src/test/java/server/haengdong/support/fixture/Fixture.java new file mode 100644 index 000000000..6844915d9 --- /dev/null +++ b/server/src/test/java/server/haengdong/support/fixture/Fixture.java @@ -0,0 +1,15 @@ +package server.haengdong.support.fixture; + +import jakarta.servlet.http.Cookie; +import server.haengdong.domain.action.Action; +import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.event.Event; + +public class Fixture { + + public static final Event EVENT1 = new Event("쿠키", "1234", "TOKEN1"); + public static final Event EVENT2 = new Event("웨디", "1234", "TOKEN2"); + public static final Cookie EVENT_COOKIE = new Cookie("eventToken", "토큰토큰"); + public static final Action ACTION = new Action(EVENT1, 1L); + public static final BillAction BILL_ACTION = new BillAction(ACTION, "뽕족", 30_000L); +} From dcf03874d5e8f209bcd2795ac9ccefd1dcc43a9e Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:01:25 +0900 Subject: [PATCH 199/273] =?UTF-8?q?fix:=20=EB=B0=B0=EA=B2=BD=20=EC=83=89?= =?UTF-8?q?=EC=9D=B4=20=EC=9E=98=EB=A6=AC=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20(#466)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: 생성 페이지 background 설정 * design: 메인 레이아웃 light gray 색 추가 * design: 홈페이지 padding bottom 2rem 추가 * design: root의 height auto로 설정 및 배경색 제거 * design: 효과없는 height 100% 제거 * design: 바텀시트 삭제로 어드민 페이지 패딩 바텀 조정 * feat: Flex prop min height 속성 추가, 알고보니 min-height 속성이 있어야 화면이 꽉 채워짐 --- HDesign/src/components/Flex/Flex.style.ts | 4 ++++ HDesign/src/components/Flex/Flex.type.ts | 3 ++- HDesign/src/layouts/MainLayout.tsx | 3 ++- client/src/GlobalStyle.ts | 3 --- client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx | 2 +- client/src/pages/CreateEventPage/SetEventNamePage.tsx | 2 +- client/src/pages/CreateEventPage/SetEventPasswordPage.tsx | 2 +- client/src/pages/EventPage/AdminPage/AdminPage.style.ts | 2 +- client/src/pages/EventPage/HomePage/HomePage.tsx | 2 +- 9 files changed, 13 insertions(+), 10 deletions(-) diff --git a/HDesign/src/components/Flex/Flex.style.ts b/HDesign/src/components/Flex/Flex.style.ts index 7d2e526a7..672cf2dd6 100644 --- a/HDesign/src/components/Flex/Flex.style.ts +++ b/HDesign/src/components/Flex/Flex.style.ts @@ -14,6 +14,7 @@ export const flexStyle = ({ margin = '0', width = 'auto', height = 'auto', + minHeight, backgroundColor, theme, ...rest @@ -30,6 +31,7 @@ export const flexStyle = ({ margin, width, height, + minHeight, ...rest, backgroundColor: (() => { @@ -38,6 +40,8 @@ export const flexStyle = ({ return theme?.colors.white; case 'gray': return theme?.colors.grayContainer; + case 'lightGray': + return theme?.colors.lightGrayContainer; default: return 'none'; } diff --git a/HDesign/src/components/Flex/Flex.type.ts b/HDesign/src/components/Flex/Flex.type.ts index 22db11365..e70fb4c21 100644 --- a/HDesign/src/components/Flex/Flex.type.ts +++ b/HDesign/src/components/Flex/Flex.type.ts @@ -2,7 +2,7 @@ import {Theme} from '@theme/theme.type'; export type FlexDirectionType = 'row' | 'column' | 'rowReverse' | 'columnReverse'; export type FlexDirectionStrictType = 'row' | 'column' | 'row-reverse' | 'column-reverse'; -export type FlexBackgroundColor = 'gray' | 'white'; +export type FlexBackgroundColor = 'gray' | 'white' | 'lightGray'; export interface FlexProps { justifyContent?: 'flexStart' | 'center' | 'flexEnd' | 'spaceBetween' | 'spaceAround' | 'spaceEvenly'; @@ -16,4 +16,5 @@ export interface FlexProps { height?: string; backgroundColor?: FlexBackgroundColor; theme?: Theme; + minHeight?: string; } diff --git a/HDesign/src/layouts/MainLayout.tsx b/HDesign/src/layouts/MainLayout.tsx index b64e3c546..22012fde8 100644 --- a/HDesign/src/layouts/MainLayout.tsx +++ b/HDesign/src/layouts/MainLayout.tsx @@ -2,7 +2,7 @@ import {PropsWithChildren} from 'react'; import {Flex} from '..'; -type MainLayoutBackground = 'white' | 'gray'; +type MainLayoutBackground = 'white' | 'gray' | 'lightGray'; interface MainLayoutProps extends PropsWithChildren { backgroundColor?: MainLayoutBackground; @@ -18,6 +18,7 @@ export function MainLayout({backgroundColor, children}: MainLayoutProps) { gap="1rem" width="100%" height="100%" + minHeight="100vh" > {children} </Flex> diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index ecbfdef56..ab16de8e1 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -156,8 +156,5 @@ export const GlobalStyle = css` #root { display: flex; flex-direction: column; - height: 100%; - - background-color: #f1f0f5; } `; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 093d2a52a..f7549563f 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -21,7 +21,7 @@ const CompleteCreateEventPage = () => { const homePageUrl = getEventPageUrlByEnvironment(eventId ?? '', 'home'); return ( - <MainLayout> + <MainLayout backgroundColor="white"> <TopNav /> <Title title="행사 개시" diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index fc6830467..e283d17a8 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -17,7 +17,7 @@ const SetEventNamePage = () => { }; return ( - <MainLayout> + <MainLayout backgroundColor="white"> <TopNav> <Back /> </TopNav> diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 0a1fd7c5e..f6e8dee28 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -9,7 +9,7 @@ const SetEventPasswordPage = () => { const {submitPassword, errorMessage, password, handleChange, canSubmit} = useSetEventPasswordPage(); return ( - <MainLayout> + <MainLayout backgroundColor="white"> <TopNav> <Back /> </TopNav> diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts index 1a711bbbd..cf6bb0042 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts +++ b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts @@ -5,7 +5,7 @@ export const receiptStyle = () => display: 'flex', flexDirection: 'column', gap: '1rem', - paddingBottom: '8.75rem', + paddingBottom: '2rem', }); export const titleAndListButtonContainerStyle = () => diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 214526f39..72fc77cb9 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -13,7 +13,7 @@ const HomePage = () => { const {totalExpenseAmount} = useTotalExpenseAmountStore(); return ( - <div> + <div style={{paddingBottom: '2rem'}}> <Title title={eventName} price={totalExpenseAmount} /> <Tabs tabsContainerStyle={{gap: '1rem'}}> <Tab label="전체 지출 내역" content={<StepList />} /> From 20e08187a3530ca004a32594976f7d2f379d41db Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:01:42 +0900 Subject: [PATCH 200/273] =?UTF-8?q?feat:=20title=EA=B3=BC=20price=EC=97=90?= =?UTF-8?q?=20=EA=B0=92=EC=9D=B4=20=EC=A1=B4=EC=9E=AC=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20=EC=A7=80=EC=B6=9C=20?= =?UTF-8?q?input=20=EB=8B=AB=EA=B8=B0=20(#472)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useSetBillInput.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/hooks/useSetBillInput.ts b/client/src/hooks/useSetBillInput.ts index 4f839602a..a14b2a481 100644 --- a/client/src/hooks/useSetBillInput.ts +++ b/client/src/hooks/useSetBillInput.ts @@ -52,6 +52,8 @@ const useSetBillInput = ({setIsAddEditableItem}: UseSetBillInputProps): UseSetBi }, }, ); + } else if (!isEmptyTitle && !isEmptyPrice) { + setIsAddEditableItem(false); } }; From ff3bf13f48ff438e31bbac436766540f274cf992 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:02:06 +0900 Subject: [PATCH 201/273] =?UTF-8?q?feat:=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EC=9D=BC=EB=B6=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#475)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: 통일성 위해 디자인 수정 * chore: v0.1.78 배포 * chore: hdesign 0.1.78 적용 * chore: v0.1.79 배포 및 적용 --- HDesign/package-lock.json | 4 ++-- HDesign/package.json | 2 +- HDesign/src/components/Button/Button.style.ts | 6 +++--- .../components/DragHandleItem/DragHandleItem.style.ts | 4 ++-- .../DragHandleItemContainer/DragHandleItemContainer.tsx | 4 ++-- .../src/components/EditableItem/EditableItem.style.ts | 4 ++-- HDesign/src/components/FixedButton/FixedButton.style.ts | 4 ++-- client/package-lock.json | 9 ++++----- client/package.json | 2 +- 9 files changed, 19 insertions(+), 20 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index 4bfb80709..c252ff81e 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.77", + "version": "0.1.79", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.77", + "version": "0.1.79" "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index 0cc67d62f..9013c10ec 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.77", + "version": "0.1.79", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/HDesign/src/components/Button/Button.style.ts b/HDesign/src/components/Button/Button.style.ts index e8d68d635..295fbc50c 100644 --- a/HDesign/src/components/Button/Button.style.ts +++ b/HDesign/src/components/Button/Button.style.ts @@ -46,21 +46,21 @@ const getButtonSizeStyle = (size: ButtonSize) => { const style = { small: css({ padding: '0.5rem 0.75rem', - borderRadius: '0.75rem', + borderRadius: '0.5rem', fontFamily: 'Pretendard', fontSize: '0.75rem', fontWeight: '400', }), medium: css({ padding: '0.75rem 1rem', - borderRadius: '1rem', + borderRadius: '0.75rem', fontFamily: 'Pretendard', fontSize: '1rem', fontWeight: '700', }), large: css({ padding: '1rem 1.5rem', - borderRadius: '1.25rem', + borderRadius: '1rem', fontFamily: 'Pretendard', fontSize: '1.25rem', fontWeight: '700', diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts index c23166272..b641c5fb3 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts @@ -8,8 +8,8 @@ export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgr css({ display: 'flex', justifyContent: 'space-between', - padding: hasDragHandle ? '0.5rem 0.5rem 0.5rem 0.25rem' : '0.5rem', - borderRadius: '0.5rem', + padding: hasDragHandle ? '0.5rem 1rem 0.5rem 0.5rem' : '0.5rem 1rem', + borderRadius: '0.75rem', backgroundColor: theme.colors[backgroundColor], }); diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx index 9bd54eacf..a95bfb5de 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx @@ -24,7 +24,7 @@ export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ( return ( <div css={containerStyle(theme, backgroundColor)} {...htmlProps}> - <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> + <Flex justifyContent="spaceBetween" paddingInline="1rem"> <Text textColor="gray" size="captionBold" onClick={onTopLeftTextClick}> {topLeftText} </Text> @@ -33,7 +33,7 @@ export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ( </Text> </Flex> {children} - <Flex justifyContent="spaceBetween" paddingInline="0.5rem"> + <Flex justifyContent="spaceBetween" paddingInline="1rem"> <Text textColor="gray" size="captionBold" onClick={onBottomLeftTextClick}> {bottomLeftText} </Text> diff --git a/HDesign/src/components/EditableItem/EditableItem.style.ts b/HDesign/src/components/EditableItem/EditableItem.style.ts index a0fe3ca2a..97142f2d8 100644 --- a/HDesign/src/components/EditableItem/EditableItem.style.ts +++ b/HDesign/src/components/EditableItem/EditableItem.style.ts @@ -8,8 +8,8 @@ export const editableItemStyle = (theme: Theme, backgroundColor: ColorKeys) => css({ display: 'flex', justifyContent: 'space-between', - padding: '0.5rem', - borderRadius: '0.5rem', + padding: '0.5rem 1rem', + borderRadius: '0.75rem', backgroundColor: theme.colors[backgroundColor], }); diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/HDesign/src/components/FixedButton/FixedButton.style.ts index b4d94038c..069157413 100644 --- a/HDesign/src/components/FixedButton/FixedButton.style.ts +++ b/HDesign/src/components/FixedButton/FixedButton.style.ts @@ -47,7 +47,7 @@ export const deleteButtonStyle = (theme: Theme) => [ color: theme.colors.white, fontFamily: 'Pretendard', - fontSize: '1.25rem', + fontSize: '1rem', fontWeight: '700', lineHeight: '1', @@ -66,7 +66,7 @@ const getFixedButtonDefaultStyle = (theme: Theme) => display: 'flex', justifyContent: 'center', padding: '1rem 1.5rem', - borderRadius: '1.25rem', + borderRadius: '1rem', width: '100%', fontFamily: 'Pretendard', diff --git a/client/package-lock.json b/client/package-lock.json index 3a0f5e4ef..7d848fac2 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.77", + "haengdong-design": "^0.1.79", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -10137,10 +10137,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.77", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.77.tgz", - "integrity": "sha512-+M41hUpL2ilwBAlaeYSinfsHy2DAMHnTq0B3tRtccJ1EKzCU3GPK3rA4z3km3GFLlmE3aOErtOeRV/xp6Y2kKA==", - "dependencies": { + "version": "0.1.79", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.79.tgz", + "integrity": "sha512-J5uFXmX+1VMzdU+aMTl36hJYrjzreLNhrtLMSBrdHtjwEROsYddbbXDlHTTUWaj7TpDQ1n5jgsy39jlKYv2m7w==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", diff --git a/client/package.json b/client/package.json index 81ea29821..b6171fa31 100644 --- a/client/package.json +++ b/client/package.json @@ -68,7 +68,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.77", + "haengdong-design": "^0.1.79", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", From b9781cb252f0d02eddda5c0431783b0de705eba4 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:05:19 +0900 Subject: [PATCH 202/273] =?UTF-8?q?feat:=20=EB=B2=84=ED=8A=BC=20=EB=A1=9C?= =?UTF-8?q?=EB=94=A9=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=83=9D=EC=84=B1=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EC=97=90=20=EC=A0=81=EC=9A=A9=20(#476)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: 통일성 위해 디자인 수정 * chore: v0.1.78 배포 * chore: hdesign 0.1.78 적용 * chore: v0.1.79 배포 및 적용 * chore: lottie-react dependency 추가 * chore: json file 읽을 수 있도록 설정 * feat: button의 loading variants 추가 * chore: v0.1.80 배포 * chore: hdesign 신규 버전 적용 * feat: 행사 생성이 pending 상태이면 button isLoading으로 변경 * style: lint 적용 * chore: lottie-react import ignore 하도록 변경 * fix: lottie-react를 mocking하여 lottie가 렌더링 시 테스트가 실패하지 않도록 변경 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> --- HDesign/eslint.config.mjs | 2 + HDesign/package-lock.json | 157 +-- HDesign/package.json | 3 +- HDesign/src/assets/loadingAnimation.json | 1176 +++++++++++++++++ .../src/components/Button/Button.stories.tsx | 2 +- HDesign/src/components/Button/Button.style.ts | 7 + HDesign/src/components/Button/Button.tsx | 35 +- HDesign/src/components/Button/Button.type.ts | 2 +- .../FixedButton/FixedButton.stories.tsx | 2 +- .../FixedButton/FixedButton.style.ts | 7 + .../components/FixedButton/FixedButton.tsx | 18 +- HDesign/tsconfig.json | 1 + client/package-lock.json | 27 +- client/package.json | 2 +- client/src/hooks/useError/useError.test.tsx | 2 + client/src/hooks/useSetEventPasswordPage.ts | 4 +- client/src/hooks/useToast/useToast.test.tsx | 2 + .../CreateEventPage/SetEventPasswordPage.tsx | 7 +- 18 files changed, 1301 insertions(+), 155 deletions(-) create mode 100644 HDesign/src/assets/loadingAnimation.json diff --git a/HDesign/eslint.config.mjs b/HDesign/eslint.config.mjs index 96b3da00a..e025936a4 100644 --- a/HDesign/eslint.config.mjs +++ b/HDesign/eslint.config.mjs @@ -59,6 +59,8 @@ export default [ 'import/parsers': { '@typescript-eslint/parser': ['.ts', '.tsx'], }, + + 'import/ignore': ['lottie-react'], }, rules: { diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index c252ff81e..c25af9210 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,17 +1,18 @@ { "name": "haengdong-design", - "version": "0.1.79", + "version": "0.1.80", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.79" + "version": "0.1.80", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -4156,141 +4157,6 @@ "node": ">=10" } }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.6.tgz", - "integrity": "sha512-Fyl+8aH9O5rpx4O7r2KnsPpoi32iWoKOYKiipeTbGjQ/E95tNPxbmsz4yqE8Ovldcga60IPJ5OKQA3HWRiuzdw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.6.tgz", - "integrity": "sha512-2WxYTqFaOx48GKC2cbO1/IntA+w+kfCFy436Ij7qRqqtV/WAvTM9TC1OmiFbqq436rSot52qYmX8fkwdB5UcLQ==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.6.tgz", - "integrity": "sha512-TBEGMSe0LhvPe4S7E68c7VzgT3OMu4VTmBLS7B2aHv4v8uZO92Khpp7L0WqgYU1y5eMjk+XLDLi4kokiNHv/Hg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.6.tgz", - "integrity": "sha512-QI8QGL0HGT42tj7F1A+YAzhGkJjUcvvTfI1e2m704W0Enl2/UIK9v5D1zvQzYwusRyKuaQfbeBRYDh0NcLOGLg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.6.tgz", - "integrity": "sha512-61AYVzhjuNQAVIKKWOJu3H0/pFD28RYJGxnGg3YMhvRLRyuWNyY5Nyyj2WkKcz/ON+g38Arlz00NT1LDIViRLg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.6.tgz", - "integrity": "sha512-hQFznpfLK8XajfAAN9Cjs0w/aVmO7iu9VZvInyrTCRcPqxV5O+rvrhRxKvC1LRMZXr5M6JRSRtepp5w+TK4kAw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.6.tgz", - "integrity": "sha512-Aqsd9afykVMuekzjm4X4TDqwxmG4CrzoOSFe0hZrn9SMio72l5eAPnMtYoe5LsIqtjV8MNprLfXaNbjHjTegmA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.6.tgz", - "integrity": "sha512-9h0hYnOeRVNeQgHQTvD1Im67faNSSzBZ7Adtxyu9urNLfBTJilMllFd2QuGHlKW5+uaT6ZH7ZWDb+c/enx7Lcg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.6.tgz", - "integrity": "sha512-izeoB8glCSe6IIDQmrVm6bvR9muk9TeKgmtY7b6l1BwL4BFnTUk4dMmpbntT90bEVQn3JPCaPtUG4HfL8VuyuA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -9973,6 +9839,23 @@ "loose-envify": "cli.js" } }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", diff --git a/HDesign/package.json b/HDesign/package.json index 9013c10ec..1d78b6893 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.79", + "version": "0.1.80", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", @@ -60,6 +60,7 @@ "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" diff --git a/HDesign/src/assets/loadingAnimation.json b/HDesign/src/assets/loadingAnimation.json new file mode 100644 index 000000000..4f507a7ea --- /dev/null +++ b/HDesign/src/assets/loadingAnimation.json @@ -0,0 +1,1176 @@ +{ + "nm": "Main Scene", + "ddd": 0, + "h": 48, + "w": 128, + "meta": { + "g": "@lottiefiles/creator 1.24.1" + }, + "layers": [ + { + "ty": 0, + "nm": " Loading Dots", + "sr": 1, + "st": 0, + "op": 81, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 962.9629629629629, + 540.7407407407408 + ] + }, + "s": { + "a": 0, + "k": [ + 27, + 27 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 64.25999999999999, + 24.2 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + }, + "w": 1920, + "h": 1080, + "refId": "precomp_Loading Dots_139596b3-8049-4b90-9165-55e00cf10251", + "ind": 1 + } + ], + "v": "5.7.0", + "fr": 60, + "op": 81, + "ip": 0, + "assets": [ + { + "nm": "Loading Dots", + "id": "precomp_Loading Dots_139596b3-8049-4b90-9165-55e00cf10251", + "fr": 60, + "layers": [ + { + "ty": 4, + "nm": "Dot4", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 25 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 39 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 55 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1142, + 540, + 0 + ], + "t": 25 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1142, + 500, + 0 + ], + "t": 39 + }, + { + "s": [ + 1142, + 540, + 0 + ], + "t": 55 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 25 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 39 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 55 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 1 + }, + { + "ty": 4, + "nm": "Dot3", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 17 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 31 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 47 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1022, + 540, + 0 + ], + "t": 17 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1022, + 500, + 0 + ], + "t": 31 + }, + { + "s": [ + 1022, + 540, + 0 + ], + "t": 47 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 17 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 31 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 47 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 2 + }, + { + "ty": 4, + "nm": "Dot2", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 9 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 23 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 39 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 902, + 540, + 0 + ], + "t": 9 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 902, + 500, + 0 + ], + "t": 23 + }, + { + "s": [ + 902, + 540, + 0 + ], + "t": 39 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 9 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 23 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 39 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 3 + }, + { + "ty": 4, + "nm": "Dot1", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 0 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 14 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 30 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 782, + 540, + 0 + ], + "t": 0 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 782, + 500, + 0 + ], + "t": 14 + }, + { + "s": [ + 782, + 540, + 0 + ], + "t": 30 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 0 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 14 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 30 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 4 + } + ] + } + ] +} \ No newline at end of file diff --git a/HDesign/src/components/Button/Button.stories.tsx b/HDesign/src/components/Button/Button.stories.tsx index 3ba8a4129..64288bcb5 100644 --- a/HDesign/src/components/Button/Button.stories.tsx +++ b/HDesign/src/components/Button/Button.stories.tsx @@ -13,7 +13,7 @@ const meta = { variants: { description: '', control: {type: 'select'}, - options: ['', 'primary', 'secondary', 'tertiary', 'destructive'], + options: ['', 'primary', 'secondary', 'tertiary', 'destructive', 'loading'], }, size: { description: '', diff --git a/HDesign/src/components/Button/Button.style.ts b/HDesign/src/components/Button/Button.style.ts index 295fbc50c..24c46ec5b 100644 --- a/HDesign/src/components/Button/Button.style.ts +++ b/HDesign/src/components/Button/Button.style.ts @@ -100,6 +100,13 @@ const getButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => { }), getHoverAndActiveBackground(theme.colors.error), ], + loading: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], }; return style[variants]; diff --git a/HDesign/src/components/Button/Button.tsx b/HDesign/src/components/Button/Button.tsx index ca78350a1..f0277590b 100644 --- a/HDesign/src/components/Button/Button.tsx +++ b/HDesign/src/components/Button/Button.tsx @@ -1,18 +1,47 @@ /** @jsxImportSource @emotion/react */ import React, {forwardRef} from 'react'; +import Lottie from 'lottie-react'; import {buttonStyle} from '@components/Button/Button.style'; -import {ButtonProps} from '@components/Button/Button.type'; +import {ButtonProps, ButtonSize} from '@components/Button/Button.type'; + +import loadingAnimation from '@assets/loadingAnimation.json'; import {useTheme} from '@theme/HDesignProvider'; +const animationSize = (size: ButtonSize) => { + switch (size) { + case 'small': + return {width: 30, height: 12}; + + case 'large': + return {width: 50, height: 20}; + + default: + return {width: 40, height: 16}; + } +}; + export const Button: React.FC<ButtonProps> = forwardRef<HTMLButtonElement, ButtonProps>(function Button( - {variants = 'primary', size = 'medium', ...htmlProps}: ButtonProps, + {variants = 'primary', size = 'medium', disabled, children, ...htmlProps}: ButtonProps, ref, ) { const {theme} = useTheme(); - return <button css={buttonStyle({variants, size, theme})} ref={ref} {...htmlProps} />; + return ( + <button + css={buttonStyle({variants, size, theme})} + ref={ref} + disabled={variants === 'loading' ? true : disabled} + {...htmlProps} + > + {variants === 'loading' ? ( + <Lottie animationData={loadingAnimation} loop={true} style={animationSize(size)} /> + ) : ( + children + )} + </button> + ); }); export default Button; diff --git a/HDesign/src/components/Button/Button.type.ts b/HDesign/src/components/Button/Button.type.ts index 52da8a18d..a0402b1dc 100644 --- a/HDesign/src/components/Button/Button.type.ts +++ b/HDesign/src/components/Button/Button.type.ts @@ -1,7 +1,7 @@ import {Theme} from '@theme/theme.type'; export type ButtonSize = 'small' | 'medium' | 'large'; -export type ButtonVariants = 'primary' | 'secondary' | 'tertiary' | 'destructive'; +export type ButtonVariants = 'primary' | 'secondary' | 'tertiary' | 'destructive' | 'loading'; export interface ButtonStyleProps { variants?: ButtonVariants; diff --git a/HDesign/src/components/FixedButton/FixedButton.stories.tsx b/HDesign/src/components/FixedButton/FixedButton.stories.tsx index fb7fdc008..47485f851 100644 --- a/HDesign/src/components/FixedButton/FixedButton.stories.tsx +++ b/HDesign/src/components/FixedButton/FixedButton.stories.tsx @@ -12,7 +12,7 @@ const meta = { variants: { description: '', control: {type: 'select'}, - options: ['', 'primary', 'secondary', 'tertiary'], + options: ['', 'primary', 'secondary', 'tertiary', 'loading'], }, disabled: { description: '', diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/HDesign/src/components/FixedButton/FixedButton.style.ts index 069157413..2e774918d 100644 --- a/HDesign/src/components/FixedButton/FixedButton.style.ts +++ b/HDesign/src/components/FixedButton/FixedButton.style.ts @@ -114,6 +114,13 @@ const getFixedButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => }), getHoverAndActiveBackground(theme.colors.error), ], + loading: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], }; return style[variants]; diff --git a/HDesign/src/components/FixedButton/FixedButton.tsx b/HDesign/src/components/FixedButton/FixedButton.tsx index efbfe164d..4430016d6 100644 --- a/HDesign/src/components/FixedButton/FixedButton.tsx +++ b/HDesign/src/components/FixedButton/FixedButton.tsx @@ -1,5 +1,6 @@ /** @jsxImportSource @emotion/react */ import {forwardRef} from 'react'; +import Lottie from 'lottie-react'; import { fixedButtonContainerStyle, @@ -10,10 +11,12 @@ import {FixedButtonProps} from '@components/FixedButton/FixedButton.type'; import IconButton from '@components/IconButton/IconButton'; import Icon from '@components/Icon/Icon'; +import loadingAnimation from '@assets/loadingAnimation.json'; + import {useTheme} from '@theme/HDesignProvider'; export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElement, FixedButtonProps>(function Button( - {variants = 'primary', onDeleteClick, ...htmlProps}: FixedButtonProps, + {variants = 'primary', onDeleteClick, disabled, children, ...htmlProps}: FixedButtonProps, ref, ) { const {theme} = useTheme(); @@ -25,7 +28,18 @@ export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElem <Icon iconType="trash" /> </IconButton> )} - <button css={fixedButtonStyle({variants, theme})} ref={ref} {...htmlProps} /> + <button + css={fixedButtonStyle({variants, theme})} + ref={ref} + disabled={variants === 'loading' ? true : disabled} + {...htmlProps} + > + {variants === 'loading' ? ( + <Lottie animationData={loadingAnimation} loop={true} style={{width: 240, height: 20}} /> + ) : ( + children + )} + </button> </div> </div> ); diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json index 04b12a2a9..ca7b8b78f 100644 --- a/HDesign/tsconfig.json +++ b/HDesign/tsconfig.json @@ -9,6 +9,7 @@ "strict": true, "declaration": true, "declarationDir": "./dist", + "resolveJsonModule": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], diff --git a/client/package-lock.json b/client/package-lock.json index 7d848fac2..f932fe761 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.79", + "haengdong-design": "^0.1.80", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -10137,12 +10137,14 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.79", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.79.tgz", - "integrity": "sha512-J5uFXmX+1VMzdU+aMTl36hJYrjzreLNhrtLMSBrdHtjwEROsYddbbXDlHTTUWaj7TpDQ1n5jgsy39jlKYv2m7w==", "dependencies": { + "version": "0.1.80", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.80.tgz", + "integrity": "sha512-rqfuFKBcqXL6LuPt4iiiM+ZNHBV++hHVGLICiqMiN9mUcl+x3zgNxiAe/80sHPH0HsZsSbuKdkksUqwdX8adhg==", + "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -14233,6 +14235,23 @@ "loose-envify": "cli.js" } }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", diff --git a/client/package.json b/client/package.json index b6171fa31..cadaf7407 100644 --- a/client/package.json +++ b/client/package.json @@ -68,7 +68,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.79", + "haengdong-design": "^0.1.80", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/hooks/useError/useError.test.tsx b/client/src/hooks/useError/useError.test.tsx index 7c39d0e95..230c5889b 100644 --- a/client/src/hooks/useError/useError.test.tsx +++ b/client/src/hooks/useError/useError.test.tsx @@ -10,6 +10,8 @@ import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; import {ErrorInfo, ErrorProvider} from './ErrorProvider'; import {useError} from './useError'; +jest.mock('lottie-react', () => () => <div>Lottie Mock</div>); + describe('useError', () => { const initializeProvider = () => renderHook(() => useError(), { diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts index 3a97a587b..82ca72fb1 100644 --- a/client/src/hooks/useSetEventPasswordPage.ts +++ b/client/src/hooks/useSetEventPasswordPage.ts @@ -15,7 +15,7 @@ const useSetEventPasswordPage = () => { const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); const location = useLocation(); - const {mutate: postEvent} = usePostEvent(); + const {mutate: postEvent, isPending: isPostEventPending} = usePostEvent(); useEffect(() => { if (!location.state) { @@ -55,6 +55,6 @@ const useSetEventPasswordPage = () => { } }; - return {submitPassword, errorMessage, password, handleChange, canSubmit}; + return {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending}; }; export default useSetEventPasswordPage; diff --git a/client/src/hooks/useToast/useToast.test.tsx b/client/src/hooks/useToast/useToast.test.tsx index 6f9522a24..54906cea4 100644 --- a/client/src/hooks/useToast/useToast.test.tsx +++ b/client/src/hooks/useToast/useToast.test.tsx @@ -11,6 +11,8 @@ import {ErrorInfo, ErrorProvider} from '../../hooks/useError/ErrorProvider'; // import {ToastProvider} from './ToastProvider'; // 위 코드에 해당하는 ToastProvider 경로 +jest.mock('lottie-react', () => () => <div>Lottie Mock</div>); + // 테스트용 헬퍼 컴포넌트 const TestComponent = ({errorInfo}: {errorInfo: ErrorInfo}) => { const {setErrorInfo} = useError(); diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index f6e8dee28..2b73f2ff2 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -6,7 +6,8 @@ import RULE from '@constants/rule'; import {PASSWORD_LENGTH} from '@constants/password'; const SetEventPasswordPage = () => { - const {submitPassword, errorMessage, password, handleChange, canSubmit} = useSetEventPasswordPage(); + const {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending} = + useSetEventPasswordPage(); return ( <MainLayout backgroundColor="white"> @@ -29,7 +30,9 @@ const SetEventPasswordPage = () => { isError={!!errorMessage} autoFocus /> - <FixedButton disabled={!canSubmit}>행동 개시!</FixedButton> + <FixedButton variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> + 행동 개시! + </FixedButton> </form> </MainLayout> ); From 39eff114937796812dc1a7ad10e060107cb4e641 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:05:39 +0900 Subject: [PATCH 203/273] =?UTF-8?q?fix:=20=ED=96=89=EC=82=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=99=84=EB=A3=8C=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#478)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CompleteCreateEventPage.tsx | 39 ++----------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index f7549563f..13af31a8d 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -1,11 +1,5 @@ import {useLocation, useNavigate} from 'react-router-dom'; -import {Button, FixedButton, Flex, Input, MainLayout, Text, Title, TopNav} from 'haengdong-design'; -import {CopyToClipboard} from 'react-copy-to-clipboard'; -import {css} from '@emotion/react'; - -import {useToast} from '@hooks/useToast/useToast'; - -import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; +import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -16,41 +10,14 @@ const CompleteCreateEventPage = () => { const params = new URLSearchParams(location.search); const eventId = params.get('eventId'); - const {showToast} = useToast(); - - const homePageUrl = getEventPageUrlByEnvironment(eventId ?? '', 'home'); - return ( <MainLayout backgroundColor="white"> <TopNav /> <Title title="행사 개시" - description="행사가 성공적으로 개시됐어요 :) 행사 링크를 통해서 지출 내역 공유와 참여자 관리가 가능해요." + description={`행사가 성공적으로 개시됐어요 :) + 관리 페이지로 이동해서 정산을 시작할 수 있어요`} /> - <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem', margin: '0 1rem'})}> - <Flex flexDirection="column"> - <Text textColor="gray">링크가 없으면 페이지에 접근할 수 없어요.</Text> - <Text textColor="primary">관리를 위해서 행사 링크를 복사 후 보관해 주세요.</Text> - </Flex> - <Input value={homePageUrl} disabled /> - - <CopyToClipboard - text={homePageUrl} - onCopy={() => - showToast({ - showingTime: 3000, - message: '링크가 복사되었어요 :) \n링크를 절대 분실하지 마세요!', - type: 'confirm', - position: 'bottom', - bottom: '8rem', - }) - } - > - <Button size="large" variants="tertiary"> - 행사 링크 복사하기 - </Button> - </CopyToClipboard> - </div> <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>관리 페이지로 이동</FixedButton> </MainLayout> From 805d79252c5c9f0283e4b4b26fc55c5fc571e030 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:06:02 +0900 Subject: [PATCH 204/273] =?UTF-8?q?fix:=20placeholder=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20(#480)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SetInitialMemberListModal/SetInitialMemberListModal.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index 8c9ef26e0..f73f2616d 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -44,6 +44,7 @@ const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: Se <LabelGroupInput.Element key={`${index}`} elementKey={`${index}`} + placeholder="이름" type="text" value={value} isError={errorIndexList.includes(index)} From 3964287ad9f57ade8f71ab3030ee92f1f2c8d9c4 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:06:24 +0900 Subject: [PATCH 205/273] =?UTF-8?q?fix:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EA=B8=88=EC=95=A1=20=EB=B6=80=EB=B6=84=EC=97=90=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=EA=B0=80=20=EC=9E=85=EB=A0=A5=EB=90=98?= =?UTF-8?q?=EB=8D=98=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20(#491)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/StepList/BillStepItem.tsx | 2 +- client/src/pages/CreateEventPage/SetEventPasswordPage.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 16e40c6af..eff8e3125 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -108,7 +108,7 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ <EditableItem.Input placeholder="0" type="number" - value={billInput.price || ''} + value={billInput.price ?? null} onChange={e => handleChangeBillInput('price', e)} style={{textAlign: 'right'}} ></EditableItem.Input> diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 2b73f2ff2..2ebe7be50 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -23,7 +23,7 @@ const SetEventPasswordPage = () => { labelText="비밀번호" errorText={errorMessage} value={password} - type="secret" + type="number" maxLength={RULE.maxEventPasswordLength} placeholder="비밀번호" onChange={handleChange} From c578a1868fb4b4e50d416ff4c0a93060ea00884e Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:06:40 +0900 Subject: [PATCH 206/273] =?UTF-8?q?fix:=20dropdown=20animation=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20=EC=88=98=EC=A0=95=20(#493)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/StepList/BillStepItem.tsx | 14 ++++++-------- .../src/components/StepList/MemberStepItem.tsx | 14 ++++++-------- .../pages/EventPage/AdminPage/AdminPage.tsx | 18 ++++++++---------- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index eff8e3125..3ad155dfb 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -117,14 +117,12 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ </EditableItem> )} </DragHandleItemContainer> - {isOpenMemberListInBillStep && ( - <MemberListInBillStep - stepName={step.stepName} - memberList={memberList} - isOpenBottomSheet={isOpenMemberListInBillStep} - setIsOpenBottomSheet={setIsOpenMemberListInBillStep} - /> - )} + <MemberListInBillStep + stepName={step.stepName} + memberList={memberList} + isOpenBottomSheet={isOpenMemberListInBillStep} + setIsOpenBottomSheet={setIsOpenMemberListInBillStep} + /> </> ); }; diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx index a9abaea1a..07793a71d 100644 --- a/client/src/components/StepList/MemberStepItem.tsx +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -23,14 +23,12 @@ const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, prefix={`${step.actions.map(({name}) => name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} onClick={() => setIsOpenBottomSheet(prev => !prev)} /> - {isOpenBottomSheet && isAdmin && ( - <DeleteMemberActionModal - memberActionType={step.type} - memberActionList={step.actions} - isBottomSheetOpened={isOpenBottomSheet} - setIsBottomSheetOpened={setIsOpenBottomSheet} - /> - )} + <DeleteMemberActionModal + memberActionType={step.type} + memberActionList={step.actions} + isBottomSheetOpened={isOpenBottomSheet && isAdmin} + setIsBottomSheetOpened={setIsOpenBottomSheet} + /> </> ); }; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 65e6f42cc..6e0e265e2 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -3,7 +3,7 @@ import {Title, FixedButton, ListButton, Button} from 'haengdong-design'; import {useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; -import {ModalBasedOnMemberCount} from '@components/Modal/index'; +import {ModalBasedOnMemberCount, SetAllMemberListModal} from '@components/Modal/index'; import useRequestGetAllMemberList from '@hooks/queries/useRequestGetAllMemberList'; import useRequestPostAuthenticate from '@hooks/queries/useRequestPostAuthentication'; @@ -73,15 +73,13 @@ const AdminPage = () => { </Button> </div> )} - {isOpenFixedButtonBottomSheet && ( - <ModalBasedOnMemberCount - allMemberList={allMemberList} - setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} - isOpenBottomSheet={isOpenFixedButtonBottomSheet} - isOpenAllMemberListButton={isOpenAllMemberListButton} - setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} - /> - )} + <ModalBasedOnMemberCount + allMemberList={allMemberList} + setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} + isOpenBottomSheet={isOpenFixedButtonBottomSheet} + isOpenAllMemberListButton={isOpenAllMemberListButton} + setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} + /> </section> </> ); From ebc2bc262282339b8828ab0ddadf6079e21ee1ad Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:07:09 +0900 Subject: [PATCH 207/273] =?UTF-8?q?chore:=20React-Query=20devtools=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20=EC=84=A4=EC=A0=95=20(#463)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: devtools 설치 * chore: stale time, gctime 셋팅 임시로 1분 설정 --- client/package-lock.json | 28 ++++++++++++++++++++++++++++ client/package.json | 1 + client/src/App.tsx | 11 ++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/client/package-lock.json b/client/package-lock.json index f932fe761..1d6cfaa28 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -26,6 +26,7 @@ "@jest/types": "^29.6.3", "@sentry/webpack-plugin": "^2.22.0", "@svgr/webpack": "^8.1.0", + "@tanstack/react-query-devtools": "^5.52.0", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", @@ -4335,6 +4336,16 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@tanstack/query-devtools": { + "version": "5.51.16", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.51.16.tgz", + "integrity": "sha512-ajwuq4WnkNCMj/Hy3KR8d3RtZ6PSKc1dD2vs2T408MdjgKzQ3klVoL6zDgVO7X+5jlb5zfgcO3thh4ojPhfIaw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tanstack/react-query": { "version": "5.51.23", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.23.tgz", @@ -4350,6 +4361,23 @@ "react": "^18.0.0" } }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.52.0.tgz", + "integrity": "sha512-oq8bDxMQ95edOlcWFaGsnSFzH11s06M1uiNiLtgsm+UG6Y5w+K6BJp0GeXN8q7sBNVBw/WPyeFdUH8rj9RT2Aw==", + "dev": true, + "dependencies": { + "@tanstack/query-devtools": "5.51.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.52.0", + "react": "^18 || ^19" + } + }, "node_modules/@testing-library/dom": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", diff --git a/client/package.json b/client/package.json index cadaf7407..4f01260c2 100644 --- a/client/package.json +++ b/client/package.json @@ -23,6 +23,7 @@ "@jest/types": "^29.6.3", "@sentry/webpack-plugin": "^2.22.0", "@svgr/webpack": "^8.1.0", + "@tanstack/react-query-devtools": "^5.52.0", "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.4.8", "@testing-library/react": "^16.0.0", diff --git a/client/src/App.tsx b/client/src/App.tsx index 3a8b7f0f2..7356423d2 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -2,6 +2,7 @@ import {Outlet} from 'react-router-dom'; import {HDesignProvider} from 'haengdong-design'; import {Global} from '@emotion/react'; import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; +import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; import {ToastProvider} from '@hooks/useToast/ToastProvider'; import {ErrorProvider} from '@hooks/useError/ErrorProvider'; @@ -9,12 +10,20 @@ import {ErrorProvider} from '@hooks/useError/ErrorProvider'; import {GlobalStyle} from './GlobalStyle'; import UnhandledErrorBoundary from './UnhandledErrorBoundary'; -const queryClient = new QueryClient(); +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 1000 * 60, // 1 minute + gcTime: 1000 * 60, // 1 minute + }, + }, +}); const App: React.FC = () => { return ( <HDesignProvider> <QueryClientProvider client={queryClient}> + <ReactQueryDevtools initialIsOpen={false} /> <UnhandledErrorBoundary> <Global styles={GlobalStyle} /> <ErrorProvider> From 56ba99bea6ae15d7eb8deeec732b6d14d72c4fc6 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:07:32 +0900 Subject: [PATCH 208/273] =?UTF-8?q?chore:=20amplitude=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=20(#335)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/index.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/index.html b/client/index.html index 97edcf3ca..1912ca40f 100644 --- a/client/index.html +++ b/client/index.html @@ -4,6 +4,15 @@ <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" /> <meta content="upgrade-insecure-requests" /> + <script src="https://cdn.amplitude.com/libs/analytics-browser-2.9.3-min.js.gz"></script> + <script src="https://cdn.amplitude.com/libs/plugin-session-replay-browser-1.6.8-min.js.gz"></script> + <script src="https://cdn.amplitude.com/libs/plugin-autocapture-browser-1.0.0-min.js.gz"></script> + <script> + window.amplitude.add(window.sessionReplay.plugin({sampleRate: 1})).promise.then(function () { + window.amplitude.add(window.amplitudeAutocapturePlugin.plugin()); + window.amplitude.init('<%= process.env.AMPLITUDE_KEY %>'); + }); + </script> <title>행동대장 From f76dbdf2116e3f717fb831d0ca56bbe475afdb91 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:40:11 +0900 Subject: [PATCH 209/273] =?UTF-8?q?feat:=20react-query=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EB=8A=94=20error=20handling=20=EC=A0=81=EC=9A=A9=20(#?= =?UTF-8?q?415)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 디자인시스템 버전 적용 * rename: 파일 이름 변경 * fix: 사용하지 않는 Error 처리 로직 삭제 * feat: 전역 에러 상태 생성 * fix: 바뀐 파일 이름 적용 * fix: ToastProvider 내에서 에러 처리 로직 제거 * refactor: AppErrorBoundary 및 QueryClientBoundary를 통한 에러 처리 * fix: 사용하지 않는 코드 임시적으로 주석 처리 TODO: 테스트 코드 역할 위임 * mover: AppErrorBoundary, QueryClientBoundary 코드 위치 변경 * fix: test 코드 변경 * chore: jest path alias 적용 * test: AppErrorBoundary 테스트코드 작성 * remove: 사용하지 않는 코드 삭제 * fix: 사용하지 않는 코드 주석처리 * fix: AppErrorBoundary, QueryClientBoundary 로직 수정 * test: AppErrorBoundary test코드 작성 * style: lint 적용 * feat: App에 ErrorBoundary 추가 * feat: UnhandledErrorBoundary 컴포넌트 구현 * feat: 에러를 구독하며 핸들링되는 에러면 토스트, 핸들링 불가능한 에러면 에러 바운더리를 띄우도록 하는 캐처 구현 * feat: 에러 페이지에 메일 추가 * feat: errorInfo를 안에서 구현하는 것이 아닌 구현된 것을 인자로 받도록 수정 * chore: 파일 위치 수정에 따라 import 경로 수정 * chore: 불필요해진 파일 제거 * chore: 개행 추가 * feat: ErrorCatcher에 대한 테스트 코드 작성 * feat: Toast의 showingTime 을 옵셔널로 수정 * chore: 없어진 컴포넌트를 renderHook에서 제거 * refactor: return문이 반복되는 부분을 리펙터링 * feat: useToast에 대한 테스트코드 작성 * chore: 사용하지 않는 파일 제거 * chore: 불필요한 파일이 커버리지에 뜨지 않도록 ignore에 추가 * rename: 파일명 오타 수정 * chore: import 경로 수정 * chore: 병힙 * chore: 라이브러리 오류로 인해 테스트 통과가 안되므로 디자인 시스템 라이브러리 다운그레이드 --------- Co-authored-by: pakxe --- client/jest.config.ts | 3 + client/package-lock.json | 26 +-- client/package.json | 2 +- client/src/App.tsx | 34 ++-- client/src/apis/fetcher.ts | 2 +- .../AppErrorBoundary/ErrorCatcher.test.tsx | 92 +++++++++++ .../AppErrorBoundary/ErrorCatcher.tsx | 62 +++++++ .../QueryClientBoundary.tsx | 24 +++ client/src/components/Toast/Toast.tsx | 2 +- client/src/components/Toast/Toast.type.ts | 2 +- client/src/hooks/useAuth/useAuth.test.tsx | 147 ----------------- client/src/hooks/useAuth/useAuth.tsx | 21 --- .../useDeleteMemberAction.test.tsx | 28 ++-- client/src/hooks/useError/ErrorProvider.tsx | 69 -------- client/src/hooks/useError/useError.test.tsx | 123 -------------- client/src/hooks/useError/useError.tsx | 12 -- client/src/hooks/useEvent/useEvent.test.tsx | 79 --------- client/src/hooks/useEvent/useEvent.tsx | 16 -- client/src/hooks/useFetch/useFetch.test.tsx | 155 ------------------ client/src/hooks/useFetch/useFetch.ts | 63 ------- .../useMemberReportListInAction.test.tsx | 5 +- .../useSearchMemberReportList.test.tsx | 27 ++- ...SetEventName.ts => useSetEventNamePage.ts} | 4 +- client/src/hooks/useToast/ToastProvider.tsx | 31 +--- client/src/hooks/useToast/useToast.test.tsx | 135 +++++++-------- .../CreateEventPage/SetEventNamePage.tsx | 6 +- client/src/pages/ErrorPage/ErrorPage.tsx | 6 +- client/src/store/appErrorStore.ts | 14 ++ client/src/types/fetchErrorType.ts | 2 +- client/src/utils/captureError.ts | 22 +-- client/src/utils/sendLogToSentry.ts | 2 +- 31 files changed, 319 insertions(+), 897 deletions(-) create mode 100644 client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx create mode 100644 client/src/components/AppErrorBoundary/ErrorCatcher.tsx create mode 100644 client/src/components/QueryClientBoundary/QueryClientBoundary.tsx delete mode 100644 client/src/hooks/useAuth/useAuth.test.tsx delete mode 100644 client/src/hooks/useAuth/useAuth.tsx delete mode 100644 client/src/hooks/useError/ErrorProvider.tsx delete mode 100644 client/src/hooks/useError/useError.test.tsx delete mode 100644 client/src/hooks/useError/useError.tsx delete mode 100644 client/src/hooks/useEvent/useEvent.test.tsx delete mode 100644 client/src/hooks/useEvent/useEvent.tsx delete mode 100644 client/src/hooks/useFetch/useFetch.test.tsx delete mode 100644 client/src/hooks/useFetch/useFetch.ts rename client/src/hooks/{useSetEventName.ts => useSetEventNamePage.ts} (91%) create mode 100644 client/src/store/appErrorStore.ts diff --git a/client/jest.config.ts b/client/jest.config.ts index 4bb1dbd3e..a75677a5a 100644 --- a/client/jest.config.ts +++ b/client/jest.config.ts @@ -19,6 +19,8 @@ const config: Config = { '/src/errors/', '/src/components/', '/src/store/', + '/src/pages/', + '/src/hooks/queries', ], verbose: true, @@ -29,6 +31,7 @@ const config: Config = { '@/(.*)$': '/src/$1', // path alias를 적용하기 위함 '^@apis/(.*)$': '/src/apis/$1', '^@constants/(.*)$': '/src/constants/$1', + '^@components/(.*)$': '/src/components/$1', '^@hooks/(.*)$': '/src/hooks/$1', '^@utils/(.*)$': '/src/utils/$1', '^@pages/(.*)$': '/src/pages/$1', diff --git a/client/package-lock.json b/client/package-lock.json index 1d6cfaa28..d86774ea2 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.80", + "haengdong-design": "^0.1.79", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -10165,14 +10165,13 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.80.tgz", - "integrity": "sha512-rqfuFKBcqXL6LuPt4iiiM+ZNHBV++hHVGLICiqMiN9mUcl+x3zgNxiAe/80sHPH0HsZsSbuKdkksUqwdX8adhg==", + "version": "0.1.79", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.79.tgz", + "integrity": "sha512-J5uFXmX+1VMzdU+aMTl36hJYrjzreLNhrtLMSBrdHtjwEROsYddbbXDlHTTUWaj7TpDQ1n5jgsy39jlKYv2m7w==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", - "lottie-react": "^2.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -14263,23 +14262,6 @@ "loose-envify": "cli.js" } }, - "node_modules/lottie-react": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", - "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", - "dependencies": { - "lottie-web": "^5.10.2" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/lottie-web": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", - "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" - }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", diff --git a/client/package.json b/client/package.json index 4f01260c2..d4297e7ba 100644 --- a/client/package.json +++ b/client/package.json @@ -69,7 +69,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.80", + "haengdong-design": "^0.1.79", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/App.tsx b/client/src/App.tsx index 7356423d2..4e9ce39e1 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,39 +1,29 @@ import {Outlet} from 'react-router-dom'; import {HDesignProvider} from 'haengdong-design'; import {Global} from '@emotion/react'; -import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; import {ToastProvider} from '@hooks/useToast/ToastProvider'; -import {ErrorProvider} from '@hooks/useError/ErrorProvider'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import ErrorCatcher from '@components/AppErrorBoundary/ErrorCatcher'; import {GlobalStyle} from './GlobalStyle'; import UnhandledErrorBoundary from './UnhandledErrorBoundary'; -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - staleTime: 1000 * 60, // 1 minute - gcTime: 1000 * 60, // 1 minute - }, - }, -}); - const App: React.FC = () => { return ( - - - - - - {/* */} - + + + + + + - - - - + + + + ); }; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index e87e3d395..2e1c2d067 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -1,4 +1,4 @@ -import {ErrorInfo} from '@hooks/useError/ErrorProvider'; +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; import objectToQueryString from '@utils/objectToQueryString'; diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx new file mode 100644 index 000000000..8d7946b8a --- /dev/null +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx @@ -0,0 +1,92 @@ +import {render, screen, waitFor} from '@testing-library/react'; +import {act, ReactNode} from 'react'; +import {MemoryRouter} from 'react-router-dom'; +import {HDesignProvider} from 'haengdong-design'; + +import FetchError from '@errors/FetchError'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; + +import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; + +import ErrorCatcher from './ErrorCatcher'; + +// 테스트용 헬퍼 컴포넌트 +const TestComponent = ({triggerError}: {triggerError: () => void}) => { + return ; +}; + +const setup = (ui: ReactNode) => + render( + + + + + {ui} + + + + , + ); + +describe('ErrorCatcher', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: jest.fn(), + })); + + it('핸들링 가능한 에러인 경우 토스트가 표시된다.', async () => { + const errorCode = 'EVENT_NOT_FOUND'; + const error = new FetchError({ + errorInfo: {errorCode, message: '서버의 에러메세지'}, + name: errorCode, + message: '에러메세지', + status: 200, + endpoint: '', + method: 'GET', + requestBody: '', + }); + + const {updateAppError} = useAppErrorStore.getState(); + + setup( updateAppError(error)} />); + + act(() => { + screen.getByText('Trigger Error').click(); + }); + + const errorMessage = SERVER_ERROR_MESSAGES[errorCode]; + + await waitFor(() => { + expect(screen.getByText(errorMessage)).toBeInTheDocument(); + }); + }); + + it('핸들링 불가능한 에러인 경우 에러 바운더리가 표시된다.', async () => { + const errorCode = '모르겠는 에러'; + const error = new FetchError({ + errorInfo: {errorCode, message: '모르겠는 에러메세지'}, + name: errorCode, + message: '에러메세지', + status: 400, + endpoint: '', + method: 'GET', + requestBody: '', + }); + + const {updateAppError} = useAppErrorStore.getState(); + + setup( updateAppError(error)} />); + + act(() => { + screen.getByText('Trigger Error').click(); + }); + + await waitFor(() => { + expect(screen.getByText('알 수 없는 오류입니다.')).toBeInTheDocument(); + }); + }); +}); diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx new file mode 100644 index 000000000..dde5f3d64 --- /dev/null +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx @@ -0,0 +1,62 @@ +import {useEffect} from 'react'; + +import FetchError from '@errors/FetchError'; +import {useToast} from '@hooks/useToast/useToast'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +import {captureError} from '@utils/captureError'; + +import {SERVER_ERROR_MESSAGES, UNKNOWN_ERROR} from '@constants/errorMessage'; + +export type ErrorInfo = { + errorCode: string; + message: string; +}; + +const convertAppErrorToErrorInfo = (appError: Error) => { + if (appError instanceof Error) { + const errorInfo = + appError instanceof FetchError ? appError.errorInfo : {errorCode: appError.name, message: appError.message}; + + return errorInfo; + } else { + const errorInfo = {errorCode: UNKNOWN_ERROR, message: JSON.stringify(appError)}; + + return errorInfo; + } +}; + +const isUnhandledError = (errorInfo: ErrorInfo) => { + if (errorInfo.errorCode === 'INTERNAL_SERVER_ERROR') return true; + + return SERVER_ERROR_MESSAGES[errorInfo.errorCode] === undefined; +}; + +const ErrorCatcher = ({children}: React.PropsWithChildren) => { + const {appError} = useAppErrorStore(); + const {showToast} = useToast(); + + useEffect(() => { + if (appError) { + const errorInfo = convertAppErrorToErrorInfo(appError); + captureError(appError, errorInfo); + + if (!isUnhandledError(errorInfo)) { + showToast({ + showingTime: 3000, + message: SERVER_ERROR_MESSAGES[errorInfo.errorCode], + type: 'error', + position: 'bottom', + bottom: '8rem', + }); + } else { + throw appError; + } + } + }, [appError]); + + return children; +}; + +export default ErrorCatcher; diff --git a/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx new file mode 100644 index 000000000..aeec24c3a --- /dev/null +++ b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx @@ -0,0 +1,24 @@ +import {MutationCache, QueryCache, QueryClient, QueryClientProvider} from '@tanstack/react-query'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +const QueryClientBoundary = ({children}: React.PropsWithChildren) => { + const {updateAppError} = useAppErrorStore(); + + const queryClient = new QueryClient({ + queryCache: new QueryCache({ + onError: (error: Error) => { + updateAppError(error); + }, + }), + mutationCache: new MutationCache({ + onError: (error: Error) => { + updateAppError(error); + }, + }), + }); + + return {children}; +}; + +export default QueryClientBoundary; diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx index edb17400d..5bf44d6fb 100644 --- a/client/src/components/Toast/Toast.tsx +++ b/client/src/components/Toast/Toast.tsx @@ -19,7 +19,7 @@ const Toast = ({ bottom = '0px', isClickToClose = true, position = 'bottom', - showingTime, + showingTime = 3000, message, onUndo, onClose, diff --git a/client/src/components/Toast/Toast.type.ts b/client/src/components/Toast/Toast.type.ts index 31ec64e3d..20b92c0db 100644 --- a/client/src/components/Toast/Toast.type.ts +++ b/client/src/components/Toast/Toast.type.ts @@ -12,7 +12,7 @@ export interface ToastOptionProps { onUndo?: () => void; isClickToClose?: boolean; onClose?: () => void; - showingTime: number; + showingTime?: number; } export interface ToastRequiredProps { diff --git a/client/src/hooks/useAuth/useAuth.test.tsx b/client/src/hooks/useAuth/useAuth.test.tsx deleted file mode 100644 index ab520543f..000000000 --- a/client/src/hooks/useAuth/useAuth.test.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import {renderHook, waitFor} from '@testing-library/react'; -import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; -import {act} from 'react'; -import {MemoryRouter} from 'react-router-dom'; - -import {useError} from '@hooks/useError/useError'; - -import {PASSWORD_LENGTH} from '@constants/password'; - -import {VALID_PASSWORD_FOR_TEST, VALID_TOKEN_FOR_TEST} from '@mocks/validValueForTest'; - -import {ErrorProvider} from '../useError/ErrorProvider'; - -import useAuth from './useAuth'; - -describe('useAuth', () => { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: 0, - }, - }, - }); - const initializeProvider = () => - renderHook( - () => { - return {errorResult: useError(), authResult: useAuth()}; - }, - { - wrapper: ({children}) => ( - - - {children} - - - ), - }, - ); - - describe('auth', () => { - it('쿠키에 토큰이 담겨있지 않다면 인증이 실패한다', async () => { - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.authResult.checkAuthentication()); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('TOKEN_NOT_FOUND'); - }); - }); - - it('쿠키에 담겨있는 토큰이 올바르다면 인증에 성공한다', async () => { - document.cookie = `eventToken=${VALID_TOKEN_FOR_TEST}`; - - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.authResult.checkAuthentication()); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo).toBe(null); - }); - }); - - it('쿠키에 담겨있는 토큰이 유효하지 않다면 인증에 실패한다.', async () => { - document.cookie = 'eventToken=fake-token'; - - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.authResult.checkAuthentication()); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('TOKEN_INVALID'); - }); - }); - - it('쿠키에 담겨있는 토큰이 만료되었다면 인증에 실패한다.', async () => { - document.cookie = 'eventToken=expired-token'; - - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.authResult.checkAuthentication()); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('TOKEN_EXPIRED'); - }); - }); - - it('쿠키에 담겨있는 토큰이 forbidden이라면 인증에 실패한다.', async () => { - document.cookie = 'eventToken=forbidden-token'; - - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.authResult.checkAuthentication()); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('FORBIDDEN'); - }); - }); - }); - - describe('login', () => { - it('비밀 번호가 올바르다면 로그인이 성공한다.', async () => { - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.authResult.loginUser({password: String(VALID_PASSWORD_FOR_TEST)})); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo).toBe(null); - }); - }); - - it(`비밀 번호가 ${PASSWORD_LENGTH}자리가 아니라면 로그인에 실패한다.`, async () => { - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.authResult.loginUser({password: '111'})); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('EVENT_PASSWORD_FORMAT_INVALID'); - }); - }); - - it('비밀 번호가 틀렸다면 로그인에 실패한다.', async () => { - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.authResult.loginUser({password: '9999'})); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('PASSWORD_INVALID'); - }); - }); - }); -}); diff --git a/client/src/hooks/useAuth/useAuth.tsx b/client/src/hooks/useAuth/useAuth.tsx deleted file mode 100644 index a294f6ad8..000000000 --- a/client/src/hooks/useAuth/useAuth.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import {RequestToken, requestPostAuthentication, requestPostToken} from '@apis/request/auth'; -import {useFetch} from '@hooks/useFetch/useFetch'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -const useAuth = () => { - const {fetch} = useFetch(); - const eventId = getEventIdByUrl(); - - const checkAuthentication = async () => { - return await fetch({queryFunction: () => requestPostAuthentication({eventId})}); - }; - - const loginUser = async ({password}: RequestToken) => { - return await fetch({queryFunction: () => requestPostToken({eventId, password})}); - }; - - return {checkAuthentication, loginUser}; -}; - -export default useAuth; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx index 20b49b096..38836f677 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -1,11 +1,13 @@ import {renderHook, waitFor} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; import {act} from 'react'; -import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; +import {HDesignProvider} from 'haengdong-design'; import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; -import {ErrorProvider} from '@hooks/useError/ErrorProvider'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; import stepListJson from '@mocks/stepList.json'; import invalidMemberStepListJson from '@mocks/invalidMemberStepList.json'; @@ -22,14 +24,6 @@ for (let i = 0; i < stepListMockData.length; i++) { } describe('useDeleteMemberAction', () => { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: 0, - }, - }, - }); - const initializeProvider = (list: MemberAction[] = memberActionList) => renderHook( () => { @@ -45,11 +39,15 @@ describe('useDeleteMemberAction', () => { }, { wrapper: ({children}) => ( - - - {children} - - + + + + + {children} + + + + ), }, ); diff --git a/client/src/hooks/useError/ErrorProvider.tsx b/client/src/hooks/useError/ErrorProvider.tsx deleted file mode 100644 index e1466cf4c..000000000 --- a/client/src/hooks/useError/ErrorProvider.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import {createContext, useState, useEffect, ReactNode} from 'react'; - -import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; - -// 에러 컨텍스트 생성 -export interface ErrorContextType { - clientErrorMessage: string; - setErrorInfo: (error: ErrorInfo) => void; - clearError: (ms?: number) => void; - errorInfo: ErrorInfo | null; -} - -export const ErrorContext = createContext(undefined); - -// 에러 컨텍스트를 제공하는 프로바이더 컴포넌트 -interface ErrorProviderProps { - children: ReactNode; - callback?: (message: string) => void; -} - -export type ErrorInfo = { - errorCode: string; - message: string; -}; - -export const ErrorProvider = ({children, callback}: ErrorProviderProps) => { - const [clientErrorMessage, setClientErrorMessage] = useState(''); - const [errorInfo, setErrorState] = useState(null); - - useEffect(() => { - if (errorInfo) { - if (isUnhandledError(errorInfo.errorCode)) { - // 에러바운더리로 보내기 - - throw errorInfo; - } - - const message = SERVER_ERROR_MESSAGES[errorInfo.errorCode]; - setClientErrorMessage(message); - // callback(message); - } - }, [errorInfo, callback]); - - const setErrorInfo = (error: ErrorInfo) => { - setClientErrorMessage(''); - setErrorState(error); - }; - - const clearError = (ms: number = 0) => { - if (errorInfo === null) return; - - setTimeout(() => { - setClientErrorMessage(''); - setErrorState(null); - }, ms); - }; - - return ( - - {children} - - ); -}; - -const isUnhandledError = (errorCode: string) => { - if (errorCode === 'INTERNAL_SERVER_ERROR') return true; - - return SERVER_ERROR_MESSAGES[errorCode] === undefined; -}; diff --git a/client/src/hooks/useError/useError.test.tsx b/client/src/hooks/useError/useError.test.tsx deleted file mode 100644 index 230c5889b..000000000 --- a/client/src/hooks/useError/useError.test.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import {renderHook, waitFor} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; -import {act} from 'react'; -import {HDesignProvider} from 'haengdong-design'; - -import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; - -import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; - -import {ErrorInfo, ErrorProvider} from './ErrorProvider'; -import {useError} from './useError'; - -jest.mock('lottie-react', () => () =>
Lottie Mock
); - -describe('useError', () => { - const initializeProvider = () => - renderHook(() => useError(), { - wrapper: ({children}) => ( - - - - {children} - - - - ), - }); - - /** - * useError, ErrorProvider, UnhandledErrorBoundary에서 사용되는 `핸들링 가능한 에러`의 정의 - * - * : 서버에서 미리 정의한 에러 코드와 에러 메세지를 던져주는 경우 이를 `핸들링 가능한 에러`로 합니다. - * 다만 예외적으로 INTERNAL_SERVER_ERROR는 핸들링 `불가능`한 에러로 합니다. - */ - const errorCode = 'EVENT_NOT_FOUND'; - const errorInfo: ErrorInfo = {errorCode, message: '메세지입니다.'}; - const expectedClientErrorMessage = SERVER_ERROR_MESSAGES[errorCode]; - - describe('저장된 에러를 초기화한다.', () => { - it('에러 초기화 함수에 인자를 넘겨주지 않은 경우 바로 에러를 초기화한다.', async () => { - const {result} = initializeProvider(); - - await act(async () => result.current.setErrorInfo(errorInfo)); - - // 에러 메세지가 세팅되기 까지 대기 (없어도 통과하나 제대로 값이 들어간 후 초기화됨을 확인하기 위함) - await waitFor(() => { - expect(result.current.clientErrorMessage).toEqual(expectedClientErrorMessage); - }); - - await act(async () => result.current.clearError()); - - await waitFor(() => expect(result.current.errorInfo).toBe(null)); - }); - - it('저장된 에러가 없는데 초기화 함수를 호출할 경우 그냥 종료한다.', async () => { - const {result} = initializeProvider(); - - await act(async () => result.current.clearError()); - - await waitFor(() => expect(result.current.errorInfo).toBe(null)); - }); - }); - - describe('핸들링 가능한 에러', () => { - it('핸들링 가능한 에러인 경우 에러 메세지를 미리 정의된 에러 메세지로 세팅한다.', async () => { - const {result} = initializeProvider(); - - await act(async () => result.current.setErrorInfo(errorInfo)); - - await waitFor(() => expect(result.current.clientErrorMessage).toEqual(expectedClientErrorMessage)); - }); - }); - - describe('핸들링 불가능한 에러', () => { - it('에러 코드가 INTERNAL_SERVER_ERROR인 경우 핸들링 불가능한 에러로 판단하고 에러를 외부로 던진다.', async () => { - const {result} = initializeProvider(); - const errorCode = 'INTERNAL_SERVER_ERROR'; - const errorInfo: ErrorInfo = {errorCode, message: '서버 에러입니다.'}; - - await act(async () => { - try { - result.current.setErrorInfo(errorInfo); - } catch (error) { - expect(error).toBe(errorInfo); - } - }); - }); - - it('에러 코드가 UNHANDLED인 경우 핸들링 불가능한 에러로 판단하고 에러를 외부로 던진다.', async () => { - const {result} = initializeProvider(); - const errorCode = 'UNHANDLED'; - const errorInfo: ErrorInfo = {errorCode, message: '알 수 없는 에러입니다.'}; - - await act(async () => { - try { - result.current.setErrorInfo(errorInfo); - } catch (error) { - expect(error).toBe(errorInfo); - } - }); - }); - - it('에러 코드에 대응하는 에러메세지가 없는 에러인 경우 핸들링 불가능한 에러로 판단하고 에러를 외부로 던진다.', async () => { - const {result} = initializeProvider(); - const errorCode = 'something strange error...'; - const errorInfo: ErrorInfo = {errorCode, message: '정말 모르겠다.'}; - - await act(async () => { - try { - result.current.setErrorInfo(errorInfo); - } catch (error) { - expect(error).toBe(errorInfo); - } - }); - }); - }); - - it('Provider없이 useError를 사용할 경우 에러를 던진다.', () => { - expect(() => { - const _ = renderHook(() => useError()); - }).toThrow('useError must be used within an ErrorProvider'); - }); -}); diff --git a/client/src/hooks/useError/useError.tsx b/client/src/hooks/useError/useError.tsx deleted file mode 100644 index ee7176233..000000000 --- a/client/src/hooks/useError/useError.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import {useContext} from 'react'; - -import {ErrorContext, ErrorContextType} from './ErrorProvider'; - -// 에러 컨텍스트를 사용하는 커스텀 훅 -export const useError = (): ErrorContextType => { - const context = useContext(ErrorContext); - if (!context) { - throw new Error('useError must be used within an ErrorProvider'); - } - return context; -}; diff --git a/client/src/hooks/useEvent/useEvent.test.tsx b/client/src/hooks/useEvent/useEvent.test.tsx deleted file mode 100644 index c636d49f8..000000000 --- a/client/src/hooks/useEvent/useEvent.test.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import {renderHook} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; -import {act} from 'react'; -import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; - -import {useError} from '@hooks/useError/useError'; - -import {PASSWORD_LENGTH} from '@constants/password'; - -import {VALID_PASSWORD_FOR_TEST} from '@mocks/validValueForTest'; -import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; - -import {ErrorProvider} from '../useError/ErrorProvider'; - -import useEvent from './useEvent'; - -describe('useEvent', () => { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: 0, - }, - }, - }); - - const initializeProvider = () => - renderHook( - () => { - return {errorResult: useError(), eventResult: useEvent()}; - }, - { - wrapper: ({children}) => ( - - - {children} - - - ), - }, - ); - - it('이름과 비밀번호를 받아 새로운 이벤트를 생성한다.', async () => { - const {result} = initializeProvider(); - - await act(async () => { - expect( - await result.current.eventResult.createNewEvent({eventName: '테스트이름', password: VALID_PASSWORD_FOR_TEST}), - ); - }); - - await act(async () => { - expect(result.current.errorResult.errorInfo).toBe(null); - }); - }); - - it(`이름 길이가 ${VALID_EVENT_NAME_LENGTH_IN_SERVER.min} ~ ${VALID_EVENT_NAME_LENGTH_IN_SERVER.max}사이가 아닌 경우 이벤트를 생성할 수 없다.`, async () => { - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.eventResult.createNewEvent({eventName: '', password: VALID_PASSWORD_FOR_TEST})); - }); - - await act(async () => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('EVENT_NAME_LENGTH_INVALID'); - }); - }); - - it(`비밀번호가 ${PASSWORD_LENGTH}자리수가 아닌 경우 이벤트를 생성할 수 없다`, async () => { - const {result} = initializeProvider(); - - await act(async () => { - expect(await result.current.eventResult.createNewEvent({eventName: '테스트이름', password: 1})); - }); - - await act(async () => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('EVENT_PASSWORD_FORMAT_INVALID'); - }); - }); -}); diff --git a/client/src/hooks/useEvent/useEvent.tsx b/client/src/hooks/useEvent/useEvent.tsx deleted file mode 100644 index e58733fc0..000000000 --- a/client/src/hooks/useEvent/useEvent.tsx +++ /dev/null @@ -1,16 +0,0 @@ -// TODO: (@todari) useEvent는 이제 쓰지 않긴 해요...! - -import {RequestPostNewEvent, ResponsePostNewEvent, requestPostNewEvent} from '@apis/request/event'; -import {useFetch} from '@hooks/useFetch/useFetch'; - -const useEvent = () => { - const {fetch} = useFetch(); - - const createNewEvent = async ({eventName, password}: RequestPostNewEvent) => { - return await fetch({queryFunction: () => requestPostNewEvent({eventName, password})}); - }; - - return {createNewEvent}; -}; - -export default useEvent; diff --git a/client/src/hooks/useFetch/useFetch.test.tsx b/client/src/hooks/useFetch/useFetch.test.tsx deleted file mode 100644 index b4748125a..000000000 --- a/client/src/hooks/useFetch/useFetch.test.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import {renderHook, waitFor} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; -import {act} from 'react'; - -import FetchError from '@errors/FetchError'; -import {useError} from '@hooks/useError/useError'; - -import {requestPostWithoutResponse} from '@apis/fetcher'; - -import {captureError} from '@utils/captureError'; - -import {UNKNOWN_ERROR} from '@constants/errorMessage'; - -import {ErrorProvider} from '../useError/ErrorProvider'; - -import {useFetch} from './useFetch'; - -describe('useFetch', () => { - const initializeProvider = () => - renderHook( - () => { - return {errorResult: useError(), fetchResult: useFetch()}; - }, - { - wrapper: ({children}) => ( - - {children} - - ), - }, - ); - - describe('요청이 성공하는 경우', () => { - it('요청이 성공했다면 그대로 api response body를 반환한다.', async () => { - const {result} = initializeProvider(); - const mockQueryFunction = jest.fn().mockResolvedValue('mocked data'); - - let data; - - await act(async () => { - data = await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); - }); - - expect(data).toBe('mocked data'); - }); - - it('onSuccess 콜백을 넘겨준 경우 콜백을 실행한다.', async () => { - const {result} = initializeProvider(); - const mockQueryFunction = jest.fn().mockResolvedValue('mocked data'); - const onSuccess = jest.fn(); - - await act(async () => { - await result.current.fetchResult.fetch({queryFunction: mockQueryFunction, onSuccess}); - }); - - expect(onSuccess).toHaveBeenCalled(); - }); - }); - - describe('요청이 실패하는 경우', () => { - describe('발생한 에러가 Error 인스턴스인 경우', () => { - const errorThrowFunction = () => requestPostWithoutResponse({endpoint: '/throw-handle-error'}); - - it('FetchError가 발생하면 해당 에러의 errorBody를 사용해 상태를 저장한다.', async () => { - const {result} = initializeProvider(); - const fetchError = new FetchError({ - errorInfo: {errorCode: 'UNHANDLED', message: 'Fetch error occurred'}, - name: 'UNHANDLED', - message: 'Fetch error occurred', - requestBody: '', - status: 400, - endpoint: '', - method: 'POST', - }); - const mockQueryFunction = jest.fn().mockRejectedValue(fetchError); - - await act(async () => { - await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); - }); - - await waitFor(() => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('UNHANDLED'); - expect(result.current.errorResult.errorInfo?.message).toBe('Fetch error occurred'); - }); - }); - - it('일반 Error가 발생하면 해당 에러의 name과 message를 사용해 상태를 저장한다.', async () => { - const {result} = initializeProvider(); - const mockError = new Error('일반 에러 발생'); - const mockQueryFunction = jest.fn().mockRejectedValue(mockError); - - try { - await act(async () => { - await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); - }); - } catch (error) { - // 에러 바운더리로 보내지는 에러라서 throw하는데 이를 받아줄 에러 바운더리를 호출하지 않았으므로 catch문에서 별다른 로직을 작성하지 않음 - } - - await waitFor(() => { - expect(result.current.errorResult.errorInfo?.errorCode).toBe('Error'); - expect(result.current.errorResult.errorInfo?.message).toBe('일반 에러 발생'); - }); - }); - - it('onError 콜백을 넘겨준 경우 onError를 실행한다.', async () => { - const {result} = initializeProvider(); - const onError = jest.fn(); - - await act(async () => { - await result.current.fetchResult.fetch({queryFunction: errorThrowFunction, onError}); - }); - - expect(onError).toHaveBeenCalled(); - }); - - it('에러가 발생하면 로그를 보낸다.', async () => { - const {result} = initializeProvider(); - - await act(async () => { - await result.current.fetchResult.fetch({queryFunction: errorThrowFunction}); - }); - - expect(captureError).toHaveBeenCalled(); - }); - }); - - describe('발생한 에러가 Error 인스턴스가 아닌 경우', () => { - const mockQueryFunction = jest.fn().mockRejectedValue('unexpected error'); - - it(`에러가 발생하면 그 에러를 던진다.`, async () => { - const {result} = initializeProvider(); - - // 에러가 발생하고 에러를 던지는지 확인 - await expect( - act(async () => { - await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); - }), - ).rejects.toThrow(new Error(UNKNOWN_ERROR)); - }); - - it('에러가 발생하면 로그를 보낸다.', async () => { - const {result} = initializeProvider(); - - await expect( - act(async () => { - await result.current.fetchResult.fetch({queryFunction: mockQueryFunction}); - }), - ).rejects.toThrow(new Error(UNKNOWN_ERROR)); - - expect(captureError).toHaveBeenCalled(); - }); - }); - }); -}); diff --git a/client/src/hooks/useFetch/useFetch.ts b/client/src/hooks/useFetch/useFetch.ts deleted file mode 100644 index 35bf18a33..000000000 --- a/client/src/hooks/useFetch/useFetch.ts +++ /dev/null @@ -1,63 +0,0 @@ -import {useState} from 'react'; -import {useNavigate} from 'react-router-dom'; - -import FetchError from '@errors/FetchError'; -import {useError} from '@hooks/useError/useError'; - -import {captureError} from '@utils/captureError'; -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import {UNKNOWN_ERROR} from '@constants/errorMessage'; - -type FetchProps = { - queryFunction: () => Promise; - onSuccess?: () => void; - onError?: () => void; -}; - -export const useFetch = () => { - const {setErrorInfo, clearError} = useError(); - const [loading, setLoading] = useState(false); - const navigate = useNavigate(); - const eventId = getEventIdByUrl(); - - const fetch = async ({queryFunction, onSuccess, onError}: FetchProps): Promise => { - setLoading(true); - - clearError(); - try { - const result = await queryFunction(); - - if (onSuccess) { - onSuccess(); - } - - return result; - } catch (error) { - if (error instanceof Error) { - const errorInfo = - error instanceof FetchError ? error.errorInfo : {errorCode: error.name, message: error.message}; - - setErrorInfo(errorInfo); - - if (onError) { - onError(); - } - - captureError(error, navigate, eventId); - } else { - setErrorInfo({errorCode: UNKNOWN_ERROR, message: JSON.stringify(error)}); - captureError(new Error(UNKNOWN_ERROR), navigate, eventId); - - // 에러를 throw 해 에러 바운더리로 보냅니다. 따라서 에러 이름은 중요하지 않음 - throw new Error(UNKNOWN_ERROR); - } - } finally { - setLoading(false); - } - - return {} as T; - }; - - return {loading, fetch}; -}; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx index 4d94804f4..2754a140d 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx @@ -5,7 +5,6 @@ import {MemoryRouter} from 'react-router-dom'; import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; import memberReportListInActionJson from '../../mocks/memberReportListInAction.json'; -import {ErrorProvider} from '../useError/ErrorProvider'; import useMemberReportListInAction from './useMemberReportListInAction'; @@ -22,9 +21,7 @@ describe('useMemberReportListInActionTest', () => { renderHook(() => useMemberReportListInAction(actionId, totalPrice, () => {}), { wrapper: ({children}) => ( - - {children} - + {children} ), }); diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx index a2b0de89d..f7a577b68 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx @@ -1,29 +1,26 @@ import {renderHook, waitFor} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; -import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; +import {QueryClient} from '@tanstack/react-query'; + +import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; import reportListJson from '../../mocks/reportList.json'; -import {ErrorProvider} from '../useError/ErrorProvider'; import useSearchMemberReportList from './useSearchMemberReportList'; describe('useSearchMemberReportList', () => { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: 0, - }, - }, - }); - const initializeProvider = (name: string) => renderHook(() => useSearchMemberReportList({name}), { wrapper: ({children}) => ( - - - {children} - - + + + + {children} + + + ), }); diff --git a/client/src/hooks/useSetEventName.ts b/client/src/hooks/useSetEventNamePage.ts similarity index 91% rename from client/src/hooks/useSetEventName.ts rename to client/src/hooks/useSetEventNamePage.ts index b36820735..f5b5bce12 100644 --- a/client/src/hooks/useSetEventName.ts +++ b/client/src/hooks/useSetEventNamePage.ts @@ -2,7 +2,7 @@ import {useState} from 'react'; import validateEventName from '@utils/validate/validateEventName'; -const useSetEventName = () => { +const useSetEventNamePage = () => { const [eventName, setEventName] = useState(''); const [errorMessage, setErrorMessage] = useState(null); const [canSubmit, setCanSubmit] = useState(false); @@ -29,4 +29,4 @@ const useSetEventName = () => { }; }; -export default useSetEventName; +export default useSetEventNamePage; diff --git a/client/src/hooks/useToast/ToastProvider.tsx b/client/src/hooks/useToast/ToastProvider.tsx index eed006967..be0d2ea15 100644 --- a/client/src/hooks/useToast/ToastProvider.tsx +++ b/client/src/hooks/useToast/ToastProvider.tsx @@ -1,9 +1,5 @@ /** @jsxImportSource @emotion/react */ -import {createContext, useContext, useEffect, useState} from 'react'; - -import {useError} from '@hooks/useError/useError'; - -import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; +import {createContext, useEffect, useState} from 'react'; import {ToastProps} from '../../components/Toast/Toast.type'; import Toast from '../../components/Toast/Toast'; @@ -23,7 +19,6 @@ type ShowToast = ToastProps & { export const ToastProvider = ({children}: React.PropsWithChildren) => { const [currentToast, setCurrentToast] = useState(null); - const {errorInfo, clearError, clientErrorMessage} = useError(); const showToast = ({showingTime = DEFAULT_TIME, isAlwaysOn = false, ...toastProps}: ShowToast) => { setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); @@ -34,28 +29,8 @@ export const ToastProvider = ({children}: React.PropsWithChildren) => { }; useEffect(() => { - if (errorInfo !== null) { - showToast({ - message: clientErrorMessage || SERVER_ERROR_MESSAGES.UNHANDLED, - showingTime: DEFAULT_TIME, // TODO: (@weadie) 나중에 토스트 프로바이더를 제거한 토스트를 만들 것이기 때문에 많이 리펙터링 안함 - isAlwaysOn: false, - position: 'bottom', - bottom: '6.25rem', - // TODO: (@soha&weadie) zIndex의 값 추후에 꼭!!! 수정 - style: {zIndex: '1000'}, - }); - - clearError(DEFAULT_TIME); - } - }, [errorInfo, clientErrorMessage]); - - useEffect(() => { - if (!currentToast) return; - - if (!currentToast.isAlwaysOn) { - const timer = setTimeout(() => { - setCurrentToast(null); - }, currentToast.showingTime); + if (currentToast && !currentToast.isAlwaysOn) { + const timer = setTimeout(() => setCurrentToast(null), currentToast.showingTime); return () => clearTimeout(timer); } diff --git a/client/src/hooks/useToast/useToast.test.tsx b/client/src/hooks/useToast/useToast.test.tsx index 54906cea4..f790ba98e 100644 --- a/client/src/hooks/useToast/useToast.test.tsx +++ b/client/src/hooks/useToast/useToast.test.tsx @@ -1,101 +1,80 @@ -import {render, screen, waitFor} from '@testing-library/react'; -import {act, ReactNode} from 'react'; +import {render, renderHook, screen, waitFor} from '@testing-library/react'; +import {act} from 'react'; import {HDesignProvider} from 'haengdong-design'; -import {useError} from '@hooks/useError/useError'; - -import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; - -import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; -import {ErrorInfo, ErrorProvider} from '../../hooks/useError/ErrorProvider'; // useError 경로에 맞게 설정 - import {ToastProvider} from './ToastProvider'; // 위 코드에 해당하는 ToastProvider 경로 +import {useToast} from './useToast'; -jest.mock('lottie-react', () => () =>
Lottie Mock
); +const TOAST_CONFIG = { + message: 'Test Toast Message', +}; // 테스트용 헬퍼 컴포넌트 -const TestComponent = ({errorInfo}: {errorInfo: ErrorInfo}) => { - const {setErrorInfo} = useError(); +const TestComponent = () => { + const {showToast} = useToast(); - // 테스트에서 직접 에러를 설정합니다. - const triggerError = () => { - setErrorInfo(errorInfo); + const handleClick = () => { + showToast(TOAST_CONFIG); }; - return ; + return ; }; -const setup = (ui: ReactNode) => +const setup = () => render( - - - {ui} - - + + + , ); -beforeEach(() => { - jest.useFakeTimers(); -}); +describe('ToastProvider', () => { + it('토스트를 띄우고 자동으로 사라지게 한다', async () => { + setup(); -afterEach(() => { - jest.useRealTimers(); -}); + // 토스트를 띄우기 위해 버튼 클릭 + act(() => { + screen.getByText('Show Toast').click(); + }); + + // 토스트 메시지가 나타나는지 확인 + expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); -describe('useToast', () => { - describe('error의 경우 자동으로 토스트를 띄워준다.', () => { - it('핸들링 가능한 에러인 경우 토스트가 뜬다.', async () => { - const errorCode = 'ACTION_NOT_FOUND'; - - setup( - , - ); - const errorMessage = SERVER_ERROR_MESSAGES[errorCode]; - - act(() => { - // 에러 트리거 버튼을 클릭 - screen.getByText('Trigger Error').click(); - }); - - // 토스트가 표시되는지 확인 - await waitFor(() => { - expect(screen.getByText(errorMessage)).toBeInTheDocument(); - }); - - // 타이머가 지나서 토스트가 사라지는지 확인 - jest.runAllTimers(); // Jest의 타이머를 실행 - await waitFor(() => { - expect(screen.queryByText(errorMessage)).not.toBeInTheDocument(); - }); + // 1초 후에 토스트 메시지가 사라지는지 확인 + await waitFor( + () => { + expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + }, + {timeout: 3100}, + ); // 타임아웃을 3100ms로 설정하여 정확히 3초 후 확인 + }); + + it('토스트 닫기 버튼을 눌렀을 때 사라진다', async () => { + setup(); + + // 토스트를 띄우기 위해 버튼 클릭 + act(() => { + screen.getByText('Show Toast').click(); + }); + + // 토스트 메시지가 나타나는지 확인 + expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + + // 토스트의 닫기 버튼을 클릭 + act(() => { + document.getElementById('toast')?.click(); }); - it('핸들링 불가능한 에러인 경우 토스트가 안뜬다.', async () => { - const errorCode = '핸들링이 안되는 에러 코드'; - - setup( - , - ); - - act(() => { - // 에러 트리거 버튼을 클릭 - screen.getByText('Trigger Error').click(); - }); - - await waitFor(() => { - expect(document.getElementById('toast')).not.toBeInTheDocument(); - }); + // 닫기 버튼을 클릭한 후 토스트가 사라지는지 확인 + await waitFor(() => { + expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); }); }); + + it('Provider없이 useToast 사용할 경우 에러를 던진다.', () => { + expect(() => { + const _ = renderHook(() => useToast()); + }).toThrow('useToast는 ToastProvider 내에서 사용되어야 합니다.'); + }); }); diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index e283d17a8..ad68327d2 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -2,13 +2,13 @@ import {useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; import {css} from '@emotion/react'; -import useSetEventName from '@hooks/useSetEventName'; +import useSetEventNamePage from '@hooks/useSetEventNamePage'; import {ROUTER_URLS} from '@constants/routerUrls'; const SetEventNamePage = () => { const navigate = useNavigate(); - const {eventName, errorMessage, canSubmit, handleEventNameChange} = useSetEventName(); + const {eventName, errorMessage, canSubmit, handleEventNameChange} = useSetEventNamePage(); const submitEventName = (event: React.FormEvent) => { event.preventDefault(); @@ -25,7 +25,7 @@ const SetEventNamePage = () => {
{ return ( - + <Title + title="알 수 없는 오류입니다." + description="오류가 난 상황에 대해 haengdongdj@gmail.com 로 연락주시면 소정의 상품을 드립니다." + /> </MainLayout> ); }; diff --git a/client/src/store/appErrorStore.ts b/client/src/store/appErrorStore.ts new file mode 100644 index 000000000..ca350d4cb --- /dev/null +++ b/client/src/store/appErrorStore.ts @@ -0,0 +1,14 @@ +import {create} from 'zustand'; + +type State = { + appError: Error | null; +}; + +type Action = { + updateAppError: (appError: State['appError']) => void; +}; + +export const useAppErrorStore = create<State & Action>(set => ({ + appError: null, + updateAppError: appError => set(() => ({appError})), +})); diff --git a/client/src/types/fetchErrorType.ts b/client/src/types/fetchErrorType.ts index 664fa368b..19fe8ee6f 100644 --- a/client/src/types/fetchErrorType.ts +++ b/client/src/types/fetchErrorType.ts @@ -1,4 +1,4 @@ -import {ErrorInfo} from '@hooks/useError/ErrorProvider'; +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; import {Method} from '@apis/fetcher'; diff --git a/client/src/utils/captureError.ts b/client/src/utils/captureError.ts index ce70da972..67a30ac99 100644 --- a/client/src/utils/captureError.ts +++ b/client/src/utils/captureError.ts @@ -1,19 +1,11 @@ -import {NavigateFunction} from 'react-router-dom'; - -import FetchError from '@errors/FetchError'; -import {ErrorInfo} from '@hooks/useError/ErrorProvider'; - -import {ROUTER_URLS} from '@constants/routerUrls'; +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; import sendLogToSentry from './sendLogToSentry'; -export const captureError = async (error: Error, navigate: NavigateFunction, eventId: string) => { +export const captureError = async (error: Error, errorInfo: ErrorInfo) => { // prod 환경에서만 Sentry capture 실행 if (process.env.NODE_ENV !== 'production') return; - const errorInfo: ErrorInfo = - error instanceof FetchError ? error.errorInfo : {message: error.message, errorCode: error.name}; - switch (errorInfo?.errorCode) { case 'INTERNAL_SERVER_ERROR': sendLogToSentry({error, errorInfo, level: 'fatal'}); @@ -21,28 +13,28 @@ export const captureError = async (error: Error, navigate: NavigateFunction, eve case 'FORBIDDEN': sendLogToSentry({error, errorInfo}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; case 'TOKEN_INVALID': sendLogToSentry({error, errorInfo}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; case 'TOKEN_EXPIRED': sendLogToSentry({error, errorInfo}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; case 'TOKEN_NOT_FOUND': sendLogToSentry({error, errorInfo}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 case 'PASSWORD_INVALID': sendLogToSentry({error, errorInfo, level: 'debug'}); - navigate(`${ROUTER_URLS.event}/${eventId}/login`); + break; // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts index d93e526a4..22d736b6c 100644 --- a/client/src/utils/sendLogToSentry.ts +++ b/client/src/utils/sendLogToSentry.ts @@ -1,6 +1,6 @@ import * as Sentry from '@sentry/react'; -import {ErrorInfo} from '@hooks/useError/ErrorProvider'; +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; import {UNKNOWN_ERROR} from '@constants/errorMessage'; From 7e1f274aa7afcc5f74f30d8dc5da32a4dbd9a05f Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:56:23 +0900 Subject: [PATCH 210/273] =?UTF-8?q?fix=20=ED=96=89=EC=82=AC=20=EC=9D=B8?= =?UTF-8?q?=EC=9B=90=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=EC=8B=9C=20?= =?UTF-8?q?=EC=A7=80=EC=B6=9C=20=EC=83=81=EC=84=B8=EC=9D=98=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=EC=9D=B4=20=EB=B3=80=EA=B2=BD=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8A=94=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#500)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/server/haengdong/application/EventService.java | 5 +++++ .../server/haengdong/domain/action/BillActionDetail.java | 4 ++++ .../haengdong/domain/action/BillActionDetailRepository.java | 2 ++ 3 files changed, 11 insertions(+) diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index 834c0e10a..d0628c0ef 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -16,6 +16,7 @@ import server.haengdong.application.response.EventDetailAppResponse; import server.haengdong.application.response.MembersAppResponse; import server.haengdong.domain.action.BillAction; +import server.haengdong.domain.action.BillActionDetailRepository; import server.haengdong.domain.action.BillActionRepository; import server.haengdong.domain.action.MemberAction; import server.haengdong.domain.action.MemberActionRepository; @@ -35,6 +36,8 @@ public class EventService { private final EventTokenProvider eventTokenProvider; private final BillActionRepository billActionRepository; private final MemberActionRepository memberActionRepository; + private final BillActionDetailRepository billActionDetailRepository; + @Transactional public EventAppResponse saveEvent(EventAppRequest request) { @@ -149,6 +152,8 @@ private void validateAfterMemberNameNotExist(Event event, String afterName) { private void updateMemberName(Event event, String beforeName, String afterName) { memberActionRepository.findAllByAction_EventAndMemberName(event, beforeName) .forEach(memberAction -> memberAction.updateMemberName(afterName)); + billActionDetailRepository.findAllByMemberName(beforeName) + .forEach(billActionDetail -> billActionDetail.updateMemberName(afterName)); } public void validatePassword(EventLoginAppRequest request) throws HaengdongException { diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java index ad13e6ab2..ffdfe04a3 100644 --- a/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java +++ b/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java @@ -43,6 +43,10 @@ public void updateIsFixed(boolean isFixed) { this.isFixed = isFixed; } + public void updateMemberName(String name) { + this.memberName = name; + } + public boolean hasMemberName(String memberName) { return this.memberName.equals(memberName); } diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java index d1d7cfe0f..17a082657 100644 --- a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java +++ b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java @@ -14,4 +14,6 @@ public interface BillActionDetailRepository extends JpaRepository<BillActionDeta where bd.billAction = :billAction """) List<BillActionDetail> findAllByBillAction(BillAction billAction); + + List<BillActionDetail> findAllByMemberName(String memberName); } From 7b8275245f351828edd195dafec347ea5eedb541 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 23 Aug 2024 01:01:27 +0900 Subject: [PATCH 211/273] =?UTF-8?q?fix:=20=EB=A1=9C=EB=94=A9=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EB=8F=84=EC=9E=85?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=B4=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EA=B0=80=20=ED=84=B0=EC=A7=80=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=EB=A5=BC=20=ED=95=B4=EA=B2=B0=20(#501)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: canvas를 로딩하기 위한 라이브러리 설치후 jest.setup에 적용 * chore: 불필요한 import 제거 --- client/jest.setup.ts | 1 + client/package-lock.json | 54 +++++++++++++++++-- client/package.json | 3 +- .../useSearchMemberReportList.test.tsx | 1 - 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/client/jest.setup.ts b/client/jest.setup.ts index 9fe320b2c..33c8f6a70 100644 --- a/client/jest.setup.ts +++ b/client/jest.setup.ts @@ -1,6 +1,7 @@ import {server} from './src/mocks/server'; import * as router from 'react-router'; import '@testing-library/jest-dom'; // toBeInTheDocument를 인식하기 위해 @testing-library/jest-dom/extend-expect추가 +import 'jest-canvas-mock'; // jsdom은 canvas를 추가할 수 없기 때문에 이를 해결하는 라이브러리 추가 beforeAll(() => { server.listen(); diff --git a/client/package-lock.json b/client/package-lock.json index d86774ea2..41dcdd25f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,8 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.79", + "haengdong-design": "^0.1.80", + "jest-canvas-mock": "^2.5.2", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -7379,6 +7380,11 @@ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "dev": true }, + "node_modules/cssfontparser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssfontparser/-/cssfontparser-1.2.1.tgz", + "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==" + }, "node_modules/csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -10165,13 +10171,14 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.79", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.79.tgz", - "integrity": "sha512-J5uFXmX+1VMzdU+aMTl36hJYrjzreLNhrtLMSBrdHtjwEROsYddbbXDlHTTUWaj7TpDQ1n5jgsy39jlKYv2m7w==", + "version": "0.1.80", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.80.tgz", + "integrity": "sha512-rqfuFKBcqXL6LuPt4iiiM+ZNHBV++hHVGLICiqMiN9mUcl+x3zgNxiAe/80sHPH0HsZsSbuKdkksUqwdX8adhg==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.24.1" @@ -11641,6 +11648,15 @@ } } }, + "node_modules/jest-canvas-mock": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.2.tgz", + "integrity": "sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==", + "dependencies": { + "cssfontparser": "^1.2.1", + "moo-color": "^1.0.2" + } + }, "node_modules/jest-changed-files": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", @@ -14262,6 +14278,23 @@ "loose-envify": "cli.js" } }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -14566,6 +14599,19 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/moo-color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz", + "integrity": "sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==", + "dependencies": { + "color-name": "^1.1.4" + } + }, + "node_modules/moo-color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", diff --git a/client/package.json b/client/package.json index d4297e7ba..afffdc4c2 100644 --- a/client/package.json +++ b/client/package.json @@ -69,7 +69,8 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.79", + "haengdong-design": "^0.1.80", + "jest-canvas-mock": "^2.5.2", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx index f7a577b68..90782cbdf 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx @@ -1,6 +1,5 @@ import {renderHook, waitFor} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; -import {QueryClient} from '@tanstack/react-query'; import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; From 0bd913c35bb6cff67e638f8cd4c56f233a98c6c9 Mon Sep 17 00:00:00 2001 From: Arachne <66822642+Arachneee@users.noreply.github.com> Date: Fri, 23 Aug 2024 02:07:41 +0900 Subject: [PATCH 212/273] =?UTF-8?q?fix:=20=EC=B0=B8=EC=97=AC=EC=9E=90=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=EC=8B=9C=20=EC=A7=80?= =?UTF-8?q?=EC=B6=9C=20=EC=83=81=EC=84=B8=20=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EC=95=88=EB=90=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#508)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/server/haengdong/application/EventService.java | 2 +- .../haengdong/domain/action/BillActionDetailRepository.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java index d0628c0ef..1aaddd0f9 100644 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ b/server/src/main/java/server/haengdong/application/EventService.java @@ -152,7 +152,7 @@ private void validateAfterMemberNameNotExist(Event event, String afterName) { private void updateMemberName(Event event, String beforeName, String afterName) { memberActionRepository.findAllByAction_EventAndMemberName(event, beforeName) .forEach(memberAction -> memberAction.updateMemberName(afterName)); - billActionDetailRepository.findAllByMemberName(beforeName) + billActionDetailRepository.findAllByBillAction_Action_EventAndMemberName(event, beforeName) .forEach(billActionDetail -> billActionDetail.updateMemberName(afterName)); } diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java index 17a082657..05de55304 100644 --- a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java +++ b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java @@ -4,6 +4,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import server.haengdong.domain.event.Event; @Repository public interface BillActionDetailRepository extends JpaRepository<BillActionDetail, Long> { @@ -15,5 +16,5 @@ public interface BillActionDetailRepository extends JpaRepository<BillActionDeta """) List<BillActionDetail> findAllByBillAction(BillAction billAction); - List<BillActionDetail> findAllByMemberName(String memberName); + List<BillActionDetail> findAllByBillAction_Action_EventAndMemberName(Event event, String memberName); } From bb8994ec02c2a277c38d1922cb88ef6ac7de8547 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 02:19:09 +0900 Subject: [PATCH 213/273] =?UTF-8?q?feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=204=EC=9E=90=EB=A6=AC=20=EB=84=98=EA=B2=8C=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=EB=90=98=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#503)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: v0.1.81 배포 * fix: 비밀번호 4자리 넘게 입력 가능한 오류 수정 --- HDesign/package-lock.json | 4 ++-- HDesign/package.json | 2 +- client/package-lock.json | 8 ++++---- client/package.json | 2 +- client/src/pages/CreateEventPage/SetEventPasswordPage.tsx | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json index c25af9210..fb92d2ae1 100644 --- a/HDesign/package-lock.json +++ b/HDesign/package-lock.json @@ -1,12 +1,12 @@ { "name": "haengdong-design", - "version": "0.1.80", + "version": "0.1.81", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "haengdong-design", - "version": "0.1.80", + "version": "0.1.81", "license": "ISC", "dependencies": { "@emotion/react": "^11.11.4", diff --git a/HDesign/package.json b/HDesign/package.json index 1d78b6893..062987bf1 100644 --- a/HDesign/package.json +++ b/HDesign/package.json @@ -1,6 +1,6 @@ { "name": "haengdong-design", - "version": "0.1.80", + "version": "0.1.81", "description": "", "main": "./dist/index.js", "module": "./dist/index.js", diff --git a/client/package-lock.json b/client/package-lock.json index 41dcdd25f..61a529538 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.80", + "haengdong-design": "^0.1.81", "jest-canvas-mock": "^2.5.2", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", @@ -10171,9 +10171,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.80.tgz", - "integrity": "sha512-rqfuFKBcqXL6LuPt4iiiM+ZNHBV++hHVGLICiqMiN9mUcl+x3zgNxiAe/80sHPH0HsZsSbuKdkksUqwdX8adhg==", + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.81.tgz", + "integrity": "sha512-IiXkt0zXSEmn7vstTLOeNZLFS35JO8lXbXavM55wdyAJd+w0e5kfRxyDk/K2oSiAnX2c2YPiGep/A0x2/gZPDg==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index afffdc4c2..6d673dd06 100644 --- a/client/package.json +++ b/client/package.json @@ -69,7 +69,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.80", + "haengdong-design": "^0.1.81", "jest-canvas-mock": "^2.5.2", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 2ebe7be50..14fcdd75b 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -23,7 +23,7 @@ const SetEventPasswordPage = () => { labelText="비밀번호" errorText={errorMessage} value={password} - type="number" + type="text" maxLength={RULE.maxEventPasswordLength} placeholder="비밀번호" onChange={handleChange} From 3ea6f8f43ca72c9362f788081454c3032970b5d4 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 02:19:27 +0900 Subject: [PATCH 214/273] =?UTF-8?q?fix:=20BottomSheet=EA=B0=80=20=EC=A1=B0?= =?UTF-8?q?=EA=B1=B4=EB=B6=80=20=EB=A0=8C=EB=8D=94=EB=A7=81=20=EB=90=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20(#506)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PutAndDeleteBillActionModal.tsx | 2 -- .../src/components/StepList/MemberStepItem.tsx | 14 ++++++++------ .../src/pages/EventPage/AdminPage/AdminPage.tsx | 16 +++++++++------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index 3d62c5c77..3157f6e67 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -65,8 +65,6 @@ const PutAndDeleteBillActionModal = ({ actions.find(({actionId}) => actionId === billAction.actionId), )[0].members; - const {showToast} = useToast(); - return ( <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> <form diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx index 07793a71d..a9abaea1a 100644 --- a/client/src/components/StepList/MemberStepItem.tsx +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -23,12 +23,14 @@ const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, prefix={`${step.actions.map(({name}) => name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} onClick={() => setIsOpenBottomSheet(prev => !prev)} /> - <DeleteMemberActionModal - memberActionType={step.type} - memberActionList={step.actions} - isBottomSheetOpened={isOpenBottomSheet && isAdmin} - setIsBottomSheetOpened={setIsOpenBottomSheet} - /> + {isOpenBottomSheet && isAdmin && ( + <DeleteMemberActionModal + memberActionType={step.type} + memberActionList={step.actions} + isBottomSheetOpened={isOpenBottomSheet} + setIsBottomSheetOpened={setIsOpenBottomSheet} + /> + )} </> ); }; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 6e0e265e2..79deeac7a 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -73,13 +73,15 @@ const AdminPage = () => { </Button> </div> )} - <ModalBasedOnMemberCount - allMemberList={allMemberList} - setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} - isOpenBottomSheet={isOpenFixedButtonBottomSheet} - isOpenAllMemberListButton={isOpenAllMemberListButton} - setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} - /> + {isOpenFixedButtonBottomSheet && ( + <ModalBasedOnMemberCount + allMemberList={allMemberList} + setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} + isOpenBottomSheet={isOpenFixedButtonBottomSheet} + isOpenAllMemberListButton={isOpenAllMemberListButton} + setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} + /> + )} </section> </> ); From 851e0fd18f808ceb9752e75feca2d9f25090378e Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 23 Aug 2024 02:20:32 +0900 Subject: [PATCH 215/273] =?UTF-8?q?feat:=20=ED=99=88=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=EC=84=9C=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EB=88=8C=EB=A0=80=EC=9D=84=20=EB=95=8C=20=EC=B0=A8?= =?UTF-8?q?=EB=93=B1=20=EC=A0=95=EC=82=B0=20=EB=AA=A8=EB=8B=AC=20=EB=9C=A8?= =?UTF-8?q?=EA=B8=B0=20(#507)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 홈화면에서 지출 내역 상세 모달이 뜨도록 함 * chore: 사용하지 않는 코드 제거 --- .../ExpenseDetailModal/ExpenseDetailModal.tsx | 142 ++++++++++++++++++ .../PutAndDeleteBillActionModal.tsx | 1 - .../src/components/StepList/BillStepItem.tsx | 8 + 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx diff --git a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx new file mode 100644 index 000000000..645acb468 --- /dev/null +++ b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx @@ -0,0 +1,142 @@ +import type {BillAction} from 'types/serviceType'; + +import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; + +import validatePurchase from '@utils/validate/validatePurchase'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; +import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; + +import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; + +import { + bottomSheetHeaderStyle, + bottomSheetStyle, + inputContainerStyle, +} from '../SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style'; + +type PutAndDeleteBillActionModalProps = { + billAction: BillAction; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; +}; + +const ExpenseDetailModal = ({ + billAction, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: PutAndDeleteBillActionModalProps) => { + const { + inputPair, + handleInputChange, + // handleOnBlur, + // errorMessage, + // errorInfo, + canSubmit, + onDelete, + onSubmit: putBillAction, + } = usePutAndDeleteBillAction( + {title: billAction.name, price: String(billAction.price), index: 0}, + validatePurchase, + () => setIsBottomSheetOpened(false), + ); + + const { + memberReportListInAction, + addAdjustedMember, + onSubmit: putMemberReportListInAction, + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + isExistAdjustedPrice, + } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); + const { + inputList, + onChange, + canEditList, + canSubmit: isChangedMemberReportInput, + } = useMemberReportInput({ + data: memberReportListInAction, + addAdjustedMember, + totalPrice: Number(inputPair.price), + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + }); + + const {data: stepListData = []} = useRequestGetStepList(); + + const actionMemberList = stepListData.filter(({actions}) => + actions.find(({actionId}) => actionId === billAction.actionId), + )[0].members; + + return ( + <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> + <form css={bottomSheetStyle} onSubmit={() => setIsBottomSheetOpened(false)}> + <h2 css={bottomSheetHeaderStyle}> + <Text size="bodyBold">지출 내역 상세</Text> + </h2> + <fieldset css={inputContainerStyle}> + <EditableItem backgroundColor="lightGrayContainer" prefixLabelText="지출 내역 / 금액"> + <EditableItem.Input + placeholder="지출 내역" + textSize="bodyBold" + value={inputPair.title} + onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('title', event)} + disabled + /> + <Flex alignItems="center" gap="0.25rem"> + <EditableItem.Input + placeholder="0" + style={{ + textAlign: 'right', + }} + type="number" + value={inputPair.price} + onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('price', event)} + isFixed={isExistAdjustedPrice()} + disabled + /> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + + <EditableItem + backgroundColor="lightGrayContainer" + prefixLabelText="참여자" + suffixLabelText={`총 ${actionMemberList.length}명`} + > + <Flex flexDirection="column" width="100%" gap="1rem"> + {inputList.map(({name, price, isFixed}, index) => ( + <Flex key={name} justifyContent="spaceBetween"> + <EditableItem.Input + value={name} + placeholder="참여자 명" + textSize="smallBodyBold" + disabled + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + onChange={event => onChange(event, index)} + isFixed={isFixed} + textSize="smallBody" + value={price} + placeholder="0" + type="number" + disabled + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </Flex> + ))} + </Flex> + </EditableItem> + </fieldset> + <FixedButton type="submit" variants="tertiary"> + 닫기 + </FixedButton> + </form> + </BottomSheet> + ); +}; + +export default ExpenseDetailModal; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index 3157f6e67..5f7d4501e 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -6,7 +6,6 @@ import validatePurchase from '@utils/validate/validatePurchase'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; -import {useToast} from '@hooks/useToast/useToast'; import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 3ad155dfb..9a9ff4f7f 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -6,6 +6,7 @@ import {BillStep, MemberReport} from 'types/serviceType'; import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; import {MemberListInBillStep} from '@components/Modal/MemberListInBillStep'; import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; +import ExpenseDetailModal from '@components/Modal/ExpenseDetailModal/ExpenseDetailModal'; import useSetBillInput from '@hooks/useSetBillInput'; @@ -84,6 +85,13 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ setIsBottomSheetOpened={setIsOpenBottomSheet} /> )} + {isOpenBottomSheet && clickedIndex === index && !isAdmin && ( + <ExpenseDetailModal + billAction={action} + isBottomSheetOpened={isOpenBottomSheet} + setIsBottomSheetOpened={setIsOpenBottomSheet} + /> + )} </Fragment> ))} From f7c1deb4f7d773b4a65eb31dd43a62aff35f37c3 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 23 Aug 2024 02:36:21 +0900 Subject: [PATCH 216/273] =?UTF-8?q?feat:=20=ED=96=89=EB=8F=99=EB=8C=80?= =?UTF-8?q?=EC=9E=A5=20=ED=9D=94=EB=93=AF=EC=BD=98(=ED=8C=8C=EB=B9=84?= =?UTF-8?q?=EC=BD=98),=20=EB=A1=9C=EA=B3=A0=20=EC=A0=81=EC=9A=A9=20(#496)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 새로운 행동 강아지 삽입 * feat: favicon 적용 * fix: 흔듯콘 logo에 사용 * style: lint 적용 --------- Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: 이태훈 <rhymint@gmail.com> --- client/favicon.ico | Bin 0 -> 44932 bytes client/index.html | 1 + client/src/assets/image/heundeut.svg | 1 + client/src/assets/image/runningDog.svg | 9 +++++++++ client/src/assets/image/standingDog.svg | 9 +++++++++ client/src/components/Common/Logo/Logo.tsx | 13 ------------- .../components/Common/Logo/RunningDogLogo.tsx | 13 +++++++++++++ .../components/Common/Logo/StandingDogLogo.tsx | 13 +++++++++++++ client/src/components/Common/Logo/index.ts | 3 ++- .../CreateEventPage/CompleteCreateEventPage.tsx | 4 +++- client/src/pages/MainPage/Nav/Nav.style.ts | 1 - client/src/pages/MainPage/Nav/Nav.tsx | 14 ++++++++++---- .../src/pages/MainPage/Section/MainSection.tsx | 4 ++-- client/webpack.common.mjs | 2 ++ 14 files changed, 65 insertions(+), 22 deletions(-) create mode 100644 client/favicon.ico create mode 100644 client/src/assets/image/heundeut.svg create mode 100644 client/src/assets/image/runningDog.svg create mode 100644 client/src/assets/image/standingDog.svg delete mode 100644 client/src/components/Common/Logo/Logo.tsx create mode 100644 client/src/components/Common/Logo/RunningDogLogo.tsx create mode 100644 client/src/components/Common/Logo/StandingDogLogo.tsx diff --git a/client/favicon.ico b/client/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2be6241f8e7c02630efcc4cf714d8f9813cf7524 GIT binary patch literal 44932 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 Hu0mjfU8{Jm literal 0 HcmV?d00001 diff --git a/client/index.html b/client/index.html index 1912ca40f..c286fad2f 100644 --- a/client/index.html +++ b/client/index.html @@ -4,6 +4,7 @@ <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" /> <meta content="upgrade-insecure-requests" /> + <link rel="icon" href="favicon.ico" type="image/x-icon" /> <script src="https://cdn.amplitude.com/libs/analytics-browser-2.9.3-min.js.gz"></script> <script src="https://cdn.amplitude.com/libs/plugin-session-replay-browser-1.6.8-min.js.gz"></script> <script src="https://cdn.amplitude.com/libs/plugin-autocapture-browser-1.0.0-min.js.gz"></script> diff --git a/client/src/assets/image/heundeut.svg b/client/src/assets/image/heundeut.svg new file mode 100644 index 000000000..c78ca8c9b --- /dev/null +++ b/client/src/assets/image/heundeut.svg @@ -0,0 +1 @@ +<svg width="35" height="33" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" overflow="hidden"><defs><image width="80" height="76" xlink:href="data:image/png;base64,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u1A7lAYREAEREAEREAEREIHKELBR/Zo2Wu2KK7MjO8QIRAhNtLg4Cl9L2TArwxBk082Wk00padBFRUAEREAEREAEREAERKBqBIqcHbGTG5jkaEfs7YlyhxixTuyhWYVauoFfcJGywjckvOXE3vL2L/z6uqAIiIAIiIAIiIAIiIAIVJFAwbMjdpKjPdnRE+cOMSIn9p6c9KEIiIAIiIAIiIAIiIAIVIJA0DTXYYXENb7Wsec1+fCFndzAJIed7OhDbocY4XFQL3Ji7wNMH4uACIiACIiACIiACIiAzwRs+P7ArIVN65rxZU552YKouANdsdFeLqDnZXqKETmx92SlD0VABERABERABERABESgEgQoEgIIEmTmdh4ZspF5EaHXTnIMuEBPMYIfyYl9ADR9JQIiIAIiIAIiIAIiIAI+E3DBT5z8eooRFxIHQSQndp9ruNIuAiIgAiIgAiIgAiLgLAFH/MR7ixFHEqeV2J2tvkqYCIiACIiACIiACIiA7wSsCVW5i533FiME60DitBK77zVc6RcBERABERABERABERCBAQR29/uuvTiJVmLvB0ifi4AIiIAIiIAIiIAIiIAITESgp88Iz+iCEzuS8QD2vWFo9jJN2kRABERABERABERABERABKpDoK8YccGJHZjlN1KduqaciIAIiIAIiIAIiIAIiEAXgb5ixBEndvmNdBWX/hABERABERABERABERCB6hDoK0aYRQec2JmMfdhnsHAKX7WJgAiIgAiIgAiIgAiIgAhUhEBfB3bmzwUndoiQKfiMTDdpsqVNBERABERABERABERABESgMgSGzYyUvhI7Zme0+GFlqpsyIgIiIAIiIAIiIAIi4AoBDPpPo6c9ZfvbGScK59zCuTfbkxt9zz5QjMiJvS83fSECIiACIiACIiACIiAC3hJ4+y/DBYiRGQgGukLkYYFkJzUgSvjadxsoRuTE3pebvhABERABERABERABERABbwmEu8xBCJHDcBI/iEw8mHFGvsC5b+Dcq3ZyY8DJB4oR/i4IzF28cP+Kf5e0yYm9JPC6rAiIgAiIgAiIgAiIQPUIcFYEftlzyNlDOeRuC0LkDmZFNji5Mej8Q8VIe2plAycZOMUy6CIZfKfFDzOAqFOIgAiIgAiIgAiIgAiIAE20IBbmggbMtIzZkzURCJ0Q/7agIzaHnXuoGHHFbwTK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" preserveAspectRatio="none" id="img0"></image><clipPath id="clip1"><rect x="0" y="0" width="2216978" height="2095500"/></clipPath></defs><g transform="translate(-462 -414)"><g><g transform="matrix(0.00015748 0 0 0.00015748 463 414)"><g clip-path="url(#clip1)" transform="scale(1.00249 1)"><use width="100%" height="100%" xlink:href="#img0" opacity="1" transform="scale(2760.87 2760.87)"></use></g></g></g></g></svg> \ No newline at end of file diff --git a/client/src/assets/image/runningDog.svg b/client/src/assets/image/runningDog.svg new file mode 100644 index 000000000..60951e642 --- /dev/null +++ b/client/src/assets/image/runningDog.svg @@ -0,0 +1,9 @@ +<svg width="280" height="280" viewBox="0 0 280 280" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<rect x="0.5" y="0.5" width="280" height="280" fill="url(#pattern0_1905_4749)"/> +<defs> +<pattern id="pattern0_1905_4749" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_1905_4749" transform="scale(0.00124224 0.00124533)"/> +</pattern> +<image id="image0_1905_4749" width="805" height="803" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyUAAAMjCAYAAAC7zb+CAAABdWlDQ1BrQ0dDb2xvclNwYWNlRGlzcGxheVAzAAAokXWQvUvDUBTFT6tS0DqIDh0cMolD1NIKdnFoKxRFMFQFq1OafgltfCQpUnETVyn4H1jBWXCwiFRwcXAQRAcR3Zw6KbhoeN6XVNoi3sfl/Ticc7lcwBtQGSv2AijplpFMxKS11Lrke4OHnlOqZrKooiwK/v276/PR9d5PiFlNu3YQ2U9cl84ul3aeAlN//V3Vn8maGv3f1EGNGRbgkYmVbYsJ3iUeMWgp4qrgvMvHgtMunzuelWSc+JZY0gpqhrhJLKc79HwHl4plrbWD2N6f1VeXxRzqUcxhEyYYilBRgQQF4X/8044/ji1yV2BQLo8CLMpESRETssTz0KFhEjJxCEHqkLhz634PrfvJbW3vFZhtcM4v2tpCAzidoZPV29p4BBgaAG7qTDVUR+qh9uZywPsJMJgChu8os2HmwiF3e38M6Hvh/GMM8B0CdpXzryPO7RqFn4Er/QcXKWq8UwZBywAAAHhlWElmTU0AKgAAAAgABQEGAAMAAAABAAIAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAACEAAAAAQAAAIQAAAABAAKgAgAEAAAAAQAAAyWgAwAEAAAAAQAAAyMAAAAAdtVDCAAAAAlwSFlzAAAUTQAAFE0BlMqNLwAAA5JpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6SXB0YzR4bXBFeHQ9Imh0dHA6Ly9pcHRjLm9yZy9zdGQvSXB0YzR4bXBFeHQvMjAwOC0wMi0yOS8iPgogICAgICAgICA8ZGM6dGl0bGU+CiAgICAgICAgICAgIDxyZGY6QWx0PgogICAgICAgICAgICAgICA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPuygnOuqqSDsl4bripQg7JWE7Yq47JuM7YGsPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOkFsdD4KICAgICAgICAgPC9kYzp0aXRsZT4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTMyPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xMzI8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlBob3RvbWV0cmljSW50ZXJwcmV0YXRpb24+MjwvdGlmZjpQaG90b21ldHJpY0ludGVycHJldGF0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8SXB0YzR4bXBFeHQ6QXJ0d29ya1RpdGxlPuygnOuqqSDsl4bripQg7JWE7Yq47JuM7YGsPC9JcHRjNHhtcEV4dDpBcnR3b3JrVGl0bGU+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgp+oXZ5AABAAElEQVR4AeydCZxkVXX/b3XPvg/MDMswMAv7LiIILoCKwAAa/SsajTFmMX+TaFxYTDR/559/4gK4RD+JidlMjInBuLIMKojIIiAIyDYsA7MzAwwzzL511//3fbdfT3VNVb1X1VXd1d2/AzVV/d599933fds595xzbwgWEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzCBe99fHJ1SWLSo2JH+9rcJmIAJmIAJmEDrCBRaV7VrNgETMIHBI/DdPy7uP3ZCGL11WXj+km8Xuq75o+Kk8RPDQaOKYUZhVHg+7AwvzpkatjyiJs4MoXvnxjCz0BmmLtsclh55cChu3RxOGl0IS8ZMCoVN20Kh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gARIIFACVqXc1NQkazHjdBWUjI4eCt+GH4SvnDvTesdDHoqSAAmQAAmQQCAE6OgeCEYWQgIkQALhIjBnqn0FWjQDD3ldEc8+AWXDB8WS5ZYtf50w2/phuHrB1pAACZAACZQLgew/VOVCgP0kARIggRgS6FArd+6tkcOwWnImlI4B6GL7TN20LVlVVSmT60WWZbrOcyRAAiRAAiRQDAJcKSkGZdZBAiRAAiUi8MAUuze0kRFQPn6JJgzAukhX+I0IlJUGrKG8aFfKNyfdZH1UouaxWhIgARIgARIgARIgARIggXIiYE+3E8FN5kyxL1kwxR5VTn1nX0mABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABCJEwIpQW9lUEiABEiABEiCBMibw8FR7WEWFtLOa5MaJs6zz50+1T7NtmdEocmOFJXcAzTic/1gRzZ1mHzxxpvVpGeNi10kgUgSolETqdrGxJEACJEACJBB/AvOm2k/ZImc4PcVgZTM+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+kOWXvnzItuhgR2u3zHLdCiXxSLtjAxBmY8h/RUd5eA6fj+D/DSPcRpfZ6xWPGKORYEfFLNtTsZonPz2Mrll/KeN1mVz2q6SloZHcg0yctxlxhsan4EESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEak/g/wPgRzBQnpl3FAAAAABJRU5ErkJggg=="/> +</defs> +</svg> diff --git a/client/src/assets/image/standingDog.svg b/client/src/assets/image/standingDog.svg new file mode 100644 index 000000000..2d34a8cf9 --- /dev/null +++ b/client/src/assets/image/standingDog.svg @@ -0,0 +1,9 @@ +<svg width="310" height="300" viewBox="0 0 310 300" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> +<rect width="310" height="300" fill="url(#pattern0_1905_4751)"/> +<defs> +<pattern id="pattern0_1905_4751" patternContentUnits="objectBoundingBox" width="1" height="1"> +<use xlink:href="#image0_1905_4751" transform="scale(0.00131926 0.0013369)"/> +</pattern> +<image id="image0_1905_4751" width="758" height="748" xlink:href="data:image/png;base64,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QAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk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PZ0ujIbprSq6UU55UMSkHkuvBXJKn82dTEtFEY9PsxAgQGDCAv4oTbgDnJ4AgXYKXF7O9xzO6cX4T/TZsgU5p414iqgn47azO2876vgk5+pUTl8P704r888X12/7QAUJECBwBwQk9ncA2SkIEOiXQNyguxBzrM/EvP2vIuF/qt76SAyHUynFj6UNAqON9MHjp4ufy1ivfZ6PPHyiWG9D3GIkQKCfAhL7fva7VhMgMGGB75by8cjuX9vMo1+mi8GDMRD4K+b0H55wWL08fXmj6zCnjxZOFVevLOcXHjtZXOwlhEYTINB6AYl967tQAwgQ6JrA5Y/zzPEzxY1vF/PcYJDe3Okm3pjU/Ucu0m+DnB7tmsE42xNGa/HJyZzvkR+nqroIEGiigMS+ib0iJgIECOxBYPVcfqicNvL9cj5x6K7005/r6ejCS8WXq+V396d0JW71LeqDgEh4r8eDpj6NewNOlZ8WlFeudxpElOFs3TA8iCcA5F2LlUW3llGRfoz6Hony//lbE/X8Hjcez1blqnXEcyNuQZ2pXpfrGLxsxu+vUc+xeHEuajpd7i9jTRvpbNzVcCgS9i/KlxYCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAi0WOAfA/FQm5Hf5vcAAAAASUVORK5CYII="/> +</defs> +</svg> diff --git a/client/src/components/Common/Logo/Logo.tsx b/client/src/components/Common/Logo/Logo.tsx deleted file mode 100644 index c8c798d2a..000000000 --- a/client/src/components/Common/Logo/Logo.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import Dog from '@assets/image/dog.svg'; - -import {logoStyle} from './Logo.style'; - -const Logo = () => { - return ( - <div css={logoStyle}> - <Dog /> - </div> - ); -}; - -export default Logo; diff --git a/client/src/components/Common/Logo/RunningDogLogo.tsx b/client/src/components/Common/Logo/RunningDogLogo.tsx new file mode 100644 index 000000000..a09a904c1 --- /dev/null +++ b/client/src/components/Common/Logo/RunningDogLogo.tsx @@ -0,0 +1,13 @@ +import RunningDog from '@assets/image/runningDog.svg'; + +import {logoStyle} from './Logo.style'; + +const RunningDogLogo = () => { + return ( + <div css={logoStyle}> + <RunningDog /> + </div> + ); +}; + +export default RunningDogLogo; diff --git a/client/src/components/Common/Logo/StandingDogLogo.tsx b/client/src/components/Common/Logo/StandingDogLogo.tsx new file mode 100644 index 000000000..5c2cf591e --- /dev/null +++ b/client/src/components/Common/Logo/StandingDogLogo.tsx @@ -0,0 +1,13 @@ +import StandingDog from '@assets/image/standingDog.svg'; + +import {logoStyle} from './Logo.style'; + +const StandingDogLogo = () => { + return ( + <div css={logoStyle}> + <StandingDog /> + </div> + ); +}; + +export default StandingDogLogo; diff --git a/client/src/components/Common/Logo/index.ts b/client/src/components/Common/Logo/index.ts index 31d6bf822..43a08fd54 100644 --- a/client/src/components/Common/Logo/index.ts +++ b/client/src/components/Common/Logo/index.ts @@ -1 +1,2 @@ -export {default as Logo} from './Logo'; +export {default as StandingDog} from './StandingDogLogo'; +export {default as RunningDog} from './RunningDogLogo'; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 13af31a8d..066165d6a 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -1,6 +1,8 @@ import {useLocation, useNavigate} from 'react-router-dom'; import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; +import {RunningDog} from '@components/Common/Logo'; + import {ROUTER_URLS} from '@constants/routerUrls'; const CompleteCreateEventPage = () => { @@ -18,7 +20,7 @@ const CompleteCreateEventPage = () => { description={`행사가 성공적으로 개시됐어요 :) 관리 페이지로 이동해서 정산을 시작할 수 있어요`} /> - + <RunningDog /> <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>관리 페이지로 이동</FixedButton> </MainLayout> ); diff --git a/client/src/pages/MainPage/Nav/Nav.style.ts b/client/src/pages/MainPage/Nav/Nav.style.ts index 0d2ab0432..58cf1cb86 100644 --- a/client/src/pages/MainPage/Nav/Nav.style.ts +++ b/client/src/pages/MainPage/Nav/Nav.style.ts @@ -12,7 +12,6 @@ export const navStyle = css({ maxWidth: '768px', zIndex: '20', height: '4rem', - boxShadow: '0 0.25rem 0.25rem 0 rgba(0, 0, 0, 0.12)', backgroundColor: 'white', }); diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index d59517466..96bad9741 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -1,5 +1,8 @@ -import {Button, Text} from 'haengdong-design'; +import {Button, Flex, Text} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; +import HeundeutLoto from '@components/Common/Logo/HeunDeutLogo'; + +import Heundeut from '@assets/image/heundeut.svg'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -9,9 +12,12 @@ const Nav = () => { const navigate = useNavigate(); return ( <header css={navStyle}> - <div css={logoStyle}> - <Text size="subTitle">행동대장</Text> - </div> + <Flex gap="0.5rem"> + <Heundeut /> + <div css={logoStyle}> + <Text size="subTitle">행동대장</Text> + </div> + </Flex> <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> 정산 시작하기 </Button> diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx index 4f62d2e1b..4bbeb7340 100644 --- a/client/src/pages/MainPage/Section/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -2,7 +2,7 @@ import {css, keyframes} from '@emotion/react'; import {Button, Text} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; -import {Logo} from '@components/Common/Logo'; +import {StandingDog} from '@components/Common/Logo'; import ChevronDown from '@assets/image/chevronDownLarge.svg'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -33,7 +33,7 @@ const MainSection = () => { })} > <div css={animateWithDelay(0)}> - <Logo /> + <StandingDog /> </div> <Text css={animateWithDelay(1)} style={{textAlign: 'center'}} size="title">{`행동대장을 통해 간편하게 정산하세요 diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs index 0312afe36..160baf0ca 100644 --- a/client/webpack.common.mjs +++ b/client/webpack.common.mjs @@ -44,6 +44,8 @@ export default { plugins: [ new HtmlWebpackPlugin({ template: './index.html', + hash: true, + favicon: './favicon.ico', }), new ForkTsCheckerWebpackPlugin(), new ModifySourcePlugin({ From da54b61534f17b22cc446b858300defcfc64a990 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 23 Aug 2024 03:59:52 +0900 Subject: [PATCH 217/273] =?UTF-8?q?feat:=20meta=20tag=20=EB=A7=81=ED=81=AC?= =?UTF-8?q?=20=EB=B3=B5=EC=82=AC=20=EC=9D=B4=EB=AF=B8=EC=A7=80=EC=99=80=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=EC=B6=94=EA=B0=80=20(#510)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: og tag 설정 (링크 붙여넣기 할 때 이미지와 소개글 나오도록 설정) * feat: 행댕이 이미지 삽입 * feat: description 수정 --- client/index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/client/index.html b/client/index.html index c286fad2f..12be549a7 100644 --- a/client/index.html +++ b/client/index.html @@ -4,6 +4,17 @@ <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" /> <meta content="upgrade-insecure-requests" /> + <meta name="haengdong" content="행동대장으로 간편하게 정산하세요" /> + <meta property="og:url" content="https://app.haengdong.pro" /> + <meta property="og:title" content="행동대장" /> + <meta property="og:type" content="website" /> + <meta property="og:description" content="행동대장으로 간편하게 정산하세요" /> + <meta + property="og:image" + content="https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%9B%A8%EB%94%94%286%EA%B8%B0%29/g583lirp8yg.jpg" + /> + <meta property="og:image:type" content="image/png" /> + <meta property="og:image:alt" content="행댕이" /> <link rel="icon" href="favicon.ico" type="image/x-icon" /> <script src="https://cdn.amplitude.com/libs/analytics-browser-2.9.3-min.js.gz"></script> <script src="https://cdn.amplitude.com/libs/plugin-session-replay-browser-1.6.8-min.js.gz"></script> From a39079fe6083f92fd48461262c84bfc625cdced3 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Fri, 23 Aug 2024 04:00:27 +0900 Subject: [PATCH 218/273] =?UTF-8?q?fix:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EB=B0=8F=20=EC=A0=84=EC=B2=B4=20=EC=B0=B8=EC=97=AC?= =?UTF-8?q?=EC=9E=90=20=EB=B2=84=EA=B7=B8=20(#511)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 전체 참여자 삭제 후 수정 요청 순서 보장 * fix: 이름 변경 수정이 존재하지 않는 상황에서도 nameChange api 요청이 전송되지 않도록 수정 * fix: 현재 필요하지 않는 hasDragHandler를 false로 변경 * fix: 인원 변동 요청을 한 후 input에 value 값이 초기화 되지 않는 버그 해결 * fix: bill 액션이 없는 상태에서 BillInput을 닫을 때 BillContainer가 사리지지 않는 버그 해결 * chore: console.log 삭제 --- .../AddMemberActionListModalContent.tsx | 7 +++++-- client/src/components/StepList/MemberStepItem.tsx | 2 +- client/src/components/StepList/StepList.tsx | 9 ++++++--- client/src/hooks/useDynamicInput.tsx | 6 ++++++ .../useMemberReportListInAction.test.tsx | 2 -- client/src/hooks/useSetAllMemberList.tsx | 6 +++--- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index b14e6ffc0..ad6e63f28 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -18,7 +18,7 @@ interface AddMemberActionListModalContentProps { const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: AddMemberActionListModalContentProps) => { const dynamicProps = useDynamicInput(validateMemberName); - const {inputList, getFilledInputList, errorMessage, canSubmit} = dynamicProps; + const {inputList, getFilledInputList, errorMessage, canSubmit, resetInputValue} = dynamicProps; const {mutate: postMemberList} = useRequestPostMemberList(); @@ -38,7 +38,10 @@ const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: Ad disabled={!canSubmit} variants={'primary'} children={`${inputList.length - 1}명 ${inOutAction === 'OUT' ? '탈주' : '늦참'}`} - onClick={handleUpdateMemberListSubmit} + onClick={() => { + handleUpdateMemberListSubmit(); + resetInputValue(); + }} /> </div> ); diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx index a9abaea1a..ed3f5bfe7 100644 --- a/client/src/components/StepList/MemberStepItem.tsx +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -18,7 +18,7 @@ const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, return ( <> <DragHandleItem - hasDragHandler={isAdmin} + hasDragHandler={false} backgroundColor="white" prefix={`${step.actions.map(({name}) => name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} onClick={() => setIsOpenBottomSheet(prev => !prev)} diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index 4d4c4a77d..d6a507247 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -36,8 +36,11 @@ const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: }, [existIndexInStepList]); useEffect(() => { - // 최초로 빈 stepList가 생성되고 난 후, 다시 hasAddedItem을 false로 변환하기 위한 조건문 - if (hasAddedItem) setHasAddedItem(prev => !prev); + if (hasAddedItem) { + setHasAddedItem(false); + + setStepList(prev => [...prev.filter(({actions}) => actions.length !== 0)]); + } if (isAddEditableItem && lastBillItemIndex !== lastItemIndex && !hasAddedItem) { setStepList(prev => [ @@ -51,7 +54,7 @@ const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: ]); setHasAddedItem(prev => !prev); } - }, [isAddEditableItem, lastBillItemIndex, lastItemIndex, hasAddedItem, existIndexInStepList, stepListData]); + }, [isAddEditableItem]); return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx index 01febb517..452add193 100644 --- a/client/src/hooks/useDynamicInput.tsx +++ b/client/src/hooks/useDynamicInput.tsx @@ -21,6 +21,7 @@ export type ReturnUseDynamicInput = { getFilledInputList: (list?: InputValue[]) => InputValue[]; focusNextInputOnEnter: (e: React.KeyboardEvent<HTMLInputElement>, index: number) => void; setInputValueTargetIndex: (index: number, value: string) => void; + resetInputValue: () => void; }; const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { @@ -96,6 +97,10 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return }); }; + const resetInputValue = () => { + setInputList(initialInputList); + }; + const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => { if (e.nativeEvent.isComposing) return; @@ -130,6 +135,7 @@ const useDynamicInput = (validateFunc: (name: string) => ValidateResult): Return getFilledInputList, focusNextInputOnEnter, setInputValueTargetIndex, + resetInputValue, }; }; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx index 2754a140d..78c29ee03 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx @@ -172,8 +172,6 @@ describe('useMemberReportListInActionTest', () => { result.current.addAdjustedMember(adjustedMemberMangcho); }); - console.log(result.current.memberReportListInAction); - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); expect(targetMember?.price).toBe(300); diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index eda5a3f81..02241d3e3 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -44,7 +44,7 @@ const useSetAllMemberList = ({ const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); - const {mutate: deleteAllMemberList} = useDeleteAllMemberList(); + const {mutateAsync: deleteAllMemberList} = useDeleteAllMemberList(); const {mutate: putAllMemberList} = usePutAllMemberList(); const editedAllMemberList = inputList.map(input => input.value); @@ -71,7 +71,7 @@ const useSetAllMemberList = ({ // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) if (deleteMemberList.length > 0) { for (const deleteMember of deleteMemberList) { - deleteAllMemberList({memberName: deleteMember}); + await deleteAllMemberList({memberName: deleteMember}); } } @@ -83,7 +83,7 @@ const useSetAllMemberList = ({ return null; // 조건에 맞지 않으면 null을 반환 }) .filter(item => item !== null); // null인 항목을 필터링하여 제거 - putAllMemberList({members: editedMemberName}); + if (!isArraysEqual(editedAllMemberList, deleteInOriginal)) putAllMemberList({members: editedMemberName}); handleCloseAllMemberListModal(); }; From d67f564165115221209a85431e417498e1ddbf6b Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Fri, 23 Aug 2024 04:14:21 +0900 Subject: [PATCH 219/273] =?UTF-8?q?fix:=20build=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=97=86=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20import=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20(#513)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: default 값이 빈문자열로 변경 * chore: build를 방해하는 import 제거 --- client/src/components/StepList/BillStepItem.tsx | 2 +- client/src/pages/MainPage/Nav/Nav.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 9a9ff4f7f..7fed9ef5c 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -116,7 +116,7 @@ const BillStepItem: React.FC<BillStepItemProps> = ({ <EditableItem.Input placeholder="0" type="number" - value={billInput.price ?? null} + value={billInput.price || ''} onChange={e => handleChangeBillInput('price', e)} style={{textAlign: 'right'}} ></EditableItem.Input> diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index 96bad9741..ec4d745c9 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -1,6 +1,5 @@ import {Button, Flex, Text} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; -import HeundeutLoto from '@components/Common/Logo/HeunDeutLogo'; import Heundeut from '@assets/image/heundeut.svg'; From e29e3007c6b857f4dc5f142667d3dbb848828cd4 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:49:35 +0900 Subject: [PATCH 220/273] =?UTF-8?q?fix:=20og=20tag=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=ED=95=B4=EC=83=81=EB=8F=84=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?(#515)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/index.html b/client/index.html index 12be549a7..4a21293f2 100644 --- a/client/index.html +++ b/client/index.html @@ -11,7 +11,7 @@ <meta property="og:description" content="행동대장으로 간편하게 정산하세요" /> <meta property="og:image" - content="https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%9B%A8%EB%94%94%286%EA%B8%B0%29/g583lirp8yg.jpg" + content="https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%BF%A0%ED%82%A4%286%EA%B8%B0%29/4tyq1x19rsn.jpg" /> <meta property="og:image:type" content="image/png" /> <meta property="og:image:alt" content="행댕이" /> From b53fc53ee0fa37c4643eda1aa57053d0ed147dd0 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 23 Aug 2024 10:06:52 +0900 Subject: [PATCH 221/273] =?UTF-8?q?feat:=20=ED=96=89=EB=8F=99=EB=8C=80?= =?UTF-8?q?=EC=9E=A5=20v1.0.0=20(#516)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe <pigkill40@naver.com> * design: 기본 css style 초기화 작업 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * design: 전역 스타일링 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우터 셋팅 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 앱의 진입점 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우트 경로 설정 Co-authored-by: pakxe <pigkill40@naver.com> * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 인원 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Input component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Title component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: BottomSheet component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 메서드 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 코드 컨벤션 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: 메서드 순서 변경 Co-authored-by: Arachne <jhg2819@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> authored-by: khabh <khabh@naver.com> * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 <rhymint@gmail.com> * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * refactor: global style app과 index에 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> --------- Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * style: lint 적용 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers<HTMLElement>' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * feat: BottomSheet 지출 부분 삭제 & input autoFocus (#433) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe <pigkill40@naver.com> * design: 기본 css style 초기화 작업 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * design: 전역 스타일링 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우터 셋팅 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 앱의 진입점 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우트 경로 설정 Co-authored-by: pakxe <pigkill40@naver.com> * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 인원 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Input component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Title component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: BottomSheet component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 메서드 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 코드 컨벤션 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: 메서드 순서 변경 Co-authored-by: Arachne <jhg2819@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> authored-by: khabh <khabh@naver.com> * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 <rhymint@gmail.com> * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * refactor: global style app과 index에 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> --------- Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * style: lint 적용 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers<HTMLElement>' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * fix: 사용하지 않는 지출 Modal Input 삭제 * remove: 지출 추가 로직 변경으로 인해 사용하지 않는 파일 제거 * feat: 첫번째 Input에 focus 적용 * feat: 첫번째 DynamicInput에 autoFocus 적용 * fix: StepListProps 속성이 없어서 발생하는 에러 해결 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: juha <khabh@naver.com> Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * fix: height가 짤리는 버그 해결 (#434) * fix: 차등 적용 인원이 2명일 때 계산되지 않는 버그 (#435) * fix: 나머지 1명만 조정치가 아닐 때 계산이 되지 않았던 버그 수정 * test: 2명일 때의 테스트 진행 * fix: 마지막 사람이 값이 변경될 수 없으므로 (input = disabled 처리) 관련 로직 훅에서 제거 * test: 발생할 수 없는 테스트 제거 * feat: 랜딩페이지 구현 (#418) * feat: 랜딩페이지 구현 * style: lint 적용 * fix: 문구 수정 * style: lint 적용 * fix: 랜딩페이지 화면의 변화에 따른 e2e 테스트 코드 변경 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> * fix: 랜딩페이지 Nav 버그 수정 (#438) * chore: 사용하지 않는 import 제거 * fix: maxWidth를 추가하여 데스크탑에서 Nav가 정상적으로 렌더링되도록 수정 * fix: totalPrice를 새로운 입력값으로 넘겨주지 않았던 문제 해결 (#442) * fix: 배경색상 height 버그 (#443) * chore: 사용하지 않는 코드 제거 * fix: 배경 heigth가 잘리는 문제를 background color를 넣어 해결 * fix: 백그라운드 수정 (#447) * fix: 멤버가 변동됐을 때 지출 상세 정보 데이터가 날라가지 않는 버그 수정 (#448) * fix: 차등 정산 모달에서 수정 완료 버튼을 누를 때 보내는 2개의 api의 순서를 보장하고 변동이 없으면 요청을 보내지 않도록 함 (#455) * feat: callback을 넘겨받아 api 요청 순서를 보장할 수 있도록 함 * fix: 지출 내역을 수정하고 나서 정상 응답이 와야 차등 정산 요청을 보내도록 함 * feat: 변경이 발생한 것에 대해서만 요청이 가도록 수정 * feat: 모달 자동 닫히도록 onClose전달 * feat: onClose를 전달해 모달을 닫는 함수를 스스로 호출하도록 함 * test: 훅에서 받는 인자가 수정되었으므로 이를 반영 * feat: onSuccessCallBack 을 없앰 * feat: Step에 stepName 반영하기 (#452) * feat: 서버로 부터 받은 stepName 출력 * feat: 마지막 action의 stepName에서 1을 더한 값을 새로 생성한 stepName에 넣기 * chore: 백엔드의 요청으로 인해 인원수 click시 BottomSheet가 띄워지지 않도록 주석처리 * fix: async, await 이 없어서 api 순서 보장이 안되기 때문에 추가 (#462) * [FE] 지출 Input 금액 default 변경 및 autoFocus (#470) * feat: 지출 내역 금액 default가 0이 아닌 ‘’로 변경 * feat: 지출 내역을 추가하면 title에 autoFocus * feat: enter 키를 눌렀을 때 handleBlurBillRequest가 실행되는 기능 추가 * feat: StepList에 isFixed 디자인시스템 반영 (#465) * chore: v0.1.77 배포 * chore: 디자인 시스템 적용 * fix: 변동된 금액인지를 나타내는 isFixed prop 추가 * feat: 차등 정산 적용시 신선한 데이터가 바로 반영되지 않고 시간차를 두고 반영되는 부분 수정 (#458) * feat: 차등 정산 내용이 수정되었을 경우 낙관적 업데이트 적용 * feat: any제거하고 타입 적용 * fix: 차등정산 수정 후 다시 로드 시 깜빡이는 현상 해결 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> * feat: 관리자 로그인 페이지에서 스위치가 관리로 활성화되지 않는 버그 (#469) * fix: 관리페이지 로그인에서도 top nav 관리 탭으로 활성화 되도록 수정 * refactor: useEventLogin으로 훅 분리 * fix: 배경 색이 잘리는 문제 해결 (#466) * design: 생성 페이지 background 설정 * design: 메인 레이아웃 light gray 색 추가 * design: 홈페이지 padding bottom 2rem 추가 * design: root의 height auto로 설정 및 배경색 제거 * design: 효과없는 height 100% 제거 * design: 바텀시트 삭제로 어드민 페이지 패딩 바텀 조정 * feat: Flex prop min height 속성 추가, 알고보니 min-height 속성이 있어야 화면이 꽉 채워짐 * feat: title과 price에 값이 존재하지 않을 경우 지출 input 닫기 (#472) * feat: 디자인시스템 일부 수정 (#475) * design: 통일성 위해 디자인 수정 * chore: v0.1.78 배포 * chore: hdesign 0.1.78 적용 * chore: v0.1.79 배포 및 적용 * feat: 버튼 로딩 구현 및 이벤트 생성 페이지에 적용 (#476) * design: 통일성 위해 디자인 수정 * chore: v0.1.78 배포 * chore: hdesign 0.1.78 적용 * chore: v0.1.79 배포 및 적용 * chore: lottie-react dependency 추가 * chore: json file 읽을 수 있도록 설정 * feat: button의 loading variants 추가 * chore: v0.1.80 배포 * chore: hdesign 신규 버전 적용 * feat: 행사 생성이 pending 상태이면 button isLoading으로 변경 * style: lint 적용 * chore: lottie-react import ignore 하도록 변경 * fix: lottie-react를 mocking하여 lottie가 렌더링 시 테스트가 실패하지 않도록 변경 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * fix: 행사 생성 완료 페이지 변경 (#478) * fix: placeholder 추가 (#480) * fix: 지출 내역 금액 부분에 문자가 입력되던 오류 수정 (#491) * fix: dropdown animation 버그 수정 (#493) * chore: React-Query devtools 환경 설정 (#463) * chore: devtools 설치 * chore: stale time, gctime 셋팅 임시로 1분 설정 * chore: amplitude 적용 (#335) * feat: react-query에 맞는 error handling 적용 (#415) * chore: 디자인시스템 버전 적용 * rename: 파일 이름 변경 * fix: 사용하지 않는 Error 처리 로직 삭제 * feat: 전역 에러 상태 생성 * fix: 바뀐 파일 이름 적용 * fix: ToastProvider 내에서 에러 처리 로직 제거 * refactor: AppErrorBoundary 및 QueryClientBoundary를 통한 에러 처리 * fix: 사용하지 않는 코드 임시적으로 주석 처리 TODO: 테스트 코드 역할 위임 * mover: AppErrorBoundary, QueryClientBoundary 코드 위치 변경 * fix: test 코드 변경 * chore: jest path alias 적용 * test: AppErrorBoundary 테스트코드 작성 * remove: 사용하지 않는 코드 삭제 * fix: 사용하지 않는 코드 주석처리 * fix: AppErrorBoundary, QueryClientBoundary 로직 수정 * test: AppErrorBoundary test코드 작성 * style: lint 적용 * feat: App에 ErrorBoundary 추가 * feat: UnhandledErrorBoundary 컴포넌트 구현 * feat: 에러를 구독하며 핸들링되는 에러면 토스트, 핸들링 불가능한 에러면 에러 바운더리를 띄우도록 하는 캐처 구현 * feat: 에러 페이지에 메일 추가 * feat: errorInfo를 안에서 구현하는 것이 아닌 구현된 것을 인자로 받도록 수정 * chore: 파일 위치 수정에 따라 import 경로 수정 * chore: 불필요해진 파일 제거 * chore: 개행 추가 * feat: ErrorCatcher에 대한 테스트 코드 작성 * feat: Toast의 showingTime 을 옵셔널로 수정 * chore: 없어진 컴포넌트를 renderHook에서 제거 * refactor: return문이 반복되는 부분을 리펙터링 * feat: useToast에 대한 테스트코드 작성 * chore: 사용하지 않는 파일 제거 * chore: 불필요한 파일이 커버리지에 뜨지 않도록 ignore에 추가 * rename: 파일명 오타 수정 * chore: import 경로 수정 * chore: 병힙 * chore: 라이브러리 오류로 인해 테스트 통과가 안되므로 디자인 시스템 라이브러리 다운그레이드 --------- Co-authored-by: pakxe <pigkill40@naver.com> * fix: 로딩 라이브러리 도입으로 인해 테스트가 터지는 문제를 해결 (#501) * fix: canvas를 로딩하기 위한 라이브러리 설치후 jest.setup에 적용 * chore: 불필요한 import 제거 * feat: 비밀번호 4자리 넘게 적용되는 오류 수정 (#503) * chore: v0.1.81 배포 * fix: 비밀번호 4자리 넘게 입력 가능한 오류 수정 * fix: BottomSheet가 조건부 렌더링 되도록 변경 (#506) * feat: 홈페이지에서 지출 내역 눌렀을 때 차등 정산 모달 뜨기 (#507) * feat: 홈화면에서 지출 내역 상세 모달이 뜨도록 함 * chore: 사용하지 않는 코드 제거 * feat: 행동대장 흔듯콘(파비콘), 로고 적용 (#496) * feat: 새로운 행동 강아지 삽입 * feat: favicon 적용 * fix: 흔듯콘 logo에 사용 * style: lint 적용 --------- Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: meta tag 링크 복사 이미지와 설명 추가 (#510) * feat: og tag 설정 (링크 붙여넣기 할 때 이미지와 소개글 나오도록 설정) * feat: 행댕이 이미지 삽입 * feat: description 수정 * fix: 지출 내역 및 전체 참여자 버그 (#511) * fix: 전체 참여자 삭제 후 수정 요청 순서 보장 * fix: 이름 변경 수정이 존재하지 않는 상황에서도 nameChange api 요청이 전송되지 않도록 수정 * fix: 현재 필요하지 않는 hasDragHandler를 false로 변경 * fix: 인원 변동 요청을 한 후 input에 value 값이 초기화 되지 않는 버그 해결 * fix: bill 액션이 없는 상태에서 BillInput을 닫을 때 BillContainer가 사리지지 않는 버그 해결 * chore: console.log 삭제 * fix: build를 위한 없는 파일 import 제거 (#513) * fix: default 값이 빈문자열로 변경 * chore: build를 방해하는 import 제거 * fix: og tag 이미지 해상도 변경 (#515) --------- Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: juha <khabh@naver.com> Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> --- .github/workflows/design-pull-request.yml | 54 + .github/workflows/frontend-pull-request.yml | 49 + .github/workflows/pr-issue-close.yml | 33 + HDesign/.gitignore | 12 + HDesign/.npmignore | 7 + HDesign/.npmrc | 2 + HDesign/.prettierrc | 12 + HDesign/.storybook/main.ts | 47 + HDesign/.storybook/preview.tsx | 41 + HDesign/eslint.config.mjs | 153 + HDesign/package-lock.json | 13707 +++++++++++ HDesign/package.json | 72 + HDesign/src/assets/buljusa.svg | 4 + HDesign/src/assets/confirm.svg | 10 + HDesign/src/assets/error.svg | 10 + HDesign/src/assets/index.ts | 7 + HDesign/src/assets/inputDelete.svg | 10 + HDesign/src/assets/loadingAnimation.json | 1176 + HDesign/src/assets/rightChevron.svg | 3 + HDesign/src/assets/search.svg | 3 + HDesign/src/assets/svg.d.ts | 6 + HDesign/src/assets/trash.svg | 3 + .../BottomSheet/BottomSheet.stories.tsx | 33 + .../BottomSheet/BottomSheet.style.ts | 60 + .../components/BottomSheet/BottomSheet.tsx | 55 + .../BottomSheet/BottomSheet.type.ts | 17 + .../components/BottomSheet/useBottomSheet.ts | 87 + .../src/components/Button/Button.stories.tsx | 40 + HDesign/src/components/Button/Button.style.ts | 113 + HDesign/src/components/Button/Button.tsx | 47 + HDesign/src/components/Button/Button.type.ts | 16 + .../DragHandleItem/DragHandleItem.stories.tsx | 51 + .../DragHandleItem/DragHandleItem.style.ts | 20 + .../DragHandleItem/DragHandleItem.tsx | 44 + .../DragHandleItem/DragHandleItem.type.ts | 19 + .../DragHandleItemContainer.stories.tsx | 90 + .../DragHandleItemContainer.style.ts | 34 + .../DragHandleItemContainer.tsx | 47 + .../DragHandleItemContainer.type.ts | 20 + .../EditableItem/EditableItem.Input.style.ts | 84 + .../EditableItem/EditableItem.Input.tsx | 54 + .../EditableItem/EditableItem.Input.type.ts | 22 + .../EditableItem/EditableItem.context.tsx | 23 + .../EditableItem.input.stories.tsx | 45 + .../EditableItem/EditableItem.stories.tsx | 276 + .../EditableItem/EditableItem.style.ts | 21 + .../components/EditableItem/EditableItem.tsx | 54 + .../EditableItem/EditableItem.type.ts | 22 + .../EditableItem/useEditableItem.ts | 23 + .../EditableItem/useEditableItemInput.ts | 46 + .../ExpenseList/ExpenseList.stories.tsx | 29 + .../ExpenseList/ExpenseList.style.ts | 29 + .../components/ExpenseList/ExpenseList.tsx | 37 + .../ExpenseList/ExpenseList.type.ts | 10 + .../FixedButton/FixedButton.stories.tsx | 46 + .../FixedButton/FixedButton.style.ts | 127 + .../components/FixedButton/FixedButton.tsx | 48 + .../FixedButton/FixedButton.type.ts | 16 + HDesign/src/components/Flex/Flex.style.ts | 49 + HDesign/src/components/Flex/Flex.tsx | 17 + HDesign/src/components/Flex/Flex.type.ts | 20 + HDesign/src/components/Icon/Icon.stories.tsx | 28 + HDesign/src/components/Icon/Icon.style.ts | 38 + HDesign/src/components/Icon/Icon.tsx | 29 + HDesign/src/components/Icon/Icon.type.ts | 21 + .../IconButton/IconButton.stories.tsx | 51 + .../components/IconButton/IconButton.style.ts | 102 + .../src/components/IconButton/IconButton.tsx | 22 + .../components/IconButton/IconButton.type.ts | 19 + .../src/components/Input/Input.stories.tsx | 56 + HDesign/src/components/Input/Input.style.ts | 56 + HDesign/src/components/Input/Input.tsx | 51 + HDesign/src/components/Input/Input.type.ts | 16 + HDesign/src/components/Input/useInput.ts | 71 + .../IsFixedIcon/IsFixedIcon.style.ts | 9 + .../components/IsFixedIcon/IsFixedIcon.tsx | 13 + .../components/LabelGroupInput/Element.tsx | 63 + .../LabelGroupInput/Element.type.ts | 10 + .../LabelGroupInput/GroupInputContext.tsx | 32 + .../LabelGroupInput.stories.tsx | 75 + .../LabelGroupInput/LabelGroupInput.style.ts | 25 + .../LabelGroupInput/LabelGroupInput.tsx | 48 + .../LabelGroupInput/LabelGroupInput.type.ts | 10 + .../src/components/LabelGroupInput/index.ts | 3 + .../LabelInput/LabelInput.stories.tsx | 56 + .../components/LabelInput/LabelInput.style.ts | 25 + .../src/components/LabelInput/LabelInput.tsx | 45 + .../components/LabelInput/LabelInput.type.ts | 12 + .../components/LabelInput/useLabelInput.ts | 26 + .../ListButton/ListButton.stories.tsx | 32 + .../components/ListButton/ListButton.style.ts | 16 + .../src/components/ListButton/ListButton.tsx | 36 + .../components/ListButton/ListButton.type.ts | 10 + .../src/components/Search/Search.stories.tsx | 32 + HDesign/src/components/Search/Search.style.ts | 42 + HDesign/src/components/Search/Search.tsx | 37 + .../src/components/Switch/Switch.stories.tsx | 35 + HDesign/src/components/Switch/Switch.style.ts | 6 + HDesign/src/components/Switch/Switch.tsx | 24 + HDesign/src/components/Switch/Switch.type.ts | 5 + HDesign/src/components/Tabs/Tab.tsx | 8 + HDesign/src/components/Tabs/Tab.type.ts | 16 + HDesign/src/components/Tabs/Tabs.stories.tsx | 31 + HDesign/src/components/Tabs/Tabs.style.ts | 53 + HDesign/src/components/Tabs/Tabs.tsx | 53 + HDesign/src/components/Text/Text.stories.tsx | 40 + HDesign/src/components/Text/Text.style.ts | 29 + HDesign/src/components/Text/Text.tsx | 19 + HDesign/src/components/Text/Text.type.ts | 30 + .../TextButton/TextButton.stories.tsx | 50 + .../components/TextButton/TextButton.style.ts | 10 + .../src/components/TextButton/TextButton.tsx | 25 + .../components/TextButton/TextButton.type.ts | 15 + .../src/components/Title/Title.stories.tsx | 38 + HDesign/src/components/Title/Title.style.ts | 19 + HDesign/src/components/Title/Title.tsx | 34 + HDesign/src/components/Title/Title.type.ts | 11 + .../src/components/Toast/Toast.stories.tsx | 71 + HDesign/src/components/Toast/Toast.style.ts | 44 + HDesign/src/components/Toast/Toast.tsx | 73 + HDesign/src/components/Toast/Toast.type.ts | 21 + .../Toast/ToastProvider.stories.tsx | 46 + .../src/components/Toast/ToastProvider.tsx | 59 + HDesign/src/components/TopNav/Back.tsx | 17 + .../src/components/TopNav/TopNav.stories.tsx | 50 + HDesign/src/components/TopNav/TopNav.style.ts | 18 + HDesign/src/components/TopNav/TopNav.tsx | 20 + HDesign/src/index.tsx | 62 + HDesign/src/layouts/ContentLayout.tsx | 25 + HDesign/src/layouts/MainLayout.tsx | 26 + HDesign/src/theme/GlobalStyle.ts | 123 + HDesign/src/theme/HDesignProvider.tsx | 37 + HDesign/src/theme/theme.type.ts | 7 + HDesign/src/token/colors.ts | 109 + HDesign/src/token/typography.ts | 67 + HDesign/src/type/strictPropsWithChildren.ts | 3 + HDesign/src/type/withTheme.ts | 5 + .../src/utils/changeCamelCaseToKebabCase.ts | 3 + HDesign/src/utils/colors.ts | 88 + HDesign/tsconfig.json | 34 + client/.gitignore | 14 + client/.npmrc | 2 + client/.prettierrc | 12 + client/cypress.config.ts | 12 + client/cypress/constants/constants.ts | 6 + client/cypress/e2e/createEvent.cy.ts | 79 + client/cypress/fixtures/postEvent.json | 3 + client/cypress/support/commands.ts | 58 + client/cypress/support/e2e.ts | 1 + client/eslint.config.mjs | 112 + client/favicon.ico | Bin 0 -> 44932 bytes client/index.html | 33 + client/jest.config.ts | 49 + client/jest.polyfills.ts | 20 + client/jest.setup.ts | 24 + client/package-lock.json | 19037 ++++++++++++++++ client/package.json | 85 + client/public/mockServiceWorker.js | 281 + client/src/App.tsx | 31 + client/src/GlobalStyle.ts | 160 + client/src/UnhandledErrorBoundary.tsx | 10 + client/src/apis/baseUrl.ts | 3 + client/src/apis/fetcher.ts | 120 + client/src/apis/request/auth.ts | 25 + client/src/apis/request/bill.ts | 69 + client/src/apis/request/event.ts | 32 + client/src/apis/request/member.ts | 84 + client/src/apis/request/report.ts | 19 + client/src/apis/request/stepList.ts | 17 + client/src/apis/tempPrefix.ts | 2 + client/src/apis/withEventId.type.ts | 3 + client/src/assets/image/addBillMockup.svg | 312 + client/src/assets/image/addMemberMockup.svg | 317 + client/src/assets/image/chevronDownLarge.svg | 3 + client/src/assets/image/dog.svg | 49 + client/src/assets/image/heundeut.svg | 1 + .../src/assets/image/memberReportMockup.svg | 311 + client/src/assets/image/runningDog.svg | 9 + client/src/assets/image/standingDog.svg | 9 + .../AppErrorBoundary/ErrorCatcher.test.tsx | 92 + .../AppErrorBoundary/ErrorCatcher.tsx | 62 + .../src/components/Common/Logo/Logo.style.ts | 8 + .../components/Common/Logo/RunningDogLogo.tsx | 13 + .../Common/Logo/StandingDogLogo.tsx | 13 + client/src/components/Common/Logo/index.ts | 2 + .../MemberReportList/MemberReportList.tsx | 22 + .../ExpenseDetailModal/ExpenseDetailModal.tsx | 142 + .../MemberListInBillStep.style.ts | 10 + .../MemberListInBillStep.tsx | 53 + .../Modal/MemberListInBillStep/index.ts | 1 + .../ModalBasedOnMemberCount.tsx | 39 + .../AddMemberActionListModalContent.style.ts | 23 + .../AddMemberActionListModalContent.tsx | 50 + .../InMember.tsx | 35 + .../OutMember.tsx | 52 + .../AddMemberActionListModalContent/index.ts | 1 + .../DeleteMemberActionModal.style.ts | 27 + .../DeleteMemberActionModal.tsx | 88 + .../DeleteMemberActionModal/index.ts | 1 + .../PutAndDeleteBillActionModal.tsx | 149 + .../PutAndDeltetBillActionModal.style.ts | 28 + .../PutAndDeleteBillActionModal/index.ts | 1 + .../SetActionListModal.style.ts | 20 + .../SetActionModal/SetActionListModal.tsx | 42 + .../components/Modal/SetActionModal/index.ts | 1 + .../SetAllMemberListModal.style.ts | 36 + .../SetAllMemberListModal.tsx | 80 + .../SetInitialMemberListModal.style.ts | 20 + .../SetInitialMemberListModal.tsx | 66 + .../Modal/SetInitialMemberListModal/index.ts | 1 + client/src/components/Modal/index.ts | 4 + .../QueryClientBoundary.tsx | 24 + .../src/components/StepList/BillStepItem.tsx | 138 + .../components/StepList/MemberStepItem.tsx | 38 + client/src/components/StepList/Step.tsx | 51 + client/src/components/StepList/StepList.tsx | 76 + client/src/components/Toast/Toast.style.ts | 65 + client/src/components/Toast/Toast.tsx | 75 + client/src/components/Toast/Toast.type.ts | 22 + client/src/constants/errorMessage.ts | 49 + client/src/constants/password.ts | 1 + client/src/constants/queryKeys.ts | 10 + client/src/constants/regExp.ts | 8 + client/src/constants/routerUrls.ts | 10 + client/src/constants/rule.ts | 8 + client/src/errors/FetchError.ts | 23 + client/src/global.d.ts | 11 + .../queries/useRequestDeleteAllMemberList.ts | 28 + .../queries/useRequestDeleteBillAction.ts | 26 + .../queries/useRequestDeleteMemberAction.ts | 28 + .../queries/useRequestGetAllMemberList.ts | 18 + .../useRequestGetCurrentInMemberList.ts | 18 + .../hooks/queries/useRequestGetEventName.ts | 18 + .../queries/useRequestGetMemberReportList.ts | 17 + .../useRequestGetMemberReportListInAction.ts | 24 + .../hooks/queries/useRequestGetStepList.ts | 30 + .../queries/useRequestPostAuthentication.ts | 23 + .../hooks/queries/useRequestPostBillList.ts | 27 + .../src/hooks/queries/useRequestPostEvent.ts | 16 + .../src/hooks/queries/useRequestPostLogin.ts | 26 + .../hooks/queries/useRequestPostMemberList.ts | 37 + .../queries/useRequestPutAllMemberList.ts | 28 + .../hooks/queries/useRequestPutBillAction.ts | 29 + .../useRequestPutMemberReportListInAction.ts | 49 + .../useDeleteMemberAction.test.tsx | 139 + .../useDeleteMemberAction.tsx | 86 + client/src/hooks/useDynamicInput.tsx | 142 + client/src/hooks/useEventLogin.ts | 42 + client/src/hooks/useInput.tsx | 97 + .../useMemberReportInput.tsx | 89 + .../useMemberReportListInAction.test.tsx | 327 + .../useMemberReportListInAction.ts | 156 + client/src/hooks/useNavSwitch.tsx | 42 + client/src/hooks/usePutAndDeleteBillAction.ts | 113 + client/src/hooks/useSearchInMemberList.ts | 54 + .../useSearchMemberReportList.test.tsx | 41 + .../useSearchMemberReportList.tsx | 16 + client/src/hooks/useSetAllMemberList.tsx | 100 + client/src/hooks/useSetBillInput.ts | 67 + client/src/hooks/useSetEventNamePage.ts | 32 + client/src/hooks/useSetEventPasswordPage.ts | 60 + client/src/hooks/useToast/ToastProvider.tsx | 47 + client/src/hooks/useToast/useToast.test.tsx | 80 + client/src/hooks/useToast/useToast.tsx | 13 + client/src/index.tsx | 32 + client/src/mocks/browser.ts | 5 + client/src/mocks/handlers.ts | 15 + client/src/mocks/handlers/authHandlers.ts | 104 + client/src/mocks/handlers/eventHandlers.ts | 55 + .../handlers/memberReportInActionHandlers.ts | 49 + client/src/mocks/handlers/reportHandlers.ts | 13 + client/src/mocks/handlers/stepListHandler.ts | 113 + client/src/mocks/handlers/testHandlers.ts | 23 + client/src/mocks/invalidMemberStepList.json | 100 + client/src/mocks/memberActionStepList.json | 23 + .../src/mocks/memberReportListInAction.json | 6 + client/src/mocks/memberReportSearchList.json | 10 + client/src/mocks/reportList.json | 18 + client/src/mocks/server.ts | 5 + client/src/mocks/serverConstants.ts | 4 + client/src/mocks/stepList.json | 100 + client/src/mocks/svg.ts | 2 + client/src/mocks/validValueForTest.ts | 4 + .../CompleteCreateEventPage.tsx | 29 + .../CreateEventPage/SetEventNamePage.tsx | 42 + .../CreateEventPage/SetEventPasswordPage.tsx | 41 + client/src/pages/CreateEventPage/index.ts | 3 + client/src/pages/ErrorPage/ErrorPage.tsx | 14 + .../EventPage/AdminPage/AdminPage.style.ts | 23 + .../pages/EventPage/AdminPage/AdminPage.tsx | 90 + .../EventPage/AdminPage/EventLoginPage.tsx | 35 + client/src/pages/EventPage/AdminPage/index.ts | 1 + .../src/pages/EventPage/EventPageLayout.tsx | 65 + .../src/pages/EventPage/HomePage/HomePage.tsx | 26 + client/src/pages/EventPage/HomePage/index.ts | 1 + client/src/pages/EventPage/index.ts | 1 + client/src/pages/MainPage/MainPage.tsx | 23 + client/src/pages/MainPage/Nav/Nav.style.ts | 22 + client/src/pages/MainPage/Nav/Nav.tsx | 27 + .../pages/MainPage/Section/AddBillSection.tsx | 31 + .../MainPage/Section/AddMemberSection.tsx | 33 + .../MainPage/Section/DescriptionSection.tsx | 33 + .../pages/MainPage/Section/MainSection.tsx | 93 + .../MainPage/Section/MemberReportSection.tsx | 31 + client/src/pages/MainPage/index.ts | 1 + client/src/router.tsx | 58 + client/src/store/appErrorStore.ts | 14 + client/src/store/stepListStore.ts | 16 + client/src/store/totalExpenseAmountStore.ts | 18 + client/src/types/fetchErrorType.ts | 11 + client/src/types/serviceType.ts | 80 + client/src/utils/caculateExpense.ts | 14 + client/src/utils/captureError.ts | 49 + client/src/utils/getEventIdByUrl.ts | 13 + .../src/utils/getEventPageUrlByEnvironment.ts | 11 + client/src/utils/groupActions.ts | 27 + client/src/utils/isArraysEqual.ts | 16 + client/src/utils/objectToQueryString.ts | 9 + client/src/utils/sendLogToSentry.ts | 66 + client/src/utils/stepListToActions.ts | 23 + client/src/utils/validate/type.ts | 5 + .../src/utils/validate/validateEventName.ts | 13 + .../utils/validate/validateEventPassword.ts | 13 + .../src/utils/validate/validateMemberName.ts | 34 + .../validate/validateMemberReportInAction.ts | 33 + client/src/utils/validate/validatePurchase.ts | 47 + client/tsconfig.json | 53 + client/webpack.common.mjs | 60 + client/webpack.dev.mjs | 33 + client/webpack.prod.mjs | 31 + 330 files changed, 47571 insertions(+) create mode 100644 .github/workflows/design-pull-request.yml create mode 100644 .github/workflows/frontend-pull-request.yml create mode 100644 .github/workflows/pr-issue-close.yml create mode 100644 HDesign/.gitignore create mode 100644 HDesign/.npmignore create mode 100644 HDesign/.npmrc create mode 100644 HDesign/.prettierrc create mode 100644 HDesign/.storybook/main.ts create mode 100644 HDesign/.storybook/preview.tsx create mode 100644 HDesign/eslint.config.mjs create mode 100644 HDesign/package-lock.json create mode 100644 HDesign/package.json create mode 100644 HDesign/src/assets/buljusa.svg create mode 100644 HDesign/src/assets/confirm.svg create mode 100644 HDesign/src/assets/error.svg create mode 100644 HDesign/src/assets/index.ts create mode 100644 HDesign/src/assets/inputDelete.svg create mode 100644 HDesign/src/assets/loadingAnimation.json create mode 100644 HDesign/src/assets/rightChevron.svg create mode 100644 HDesign/src/assets/search.svg create mode 100644 HDesign/src/assets/svg.d.ts create mode 100644 HDesign/src/assets/trash.svg create mode 100644 HDesign/src/components/BottomSheet/BottomSheet.stories.tsx create mode 100644 HDesign/src/components/BottomSheet/BottomSheet.style.ts create mode 100644 HDesign/src/components/BottomSheet/BottomSheet.tsx create mode 100644 HDesign/src/components/BottomSheet/BottomSheet.type.ts create mode 100644 HDesign/src/components/BottomSheet/useBottomSheet.ts create mode 100644 HDesign/src/components/Button/Button.stories.tsx create mode 100644 HDesign/src/components/Button/Button.style.ts create mode 100644 HDesign/src/components/Button/Button.tsx create mode 100644 HDesign/src/components/Button/Button.type.ts create mode 100644 HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx create mode 100644 HDesign/src/components/DragHandleItem/DragHandleItem.style.ts create mode 100644 HDesign/src/components/DragHandleItem/DragHandleItem.tsx create mode 100644 HDesign/src/components/DragHandleItem/DragHandleItem.type.ts create mode 100644 HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx create mode 100644 HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts create mode 100644 HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx create mode 100644 HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts create mode 100644 HDesign/src/components/EditableItem/EditableItem.Input.style.ts create mode 100644 HDesign/src/components/EditableItem/EditableItem.Input.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.Input.type.ts create mode 100644 HDesign/src/components/EditableItem/EditableItem.context.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.input.stories.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.stories.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.style.ts create mode 100644 HDesign/src/components/EditableItem/EditableItem.tsx create mode 100644 HDesign/src/components/EditableItem/EditableItem.type.ts create mode 100644 HDesign/src/components/EditableItem/useEditableItem.ts create mode 100644 HDesign/src/components/EditableItem/useEditableItemInput.ts create mode 100644 HDesign/src/components/ExpenseList/ExpenseList.stories.tsx create mode 100644 HDesign/src/components/ExpenseList/ExpenseList.style.ts create mode 100644 HDesign/src/components/ExpenseList/ExpenseList.tsx create mode 100644 HDesign/src/components/ExpenseList/ExpenseList.type.ts create mode 100644 HDesign/src/components/FixedButton/FixedButton.stories.tsx create mode 100644 HDesign/src/components/FixedButton/FixedButton.style.ts create mode 100644 HDesign/src/components/FixedButton/FixedButton.tsx create mode 100644 HDesign/src/components/FixedButton/FixedButton.type.ts create mode 100644 HDesign/src/components/Flex/Flex.style.ts create mode 100644 HDesign/src/components/Flex/Flex.tsx create mode 100644 HDesign/src/components/Flex/Flex.type.ts create mode 100644 HDesign/src/components/Icon/Icon.stories.tsx create mode 100644 HDesign/src/components/Icon/Icon.style.ts create mode 100644 HDesign/src/components/Icon/Icon.tsx create mode 100644 HDesign/src/components/Icon/Icon.type.ts create mode 100644 HDesign/src/components/IconButton/IconButton.stories.tsx create mode 100644 HDesign/src/components/IconButton/IconButton.style.ts create mode 100644 HDesign/src/components/IconButton/IconButton.tsx create mode 100644 HDesign/src/components/IconButton/IconButton.type.ts create mode 100644 HDesign/src/components/Input/Input.stories.tsx create mode 100644 HDesign/src/components/Input/Input.style.ts create mode 100644 HDesign/src/components/Input/Input.tsx create mode 100644 HDesign/src/components/Input/Input.type.ts create mode 100644 HDesign/src/components/Input/useInput.ts create mode 100644 HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts create mode 100644 HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx create mode 100644 HDesign/src/components/LabelGroupInput/Element.tsx create mode 100644 HDesign/src/components/LabelGroupInput/Element.type.ts create mode 100644 HDesign/src/components/LabelGroupInput/GroupInputContext.tsx create mode 100644 HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx create mode 100644 HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts create mode 100644 HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx create mode 100644 HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts create mode 100644 HDesign/src/components/LabelGroupInput/index.ts create mode 100644 HDesign/src/components/LabelInput/LabelInput.stories.tsx create mode 100644 HDesign/src/components/LabelInput/LabelInput.style.ts create mode 100644 HDesign/src/components/LabelInput/LabelInput.tsx create mode 100644 HDesign/src/components/LabelInput/LabelInput.type.ts create mode 100644 HDesign/src/components/LabelInput/useLabelInput.ts create mode 100644 HDesign/src/components/ListButton/ListButton.stories.tsx create mode 100644 HDesign/src/components/ListButton/ListButton.style.ts create mode 100644 HDesign/src/components/ListButton/ListButton.tsx create mode 100644 HDesign/src/components/ListButton/ListButton.type.ts create mode 100644 HDesign/src/components/Search/Search.stories.tsx create mode 100644 HDesign/src/components/Search/Search.style.ts create mode 100644 HDesign/src/components/Search/Search.tsx create mode 100644 HDesign/src/components/Switch/Switch.stories.tsx create mode 100644 HDesign/src/components/Switch/Switch.style.ts create mode 100644 HDesign/src/components/Switch/Switch.tsx create mode 100644 HDesign/src/components/Switch/Switch.type.ts create mode 100644 HDesign/src/components/Tabs/Tab.tsx create mode 100644 HDesign/src/components/Tabs/Tab.type.ts create mode 100644 HDesign/src/components/Tabs/Tabs.stories.tsx create mode 100644 HDesign/src/components/Tabs/Tabs.style.ts create mode 100644 HDesign/src/components/Tabs/Tabs.tsx create mode 100644 HDesign/src/components/Text/Text.stories.tsx create mode 100644 HDesign/src/components/Text/Text.style.ts create mode 100644 HDesign/src/components/Text/Text.tsx create mode 100644 HDesign/src/components/Text/Text.type.ts create mode 100644 HDesign/src/components/TextButton/TextButton.stories.tsx create mode 100644 HDesign/src/components/TextButton/TextButton.style.ts create mode 100644 HDesign/src/components/TextButton/TextButton.tsx create mode 100644 HDesign/src/components/TextButton/TextButton.type.ts create mode 100644 HDesign/src/components/Title/Title.stories.tsx create mode 100644 HDesign/src/components/Title/Title.style.ts create mode 100644 HDesign/src/components/Title/Title.tsx create mode 100644 HDesign/src/components/Title/Title.type.ts create mode 100644 HDesign/src/components/Toast/Toast.stories.tsx create mode 100644 HDesign/src/components/Toast/Toast.style.ts create mode 100644 HDesign/src/components/Toast/Toast.tsx create mode 100644 HDesign/src/components/Toast/Toast.type.ts create mode 100644 HDesign/src/components/Toast/ToastProvider.stories.tsx create mode 100644 HDesign/src/components/Toast/ToastProvider.tsx create mode 100644 HDesign/src/components/TopNav/Back.tsx create mode 100644 HDesign/src/components/TopNav/TopNav.stories.tsx create mode 100644 HDesign/src/components/TopNav/TopNav.style.ts create mode 100644 HDesign/src/components/TopNav/TopNav.tsx create mode 100644 HDesign/src/index.tsx create mode 100644 HDesign/src/layouts/ContentLayout.tsx create mode 100644 HDesign/src/layouts/MainLayout.tsx create mode 100644 HDesign/src/theme/GlobalStyle.ts create mode 100644 HDesign/src/theme/HDesignProvider.tsx create mode 100644 HDesign/src/theme/theme.type.ts create mode 100644 HDesign/src/token/colors.ts create mode 100644 HDesign/src/token/typography.ts create mode 100644 HDesign/src/type/strictPropsWithChildren.ts create mode 100644 HDesign/src/type/withTheme.ts create mode 100644 HDesign/src/utils/changeCamelCaseToKebabCase.ts create mode 100644 HDesign/src/utils/colors.ts create mode 100644 HDesign/tsconfig.json create mode 100644 client/.gitignore create mode 100644 client/.npmrc create mode 100644 client/.prettierrc create mode 100644 client/cypress.config.ts create mode 100644 client/cypress/constants/constants.ts create mode 100644 client/cypress/e2e/createEvent.cy.ts create mode 100644 client/cypress/fixtures/postEvent.json create mode 100644 client/cypress/support/commands.ts create mode 100644 client/cypress/support/e2e.ts create mode 100644 client/eslint.config.mjs create mode 100644 client/favicon.ico create mode 100644 client/index.html create mode 100644 client/jest.config.ts create mode 100644 client/jest.polyfills.ts create mode 100644 client/jest.setup.ts create mode 100644 client/package-lock.json create mode 100644 client/package.json create mode 100644 client/public/mockServiceWorker.js create mode 100644 client/src/App.tsx create mode 100644 client/src/GlobalStyle.ts create mode 100644 client/src/UnhandledErrorBoundary.tsx create mode 100644 client/src/apis/baseUrl.ts create mode 100644 client/src/apis/fetcher.ts create mode 100644 client/src/apis/request/auth.ts create mode 100644 client/src/apis/request/bill.ts create mode 100644 client/src/apis/request/event.ts create mode 100644 client/src/apis/request/member.ts create mode 100644 client/src/apis/request/report.ts create mode 100644 client/src/apis/request/stepList.ts create mode 100644 client/src/apis/tempPrefix.ts create mode 100644 client/src/apis/withEventId.type.ts create mode 100644 client/src/assets/image/addBillMockup.svg create mode 100644 client/src/assets/image/addMemberMockup.svg create mode 100644 client/src/assets/image/chevronDownLarge.svg create mode 100644 client/src/assets/image/dog.svg create mode 100644 client/src/assets/image/heundeut.svg create mode 100644 client/src/assets/image/memberReportMockup.svg create mode 100644 client/src/assets/image/runningDog.svg create mode 100644 client/src/assets/image/standingDog.svg create mode 100644 client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx create mode 100644 client/src/components/AppErrorBoundary/ErrorCatcher.tsx create mode 100644 client/src/components/Common/Logo/Logo.style.ts create mode 100644 client/src/components/Common/Logo/RunningDogLogo.tsx create mode 100644 client/src/components/Common/Logo/StandingDogLogo.tsx create mode 100644 client/src/components/Common/Logo/index.ts create mode 100644 client/src/components/MemberReportList/MemberReportList.tsx create mode 100644 client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx create mode 100644 client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts create mode 100644 client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx create mode 100644 client/src/components/Modal/MemberListInBillStep/index.ts create mode 100644 client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx create mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts create mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts create mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx create mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts create mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx create mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts create mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts create mode 100644 client/src/components/Modal/SetActionModal/SetActionListModal.style.ts create mode 100644 client/src/components/Modal/SetActionModal/SetActionListModal.tsx create mode 100644 client/src/components/Modal/SetActionModal/index.ts create mode 100644 client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts create mode 100644 client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx create mode 100644 client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts create mode 100644 client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx create mode 100644 client/src/components/Modal/SetInitialMemberListModal/index.ts create mode 100644 client/src/components/Modal/index.ts create mode 100644 client/src/components/QueryClientBoundary/QueryClientBoundary.tsx create mode 100644 client/src/components/StepList/BillStepItem.tsx create mode 100644 client/src/components/StepList/MemberStepItem.tsx create mode 100644 client/src/components/StepList/Step.tsx create mode 100644 client/src/components/StepList/StepList.tsx create mode 100644 client/src/components/Toast/Toast.style.ts create mode 100644 client/src/components/Toast/Toast.tsx create mode 100644 client/src/components/Toast/Toast.type.ts create mode 100644 client/src/constants/errorMessage.ts create mode 100644 client/src/constants/password.ts create mode 100644 client/src/constants/queryKeys.ts create mode 100644 client/src/constants/regExp.ts create mode 100644 client/src/constants/routerUrls.ts create mode 100644 client/src/constants/rule.ts create mode 100644 client/src/errors/FetchError.ts create mode 100644 client/src/global.d.ts create mode 100644 client/src/hooks/queries/useRequestDeleteAllMemberList.ts create mode 100644 client/src/hooks/queries/useRequestDeleteBillAction.ts create mode 100644 client/src/hooks/queries/useRequestDeleteMemberAction.ts create mode 100644 client/src/hooks/queries/useRequestGetAllMemberList.ts create mode 100644 client/src/hooks/queries/useRequestGetCurrentInMemberList.ts create mode 100644 client/src/hooks/queries/useRequestGetEventName.ts create mode 100644 client/src/hooks/queries/useRequestGetMemberReportList.ts create mode 100644 client/src/hooks/queries/useRequestGetMemberReportListInAction.ts create mode 100644 client/src/hooks/queries/useRequestGetStepList.ts create mode 100644 client/src/hooks/queries/useRequestPostAuthentication.ts create mode 100644 client/src/hooks/queries/useRequestPostBillList.ts create mode 100644 client/src/hooks/queries/useRequestPostEvent.ts create mode 100644 client/src/hooks/queries/useRequestPostLogin.ts create mode 100644 client/src/hooks/queries/useRequestPostMemberList.ts create mode 100644 client/src/hooks/queries/useRequestPutAllMemberList.ts create mode 100644 client/src/hooks/queries/useRequestPutBillAction.ts create mode 100644 client/src/hooks/queries/useRequestPutMemberReportListInAction.ts create mode 100644 client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx create mode 100644 client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx create mode 100644 client/src/hooks/useDynamicInput.tsx create mode 100644 client/src/hooks/useEventLogin.ts create mode 100644 client/src/hooks/useInput.tsx create mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx create mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx create mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts create mode 100644 client/src/hooks/useNavSwitch.tsx create mode 100644 client/src/hooks/usePutAndDeleteBillAction.ts create mode 100644 client/src/hooks/useSearchInMemberList.ts create mode 100644 client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx create mode 100644 client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx create mode 100644 client/src/hooks/useSetAllMemberList.tsx create mode 100644 client/src/hooks/useSetBillInput.ts create mode 100644 client/src/hooks/useSetEventNamePage.ts create mode 100644 client/src/hooks/useSetEventPasswordPage.ts create mode 100644 client/src/hooks/useToast/ToastProvider.tsx create mode 100644 client/src/hooks/useToast/useToast.test.tsx create mode 100644 client/src/hooks/useToast/useToast.tsx create mode 100644 client/src/index.tsx create mode 100644 client/src/mocks/browser.ts create mode 100644 client/src/mocks/handlers.ts create mode 100644 client/src/mocks/handlers/authHandlers.ts create mode 100644 client/src/mocks/handlers/eventHandlers.ts create mode 100644 client/src/mocks/handlers/memberReportInActionHandlers.ts create mode 100644 client/src/mocks/handlers/reportHandlers.ts create mode 100644 client/src/mocks/handlers/stepListHandler.ts create mode 100644 client/src/mocks/handlers/testHandlers.ts create mode 100644 client/src/mocks/invalidMemberStepList.json create mode 100644 client/src/mocks/memberActionStepList.json create mode 100644 client/src/mocks/memberReportListInAction.json create mode 100644 client/src/mocks/memberReportSearchList.json create mode 100644 client/src/mocks/reportList.json create mode 100644 client/src/mocks/server.ts create mode 100644 client/src/mocks/serverConstants.ts create mode 100644 client/src/mocks/stepList.json create mode 100644 client/src/mocks/svg.ts create mode 100644 client/src/mocks/validValueForTest.ts create mode 100644 client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx create mode 100644 client/src/pages/CreateEventPage/SetEventNamePage.tsx create mode 100644 client/src/pages/CreateEventPage/SetEventPasswordPage.tsx create mode 100644 client/src/pages/CreateEventPage/index.ts create mode 100644 client/src/pages/ErrorPage/ErrorPage.tsx create mode 100644 client/src/pages/EventPage/AdminPage/AdminPage.style.ts create mode 100644 client/src/pages/EventPage/AdminPage/AdminPage.tsx create mode 100644 client/src/pages/EventPage/AdminPage/EventLoginPage.tsx create mode 100644 client/src/pages/EventPage/AdminPage/index.ts create mode 100644 client/src/pages/EventPage/EventPageLayout.tsx create mode 100644 client/src/pages/EventPage/HomePage/HomePage.tsx create mode 100644 client/src/pages/EventPage/HomePage/index.ts create mode 100644 client/src/pages/EventPage/index.ts create mode 100644 client/src/pages/MainPage/MainPage.tsx create mode 100644 client/src/pages/MainPage/Nav/Nav.style.ts create mode 100644 client/src/pages/MainPage/Nav/Nav.tsx create mode 100644 client/src/pages/MainPage/Section/AddBillSection.tsx create mode 100644 client/src/pages/MainPage/Section/AddMemberSection.tsx create mode 100644 client/src/pages/MainPage/Section/DescriptionSection.tsx create mode 100644 client/src/pages/MainPage/Section/MainSection.tsx create mode 100644 client/src/pages/MainPage/Section/MemberReportSection.tsx create mode 100644 client/src/pages/MainPage/index.ts create mode 100644 client/src/router.tsx create mode 100644 client/src/store/appErrorStore.ts create mode 100644 client/src/store/stepListStore.ts create mode 100644 client/src/store/totalExpenseAmountStore.ts create mode 100644 client/src/types/fetchErrorType.ts create mode 100644 client/src/types/serviceType.ts create mode 100644 client/src/utils/caculateExpense.ts create mode 100644 client/src/utils/captureError.ts create mode 100644 client/src/utils/getEventIdByUrl.ts create mode 100644 client/src/utils/getEventPageUrlByEnvironment.ts create mode 100644 client/src/utils/groupActions.ts create mode 100644 client/src/utils/isArraysEqual.ts create mode 100644 client/src/utils/objectToQueryString.ts create mode 100644 client/src/utils/sendLogToSentry.ts create mode 100644 client/src/utils/stepListToActions.ts create mode 100644 client/src/utils/validate/type.ts create mode 100644 client/src/utils/validate/validateEventName.ts create mode 100644 client/src/utils/validate/validateEventPassword.ts create mode 100644 client/src/utils/validate/validateMemberName.ts create mode 100644 client/src/utils/validate/validateMemberReportInAction.ts create mode 100644 client/src/utils/validate/validatePurchase.ts create mode 100644 client/tsconfig.json create mode 100644 client/webpack.common.mjs create mode 100644 client/webpack.dev.mjs create mode 100644 client/webpack.prod.mjs diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml new file mode 100644 index 000000000..af168a976 --- /dev/null +++ b/.github/workflows/design-pull-request.yml @@ -0,0 +1,54 @@ +name: Storybook Deployment + +on: + pull_request: + branches: + - fe-dev + paths: + - 'HDesign/**' + +jobs: + chromatic: + name: Run Chromatic + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.15.1' + + - name: Cache dependencies + id: cache + uses: actions/cache@v3 + with: + path: '**/node_modules' + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-npm- + + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: | + cd HDesign + npm install + + - name: Run lint + run: npm run lint + working-directory: ./HDesign + + - name: Run Chromatic + uses: chromaui/action@latest + id: publish_chromatic + with: + workingDir: HDesign + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + + - name: Comment on PR + uses: thollander/actions-comment-pull-request@v2 + with: + message: '🚀 **storybook**: ${{ steps.publish_chromatic.outputs.storybookUrl }}' diff --git a/.github/workflows/frontend-pull-request.yml b/.github/workflows/frontend-pull-request.yml new file mode 100644 index 000000000..c2749939b --- /dev/null +++ b/.github/workflows/frontend-pull-request.yml @@ -0,0 +1,49 @@ +name: frontend-pull-request + +on: + pull_request: + types: [opened, synchronize] + branches: [main, fe-dev] + paths: + - 'client/**' + +jobs: + test: + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ./client + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.15.1' + + - name: Install dependencies + working-directory: ./client + run: npm install + + - name: Run lint + working-directory: ./client + run: npm run lint + + - name: Run test + working-directory: ./client + run: npm run test + + - name: Cypress test + run: npm run dev & + env: + CI: true + + - name: Wait for the server to start + run: sleep 3 + + - name: Run Cypress tests + run: npm run cypress-run diff --git a/.github/workflows/pr-issue-close.yml b/.github/workflows/pr-issue-close.yml new file mode 100644 index 000000000..c37eb255d --- /dev/null +++ b/.github/workflows/pr-issue-close.yml @@ -0,0 +1,33 @@ +name: Close Issue on PR Merge + +on: + pull_request: + types: [closed] + +jobs: + close-issue: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Extract issue number from PR body + id: extract_issue + run: | + # Fetch PR body + PR_BODY=$(curl -s -H "Authorization: token ${{ secrets.CONFIG_SUBMODULE_TOKEN }}" \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}" \ + | jq -r '.body') + # Extract issue number from PR body using regex (customize if needed) + ISSUE_NUMBER=$(echo "$PR_BODY" | grep -oP '#\d+' | head -1 | sed 's/#//') + echo "ISSUE_NUMBER=$ISSUE_NUMBER" >> $GITHUB_ENV + - name: Close associated issue + if: env.ISSUE_NUMBER != '' + run: | + echo "Closing issue #${{ env.ISSUE_NUMBER }}" + curl -s -X PATCH -H "Authorization: token ${{ secrets.CONFIG_SUBMODULE_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + -d '{"state": "closed"}' \ + "https://api.github.com/repos/${{ github.repository }}/issues/${{ env.ISSUE_NUMBER }}" diff --git a/HDesign/.gitignore b/HDesign/.gitignore new file mode 100644 index 000000000..b98928456 --- /dev/null +++ b/HDesign/.gitignore @@ -0,0 +1,12 @@ +logs +*.log +npm-debug.log* + +node_modules +dist + +.env + +storybook-static +*storybook.log +.DS_Store diff --git a/HDesign/.npmignore b/HDesign/.npmignore new file mode 100644 index 000000000..363c89306 --- /dev/null +++ b/HDesign/.npmignore @@ -0,0 +1,7 @@ +node_modules/ +src/ +tsconfig.json +.storybook/ +.eslintrc.json +.prettierrc +webpack.config.js \ No newline at end of file diff --git a/HDesign/.npmrc b/HDesign/.npmrc new file mode 100644 index 000000000..ece05f588 --- /dev/null +++ b/HDesign/.npmrc @@ -0,0 +1,2 @@ +engine-strict = true +legacy-peer-deps = true diff --git a/HDesign/.prettierrc b/HDesign/.prettierrc new file mode 100644 index 000000000..c025201f4 --- /dev/null +++ b/HDesign/.prettierrc @@ -0,0 +1,12 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "jsxSingleQuote": false, + "bracketSpacing": false, + "proseWrap": "preserve" +} diff --git a/HDesign/.storybook/main.ts b/HDesign/.storybook/main.ts new file mode 100644 index 000000000..a1fa61591 --- /dev/null +++ b/HDesign/.storybook/main.ts @@ -0,0 +1,47 @@ +/** @type { import('@storybook/react-webpack5').StorybookConfig } */ +import type {StorybookConfig} from '@storybook/react-webpack5'; +import path from 'path'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + '@storybook/addon-webpack5-compiler-swc', + '@storybook/addon-onboarding', + '@storybook/addon-links', + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/react-webpack5', + options: {}, + }, + webpackFinal: async config => { + if (config.resolve) { + config.resolve.alias = { + ...config.resolve.alias, + '@components': path.resolve(__dirname, '../src/components'), + '@token': path.resolve(__dirname, '../src/token'), + '@type': path.resolve(__dirname, '../src/type'), + '@theme': path.resolve(__dirname, '../src/theme'), + '@assets': path.resolve(__dirname, '../src/assets'), + '@utils': path.resolve(__dirname, '../src/utils'), + }; + } + + config.module = config.module || {}; + config.module.rules = config.module.rules || []; + + const imageRule = config.module.rules.find(rule => rule?.['test']?.test('.svg')); + if (imageRule) { + imageRule['exclude'] = /\.svg$/; + } + + config.module.rules.push({ + test: /\.svg$/, + use: ['@svgr/webpack'], + }); + return config; + }, +}; +export default config; diff --git a/HDesign/.storybook/preview.tsx b/HDesign/.storybook/preview.tsx new file mode 100644 index 000000000..22008ad03 --- /dev/null +++ b/HDesign/.storybook/preview.tsx @@ -0,0 +1,41 @@ +/** @jsxImportSource @emotion/react */ + +import type {Preview} from '@storybook/react'; +import {HDesignProvider} from '../src/theme/HDesignProvider'; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + viewport: { + defaultViewport: { + styles: { + width: '375px', + height: '812px', + }, + }, + }, + backgrounds: { + default: 'gray', + values: [ + { + name: 'gray', + value: '#f3f3f3', + }, + ], + }, + }, + decorators: [ + Story => ( + <HDesignProvider> + <Story /> + </HDesignProvider> + ), + ], +}; + +export default preview; diff --git a/HDesign/eslint.config.mjs b/HDesign/eslint.config.mjs new file mode 100644 index 000000000..e025936a4 --- /dev/null +++ b/HDesign/eslint.config.mjs @@ -0,0 +1,153 @@ +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; + +import {fixupConfigRules, fixupPluginRules} from '@eslint/compat'; +import react from 'eslint-plugin-react'; +import typescriptEslint from '@typescript-eslint/eslint-plugin'; +import _import from 'eslint-plugin-import'; +import prettier from 'eslint-plugin-prettier'; +import tsParser from '@typescript-eslint/parser'; +import js from '@eslint/js'; +import {FlatCompat} from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [ + ...fixupConfigRules( + compat.extends( + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', + 'plugin:import/typescript', + 'plugin:import/recommended', + 'plugin:import/errors', + 'plugin:import/warnings', + 'prettier', + 'plugin:prettier/recommended', + ), + ), + { + plugins: { + react: fixupPluginRules(react), + '@typescript-eslint': fixupPluginRules(typescriptEslint), + import: fixupPluginRules(_import), + prettier: fixupPluginRules(prettier), + }, + + languageOptions: { + parser: tsParser, + }, + + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + + typescript: { + directory: './lib', + }, + }, + + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + + 'import/ignore': ['lottie-react'], + }, + + rules: { + 'no-use-before-define': 0, + 'prettier/prettier': 'error', + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + 'import/prefer-default-export': 0, + 'import/no-named-as-default': 0, + 'import/namespace': 0, + 'import/extensions': 0, + 'import/no-cycle': 0, + 'react/no-unknown-property': 0, + 'react/jsx-filename-extension': [1, {extensions: ['.ts', '.tsx']}], + 'react/function-component-definition': 0, + 'react/jsx-props-no-spreading': 0, + 'react/jsx-key': 0, + 'react/button-has-type': 'off', + 'no-shadow': 0, + 'no-console': 0, + 'no-alert': 0, + 'react/no-children-prop': 'off', + 'react/no-array-index-key': 'off', + 'react-hooks/exhaustive-deps': 'off', + 'react-hooks/rules-of-hooks': 'off', + 'react/jsx-no-useless-fragment': 'off', + 'react/jsx-no-constructed-context-values': 'off', + 'jsx-a11y/click-events-have-key-events': 'off', + 'jsx-a11y/no-static-element-interactions': 'off', + + '@typescript-eslint/no-unused-vars': 0, + + // 'react/jsx-uses-vars': 'error', + // '@typescript-eslint/no-use-before-define': ['error'], + // '@typescript-eslint/explicit-module-boundary-types': 'error', + + 'import/order': [ + 'error', + { + 'newlines-between': 'always', + + groups: ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'], + + pathGroups: [ + { + pattern: 'react*', + group: 'external', + position: 'before', + }, + { + pattern: '@components/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@layouts/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@assets/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@theme/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@token/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@types/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@utils/*', + group: 'internal', + position: 'after', + }, + ], + }, + ], + }, + }, +]; diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json new file mode 100644 index 000000000..fb92d2ae1 --- /dev/null +++ b/HDesign/package-lock.json @@ -0,0 +1,13707 @@ +{ + "name": "haengdong-design", + "version": "0.1.81", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "haengdong-design", + "version": "0.1.81", + "license": "ISC", + "dependencies": { + "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", + "@storybook/test": "^8.2.2", + "@swc/core": "^1.7.6", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "esbuild": "^0.23.0", + "eslint": "^9.8.0", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-storybook": "^0.8.0", + "file-loader": "^6.2.0", + "globals": "^15.8.0", + "prettier": "3.3.2", + "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", + "ts-loader": "^9.5.1", + "tsc-alias": "^1.8.10", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", + "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", + "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.9", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-module-transforms": "^7.24.9", + "@babel/helpers": "^7.24.8", + "@babel/parser": "^7.24.8", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/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==" + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", + "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", + "dependencies": { + "@babel/types": "^7.24.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", + "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", + "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", + "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", + "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", + "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", + "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "dependencies": { + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", + "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", + "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", + "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", + "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", + "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz", + "integrity": "sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-flow": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", + "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", + "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", + "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", + "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", + "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.8", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", + "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-flow-strip-types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", + "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/register/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", + "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", + "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.8", + "@babel/types": "^7.24.8", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@babel/types": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@base2/pretty-print-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", + "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", + "dev": true + }, + "node_modules/@chromatic-com/storybook": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.6.1.tgz", + "integrity": "sha512-x1x1NB3j4xpfeSWKr96emc+7ZvfsvH+/WVb3XCjkB24PPbT8VZXb3mJSAQMrSzuQ8+eQE9kDogYHH9Fj3tb/Cw==", + "dev": true, + "dependencies": { + "chromatic": "^11.4.0", + "filesize": "^10.0.12", + "jsonfile": "^6.1.0", + "react-confetti": "^6.1.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=16.0.0", + "yarn": ">=1.22.18" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "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", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/react": { + "version": "11.11.4", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", + "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", + "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "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==" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "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==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", + "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@eslint/js": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dev": true, + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", + "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/addon-actions": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.2.tgz", + "integrity": "sha512-SN4cSRt3f0qXi5te+yhMseSdQuZntA8lGlASbRmN77YQTpIaGsNiH88xFoky0s9qz531hiRfU1R0ZSMylBwSKw==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.2.tgz", + "integrity": "sha512-m/xJe7uKL+kfJx7pQcHwAeIvJ3tdLIpDGrMAVDNDJHcAxfe44cFjIInaV/1HKf3y5Awap+DZFW66ekkxuI9zzA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-controls": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.2.tgz", + "integrity": "sha512-y241aOANGzT5XBADUIvALwG/xF5eC6UItzmWJaFvOzSBCq74GIA0+Hu9atyFdvFQbXOrdvPWC4jR+9iuBFRxAA==", + "dev": true, + "dependencies": { + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.2.tgz", + "integrity": "sha512-qk/yjAR9RpsSrKLLbeCgb6u58c8TmYqyJSnXgbAozZZNKHBWlIpvZ/hTNYud8qo0coPlxnLdjnZf32TykWGlAg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.2.2", + "@storybook/csf-plugin": "8.2.2", + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.2", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "fs-extra": "^11.1.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-docs/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/addon-essentials": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.2.tgz", + "integrity": "sha512-yN//BFMbSvNV0+Sll2hcKmgJX06TUKQDm6pZimUjkXczFtOmK7K/UdDmKjWS+qjhfJdWpxdRoEpxoHvvRmNfsA==", + "dev": true, + "dependencies": { + "@storybook/addon-actions": "8.2.2", + "@storybook/addon-backgrounds": "8.2.2", + "@storybook/addon-controls": "8.2.2", + "@storybook/addon-docs": "8.2.2", + "@storybook/addon-highlight": "8.2.2", + "@storybook/addon-measure": "8.2.2", + "@storybook/addon-outline": "8.2.2", + "@storybook/addon-toolbars": "8.2.2", + "@storybook/addon-viewport": "8.2.2", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-highlight": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.2.tgz", + "integrity": "sha512-yDTRzzL+IJAymgY32xoZl09BGBVmPOUV2wVNGYcZkkBLvz2GSQMTfUe1/7F4jAx//+rFBu48/MQzsTC7Bk8kPw==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-interactions": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.2.tgz", + "integrity": "sha512-zRRuUwm/l41JtTUgjIoQTUgLT99Hsdz9cqKca/8NYo1MGBdEcKE41DH4aBIzKaOKFu7p9q00/o/X1EqYX4LMUA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.2.2", + "@storybook/test": "8.2.2", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-links": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.2.tgz", + "integrity": "sha512-eGh7O7SgTJMtnuXC0HlRPOegu1njcJS2cnVqjbzjvjxsPSBhbHpdYMi9Q9E7al/FKuqMUOjIR9YLIlmK1AJaqA==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-measure": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.2.tgz", + "integrity": "sha512-3rCo/aMltt5FrBVdr2dYlD8HlE2q9TLKGJZnwh9on4QyL6ArHbdYw0LmyHe/LrFahJ49w1XQZBMSJcAdRkkS7w==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-onboarding": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.2.tgz", + "integrity": "sha512-dCdE8Mt/JW6cq6dY7co35Sul/bAkUT3ixaxBrUagFUYUQ/PTYM6p4/B+45RURD5S9z8LVHH1rVgmEeScm3U78w==", + "dev": true, + "dependencies": { + "react-confetti": "^6.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-outline": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.2.tgz", + "integrity": "sha512-Y+PQtfTNO8GLX5nz+3x5AMfHNvdGvBXazJ29+Rl1ygYN1+Q9ZhRJDE1kAK0wLxb7CG14peAgdYEaQb3Rduv7HQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-toolbars": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.2.tgz", + "integrity": "sha512-JGOueOc3EPljlCl9dVSQee0aMYoqGNvN0UH+R6wYJ3bDZ+tUG/iYpsZVPUOvS8vzp3Imk5Is1kzQbQYJtzdGLg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-viewport": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.2.tgz", + "integrity": "sha512-gkZ8bsjGGP0NuevkT2iKC+szezSy+w4BrBDknf490mRU2K/B2e7TGojf/j/AtxzILMzD4IKzKUXbE/zwcqjZvA==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "dependencies": { + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@storybook/blocks": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.2.tgz", + "integrity": "sha512-av0Tryg4toDl2L/d1ABErtsAk9wvM1su6+M4wq5/Go50sk5IjGTldhbZFa9zNOohxLkZwaj0Q5xAgJ1Y+m5KrQ==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.4.5", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.3.tgz", + "integrity": "sha512-yU9rtcVpo12vD8m/nbdepyJ09K937ZnSsrvIM9XfzbxXA/+p4Cov9Rjg1VfoWyRd1ApxaztSktQlawBlb6bKEA==", + "dev": true, + "dependencies": { + "@storybook/core-webpack": "8.2.3", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "browser-assert": "^1.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "cjs-module-lexer": "^1.2.3", + "constants-browserify": "^1.0.0", + "css-loader": "^6.7.1", + "es-module-lexer": "^1.5.0", + "express": "^4.19.2", + "fork-ts-checker-webpack-plugin": "^8.0.0", + "fs-extra": "^11.1.0", + "html-webpack-plugin": "^5.5.0", + "magic-string": "^0.30.5", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "semver": "^7.3.7", + "style-loader": "^3.3.1", + "terser-webpack-plugin": "^5.3.1", + "ts-dedent": "^2.0.0", + "url": "^0.11.0", + "util": "^0.12.4", + "util-deprecate": "^1.0.2", + "webpack": "5", + "webpack-dev-middleware": "^6.1.2", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.6.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.3" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", + "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", + "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/codemod": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.2.2.tgz", + "integrity": "sha512-wRUVKLHVUhbLJYKW3QOufUxJGwaUT4jTCD8+HOGpHPdJO3NrwXu186xt4tuPZO2Y/NnacPeCQPsaK5ok4O8o7A==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/core": "8.2.2", + "@storybook/csf": "0.1.11", + "@types/cross-spawn": "^6.0.2", + "cross-spawn": "^7.0.3", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "lodash": "^4.17.21", + "prettier": "^3.1.1", + "recast": "^0.23.5", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/codemod/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/core": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.2.tgz", + "integrity": "sha512-L4ojYI+Os/i5bCReDIlFgEDQSS94mbJlNU9WRzEGZpqNC5/hbFEC9Tip7P1MiRx9NrewkzU7b+UCP7mi3e4drQ==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@types/express": "^4.17.21", + "@types/node": "^18.0.0", + "browser-assert": "^1.2.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", + "esbuild-register": "^3.5.0", + "express": "^4.19.2", + "process": "^0.11.10", + "recast": "^0.23.5", + "util": "^0.12.4", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-webpack": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", + "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", + "dev": true, + "dependencies": { + "@types/node": "^18.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.3" + } + }, + "node_modules/@storybook/core-webpack/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/core/node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/core/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/core/node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/@storybook/csf": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", + "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", + "dev": true, + "dependencies": { + "type-fest": "^2.19.0" + } + }, + "node_modules/@storybook/csf-plugin": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.2.2.tgz", + "integrity": "sha512-3K2RUpDDvq3DT46qAIj2VBC+fzTTebRUcZUsRfS6G1AzaX9p25iClEHiwcJacFkgQKhkci8A/Ly3Z4JJ3b4Pgw==", + "dev": true, + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true + }, + "node_modules/@storybook/icons": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.9.tgz", + "integrity": "sha512-cOmylsz25SYXaJL/gvTk/dl3pyk7yBFRfeXTsHvTA3dfhoU/LWSq0NKL9nM7WBasJyn6XPSGnLS4RtKXLw5EUg==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@storybook/instrumenter": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.2.2.tgz", + "integrity": "sha512-refwnHqKHhya45MgqakhMG0jKhTiEIAl0aOwAaQy9+zf9ncMIYQAXRQsSZ2Z188lFWE24wbeHKteb62a5ZfWwQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@vitest/utils": "^1.3.1", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/preset-react-webpack": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.3.tgz", + "integrity": "sha512-i886+vCMGlpFgOAOIg6BxSHgt38MXS6gqNX8Z65KVVIlI6i/9WqEQeHYfukbdGvVZ96cYWmdrnqUieIIkdCdBw==", + "dev": true, + "dependencies": { + "@storybook/core-webpack": "8.2.3", + "@storybook/react": "8.2.3", + "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "magic-string": "^0.30.5", + "react-docgen": "^7.0.0", + "resolve": "^1.22.8", + "semver": "^7.3.7", + "tsconfig-paths": "^4.2.0", + "webpack": "5" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/react": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.3.tgz", + "integrity": "sha512-818F6pJWFBiwG0r6DiUVrV+qndwbIso2gtgJoituBgIJO2eIzNmkPNSsckbaR7u+FpE4dWiIIhmDVZSnRwvDlA==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.3", + "@types/escodegen": "^0.0.6", + "@types/estree": "^0.0.51", + "@types/node": "^18.0.0", + "acorn": "^7.4.1", + "acorn-jsx": "^5.3.1", + "acorn-walk": "^7.2.0", + "escodegen": "^2.1.0", + "html-tags": "^3.1.0", + "lodash": "^4.17.21", + "prop-types": "^15.7.2", + "react-element-to-jsx-string": "^15.0.0", + "semver": "^7.3.7", + "ts-dedent": "^2.0.0", + "type-fest": "~2.19", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin": { + "version": "1.0.6--canary.9.0c3f3b7.0", + "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", + "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "endent": "^2.0.1", + "find-cache-dir": "^3.3.1", + "flat-cache": "^3.0.4", + "micromatch": "^4.0.2", + "react-docgen-typescript": "^2.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "typescript": ">= 4.x", + "webpack": ">= 4" + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@storybook/react-dom-shim": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.2.tgz", + "integrity": "sha512-4fb1/yT9WXHzHjs0In6orIEZxga5eXd9UaXEFGudBgowCjDUVP9LabDdKTbGusz20lfaAkATsRG/W+EcSLoh8w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.2" + } + }, + "node_modules/@storybook/react-webpack5": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.3.tgz", + "integrity": "sha512-lcm73r8S5Uy2ENuFDSR07fW+KRSYGNcrF53VItP+rgFZHrOm7gaeebrjSIA6r4tQwdd9218VaqpQGFrKAURS2w==", + "dev": true, + "dependencies": { + "@storybook/builder-webpack5": "8.2.3", + "@storybook/preset-react-webpack": "8.2.3", + "@storybook/react": "8.2.3", + "@types/node": "^18.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/react-webpack5/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/react/node_modules/@storybook/react-dom-shim": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.3.tgz", + "integrity": "sha512-N8AsM6N1S867GGWt2J2q5oY5ryqxohh3y1HqNtjg+wXf5+RkTD6M2Cgqe6p+JHz81nDKyvvVzP60MvvDhY5VOA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.3" + } + }, + "node_modules/@storybook/react/node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@storybook/react/node_modules/@types/node": { + "version": "18.19.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", + "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/react/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/test": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.2.2.tgz", + "integrity": "sha512-X2qAKErjTh1X7XLAZqCMtU0ZK8JuwdKmgiqU0oXWxIDmCX6/Dm9ZIcdMZHs/S+K/UnIByjNlQpTShLVfRUeN1w==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/instrumenter": "8.2.2", + "@testing-library/dom": "10.1.0", + "@testing-library/jest-dom": "6.4.5", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "1.6.0", + "@vitest/spy": "1.6.0", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.2" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@swc/core": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.6.tgz", + "integrity": "sha512-FZxyao9eQks1MRmUshgsZTmlg/HB2oXK5fghkoWJm/1CU2q2kaJlVDll2as5j+rmWiwkp0Gidlq8wlXcEEAO+g==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.6", + "@swc/core-darwin-x64": "1.7.6", + "@swc/core-linux-arm-gnueabihf": "1.7.6", + "@swc/core-linux-arm64-gnu": "1.7.6", + "@swc/core-linux-arm64-musl": "1.7.6", + "@swc/core-linux-x64-gnu": "1.7.6", + "@swc/core-linux-x64-musl": "1.7.6", + "@swc/core-win32-arm64-msvc": "1.7.6", + "@swc/core-win32-ia32-msvc": "1.7.6", + "@swc/core-win32-x64-msvc": "1.7.6" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.6.tgz", + "integrity": "sha512-6lYHey84ZzsdtC7UuPheM4Rm0Inzxm6Sb8U6dmKc4eCx8JL0LfWG4LC5RsdsrTxnjTsbriWlnhZBffh8ijUHIQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", + "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", + "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/doctrine": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", + "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", + "dev": true + }, + "node_modules/@types/emscripten": { + "version": "1.39.13", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", + "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==", + "dev": true + }, + "node_modules/@types/escodegen": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz", + "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==", + "dev": true + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/lodash": { + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", + "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==", + "dev": true + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", + "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", + "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", + "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/type-utils": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", + "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/utils": "7.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", + "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", + "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", + "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", + "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/visitor-keys": "7.16.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", + "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.16.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vitest/utils/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/utils/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/fslib": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", + "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", + "dev": true, + "dependencies": { + "@yarnpkg/libzip": "^2.3.0", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/fslib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@yarnpkg/libzip": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", + "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", + "dev": true, + "dependencies": { + "@types/emscripten": "^1.39.6", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/libzip/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "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": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "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, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.toreversed": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", + "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/available-typed-arrays": { + "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, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", + "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromatic": { + "version": "11.5.5", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.5.5.tgz", + "integrity": "sha512-YS0GJwegF0vpMbwZE68/xJlI4SlUGMqI78V2ATAF19YwTHaq8jGP1CPQGKUSlgWUhzPtyu3ELy6Dvv/owYljAg==", + "dev": true, + "bin": { + "chroma": "dist/bin.js", + "chromatic": "dist/bin.js", + "chromatic-cli": "dist/bin.js" + }, + "peerDependencies": { + "@chromatic-com/cypress": "^0.*.* || ^1.0.0", + "@chromatic-com/playwright": "^0.*.* || ^1.0.0" + }, + "peerDependenciesMeta": { + "@chromatic-com/cypress": { + "optional": true + }, + "@chromatic-com/playwright": { + "optional": true + } + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "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.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.827", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", + "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dev": true, + "dependencies": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "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, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" + } + }, + "node_modules/esbuild-register": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", + "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" + } + }, + "node_modules/esbuild-register/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/esbuild-register/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-node/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 + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils/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 + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "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.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/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 + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "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, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.34.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.4.tgz", + "integrity": "sha512-Np+jo9bUwJNxCsT12pXtrGhJgT3T44T1sHhn1Ssr42XFn8TES0267wPGo5nNrMHi8qkyimDAX2BUmkf9pSaVzA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.toreversed": "^1.1.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-storybook": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.8.0.tgz", + "integrity": "sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==", + "dev": true, + "dependencies": { + "@storybook/csf": "^0.0.1", + "@typescript-eslint/utils": "^5.62.0", + "requireindex": "^1.2.0", + "ts-dedent": "^2.2.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "eslint": ">=6" + } + }, + "node_modules/eslint-plugin-storybook/node_modules/@storybook/csf": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", + "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "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 + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-parse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-package-json": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", + "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", + "dev": true, + "dependencies": { + "walk-up-path": "^3.0.1" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/file-entry-cache/node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/filesize": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.4.tgz", + "integrity": "sha512-ryBwPIIeErmxgPnm6cbESAzXjuEFubs+yKYLBZvg3CaiNcmkJChoOGcBSrZ6IwkMwPABwPpVXE6IlNdGJJrvEg==", + "dev": true, + "engines": { + "node": ">= 10.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flat-cache/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/flow-parser": { + "version": "0.239.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.239.1.tgz", + "integrity": "sha512-topOrETNxJ6T2gAnQiWqAlzGPj8uI2wtmNOlDIMNB+qyvGJZ6R++STbUOTAYmvPhOMz2gXnXPH0hOvURYmrBow==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/giget": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "tar": "^6.2.0" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/globals": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", + "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "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, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "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==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "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, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-heading-rank": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", + "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-absolute-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", + "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jscodeshift": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/preset-flow": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@babel/register": "^7.22.15", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.23.3", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true + }, + "node_modules/markdown-to-jsx": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz", + "integrity": "sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mlly": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", + "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/mylas": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", + "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/raouldeheer" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-dir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-dir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nypm": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.9.tgz", + "integrity": "sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/nypm/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/nypm/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/nypm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nypm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/objectorarray": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", + "dev": true + }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-types": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.3.tgz", + "integrity": "sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==", + "dev": true, + "dependencies": { + "confbox": "^0.1.7", + "mlly": "^1.7.1", + "pathe": "^1.1.2" + } + }, + "node_modules/plimit-lit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", + "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", + "dev": true, + "dependencies": { + "queue-lit": "^1.5.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-lit": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", + "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-confetti": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", + "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", + "dev": true, + "dependencies": { + "tween-functions": "^1.2.0" + }, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-docgen": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.0.3.tgz", + "integrity": "sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.9", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9", + "@types/babel__core": "^7.18.0", + "@types/babel__traverse": "^7.18.0", + "@types/doctrine": "^0.0.9", + "@types/resolve": "^1.20.2", + "doctrine": "^3.0.0", + "resolve": "^1.22.1", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=16.14.0" + } + }, + "node_modules/react-docgen-typescript": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", + "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", + "dev": true, + "peerDependencies": { + "typescript": ">= 4.3.x" + } + }, + "node_modules/react-docgen/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-element-to-jsx-string": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", + "integrity": "sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==", + "dev": true, + "dependencies": { + "@base2/pretty-print-object": "1.0.1", + "is-plain-object": "5.0.0", + "react-is": "18.1.0" + }, + "peerDependencies": { + "react": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0", + "react-dom": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/react-is": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", + "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "dev": true + }, + "node_modules/react-inspector": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz", + "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==", + "dev": true, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-router": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", + "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", + "dependencies": { + "@remix-run/router": "1.17.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", + "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", + "dependencies": { + "@remix-run/router": "1.17.1", + "react-router": "6.24.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recast": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", + "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "dev": true, + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent/node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "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", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/rehype-external-links": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", + "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-is-element": "^3.0.0", + "is-absolute-url": "^4.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", + "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true, + "engines": { + "node": ">=0.10.5" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/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 + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.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, + "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, + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/storybook": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.2.2.tgz", + "integrity": "sha512-xDT9gyzAEFQNeK7P+Mj/8bNzN+fbm6/4D6ihdSzmczayjydpNjMs74HDHMY6S4Bfu6tRVyEK2ALPGnr6ZVofBA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/codemod": "8.2.2", + "@storybook/core": "8.2.2", + "@types/semver": "^7.3.4", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "cross-spawn": "^7.0.3", + "detect-indent": "^6.1.0", + "envinfo": "^7.7.3", + "execa": "^5.0.0", + "fd-package-json": "^1.2.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "giget": "^1.0.0", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "leven": "^3.1.0", + "ora": "^5.4.1", + "prettier": "^3.1.1", + "prompts": "^2.4.0", + "semver": "^7.3.7", + "strip-json-comments": "^3.0.1", + "tempy": "^3.1.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0" + }, + "bin": { + "getstorybook": "bin/index.cjs", + "sb": "bin/index.cjs", + "storybook": "bin/index.cjs" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook-addon-react-router-v6": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/storybook-addon-react-router-v6/-/storybook-addon-react-router-v6-2.0.15.tgz", + "integrity": "sha512-4vOYIQwehlQLyXaCT9K0Iu0po2Z+pANGsqkfm/BQuAEjE9MoN7vrsrQLHINhKbmQVtNMmuS/oBR3GGNbqQ1gew==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "compare-versions": "^6.0.0", + "react-inspector": "6.0.2" + }, + "peerDependencies": { + "@storybook/blocks": "^7.0.0", + "@storybook/channels": "^7.0.0", + "@storybook/components": "^7.0.0", + "@storybook/core-events": "^7.0.0", + "@storybook/manager-api": "^7.0.0", + "@storybook/preview-api": "^7.0.0", + "@storybook/theming": "^7.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-router-dom": "^6.4.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/storybook/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/storybook/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/storybook/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "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", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "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, + "dependencies": { + "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" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/svgo/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/telejson": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", + "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/temp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/temp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/temp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.31.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", + "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tsc-alias": { + "version": "1.8.10", + "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", + "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.3", + "commander": "^9.0.0", + "globby": "^11.0.4", + "mylas": "^2.1.9", + "normalize-path": "^3.0.0", + "plimit-lit": "^1.2.6" + }, + "bin": { + "tsc-alias": "dist/bin/index.js" + } + }, + "node_modules/tsc-alias/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", + "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.16.0", + "@typescript-eslint/parser": "7.16.0", + "@typescript-eslint/utils": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", + "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.16.0", + "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/ufo": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", + "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unplugin": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.11.0.tgz", + "integrity": "sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "chokidar": "^3.6.0", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.6.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "dev": true, + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.11.2" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/url/node_modules/qs": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", + "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/walk-up-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", + "dev": true + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webpack": { + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-hot-middleware": { + "version": "2.26.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", + "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", + "dev": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "strip-ansi": "^6.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "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.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/HDesign/package.json b/HDesign/package.json new file mode 100644 index 000000000..062987bf1 --- /dev/null +++ b/HDesign/package.json @@ -0,0 +1,72 @@ +{ + "name": "haengdong-design", + "version": "0.1.81", + "description": "", + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "start": "webpack serve ", + "build": "rm -rf dist && mkdir dist && tsc && cp -r ./src/assets ./dist && tsc-alias", + "storybook": "storybook dev -p 6006", + "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", + "format": "prettier --write {src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", + "build-storybook": "storybook build" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", + "@storybook/test": "^8.2.2", + "@swc/core": "^1.7.6", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "esbuild": "^0.23.0", + "eslint": "^9.8.0", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.4", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-storybook": "^0.8.0", + "file-loader": "^6.2.0", + "globals": "^15.8.0", + "prettier": "3.3.2", + "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", + "ts-loader": "^9.5.1", + "tsc-alias": "^1.8.10", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.0" + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "engines": { + "npm": ">=10.7.0", + "node": ">=20.15.1" + } +} diff --git a/HDesign/src/assets/buljusa.svg b/HDesign/src/assets/buljusa.svg new file mode 100644 index 000000000..fe5c47534 --- /dev/null +++ b/HDesign/src/assets/buljusa.svg @@ -0,0 +1,4 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M6.375 12.5C6.54076 12.5 6.69973 12.4407 6.81694 12.3352C6.93415 12.2298 7 12.0867 7 11.9375C7 11.7883 6.93415 11.6452 6.81694 11.5398C6.69973 11.4343 6.54076 11.375 6.375 11.375C6.20924 11.375 6.05027 11.4343 5.93306 11.5398C5.81585 11.6452 5.75 11.7883 5.75 11.9375C5.75 12.0867 5.81585 12.2298 5.93306 12.3352C6.05027 12.4407 6.20924 12.5 6.375 12.5ZM6.375 8.5625C6.54076 8.5625 6.69973 8.50324 6.81694 8.39775C6.93415 8.29226 7 8.14918 7 8C7 7.85082 6.93415 7.70774 6.81694 7.60225C6.69973 7.49676 6.54076 7.4375 6.375 7.4375C6.20924 7.4375 6.05027 7.49676 5.93306 7.60225C5.81585 7.70774 5.75 7.85082 5.75 8C5.75 8.14918 5.81585 8.29226 5.93306 8.39775C6.05027 8.50324 6.20924 8.5625 6.375 8.5625ZM6.375 4.625C6.54076 4.625 6.69973 4.56574 6.81694 4.46025C6.93415 4.35476 7 4.21168 7 4.0625C7 3.91332 6.93415 3.77024 6.81694 3.66475C6.69973 3.55926 6.54076 3.5 6.375 3.5C6.20924 3.5 6.05027 3.55926 5.93306 3.66475C5.81585 3.77024 5.75 3.91332 5.75 4.0625C5.75 4.21168 5.81585 4.35476 5.93306 4.46025C6.05027 4.56574 6.20924 4.625 6.375 4.625Z" fill="currentColor" stroke="currentColor"/> +<path d="M9.625 12.5C9.79076 12.5 9.94973 12.4407 10.0669 12.3352C10.1842 12.2298 10.25 12.0867 10.25 11.9375C10.25 11.7883 10.1842 11.6452 10.0669 11.5398C9.94973 11.4343 9.79076 11.375 9.625 11.375C9.45924 11.375 9.30027 11.4343 9.18306 11.5398C9.06585 11.6452 9 11.7883 9 11.9375C9 12.0867 9.06585 12.2298 9.18306 12.3352C9.30027 12.4407 9.45924 12.5 9.625 12.5ZM9.625 8.5625C9.79076 8.5625 9.94973 8.50324 10.0669 8.39775C10.1842 8.29226 10.25 8.14918 10.25 8C10.25 7.85082 10.1842 7.70774 10.0669 7.60225C9.94973 7.49676 9.79076 7.4375 9.625 7.4375C9.45924 7.4375 9.30027 7.49676 9.18306 7.60225C9.06585 7.70774 9 7.85082 9 8C9 8.14918 9.06585 8.29226 9.18306 8.39775C9.30027 8.50324 9.45924 8.5625 9.625 8.5625ZM9.625 4.625C9.79076 4.625 9.94973 4.56574 10.0669 4.46025C10.1842 4.35476 10.25 4.21168 10.25 4.0625C10.25 3.91332 10.1842 3.77024 10.0669 3.66475C9.94973 3.55926 9.79076 3.5 9.625 3.5C9.45924 3.5 9.30027 3.55926 9.18306 3.66475C9.06585 3.77024 9 3.91332 9 4.0625C9 4.21168 9.06585 4.35476 9.18306 4.46025C9.30027 4.56574 9.45924 4.625 9.625 4.625Z" fill="currentColor" stroke="currentColor"/> +</svg> diff --git a/HDesign/src/assets/confirm.svg b/HDesign/src/assets/confirm.svg new file mode 100644 index 000000000..ef31a5152 --- /dev/null +++ b/HDesign/src/assets/confirm.svg @@ -0,0 +1,10 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1042_1615)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C11.3132 20 12.6136 19.7413 13.8268 19.2388C15.0401 18.7362 16.1425 17.9997 17.0711 17.0711C17.9997 16.1425 18.7362 15.0401 19.2388 13.8268C19.7413 12.6136 20 11.3132 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 -1.95685e-08 10 0C7.34784 3.95203e-08 4.8043 1.05357 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C4.8043 18.9464 7.34784 20 10 20ZM15.2978 7.37778C15.3953 7.26627 15.4696 7.13638 15.5162 6.99574C15.5628 6.85511 15.5808 6.70657 15.5692 6.55887C15.5575 6.41117 15.5165 6.26729 15.4484 6.1357C15.3804 6.0041 15.2866 5.88745 15.1728 5.7926C15.059 5.69775 14.9274 5.62663 14.7857 5.5834C14.644 5.54018 14.495 5.52574 14.3476 5.54092C14.2003 5.5561 14.0574 5.60061 13.9275 5.67181C13.7976 5.74302 13.6832 5.83949 13.5911 5.95556L9.59333 10.7522C9.20778 11.2144 8.99111 11.4711 8.81889 11.6278L8.81222 11.6344L8.80444 11.6289C8.61778 11.4878 8.37889 11.2522 7.95445 10.8267L6.34111 9.21445C6.13155 9.01205 5.85088 8.90005 5.55956 8.90259C5.26823 8.90512 4.98954 9.02197 4.78354 9.22798C4.57753 9.43399 4.46067 9.71267 4.45814 10.004C4.45561 10.2953 4.5676 10.576 4.77 10.7856L6.38222 12.3978L6.42778 12.4433C6.79111 12.8067 7.13889 13.1556 7.46445 13.4011C7.82778 13.6767 8.30444 13.9344 8.91444 13.9078C9.52556 13.88 9.97667 13.5789 10.3144 13.2722C10.6144 12.9978 10.9311 12.6189 11.2589 12.2244L11.3 12.1756L15.2978 7.37778Z" fill="currentColor"/> +</g> +<defs> +<clipPath id="clip0_1042_1615"> +<rect width="20" height="20" rx="8" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/HDesign/src/assets/error.svg b/HDesign/src/assets/error.svg new file mode 100644 index 000000000..479cae34a --- /dev/null +++ b/HDesign/src/assets/error.svg @@ -0,0 +1,10 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1042_1585)"> +<path d="M11 11H9V5H11M11 15H9V13H11M10 0C8.68678 0 7.38642 0.258658 6.17317 0.761205C4.95991 1.26375 3.85752 2.00035 2.92893 2.92893C1.05357 4.8043 0 7.34784 0 10C0 12.6522 1.05357 15.1957 2.92893 17.0711C3.85752 17.9997 4.95991 18.7362 6.17317 19.2388C7.38642 19.7413 8.68678 20 10 20C12.6522 20 15.1957 18.9464 17.0711 17.0711C18.9464 15.1957 20 12.6522 20 10C20 8.68678 19.7413 7.38642 19.2388 6.17317C18.7362 4.95991 17.9997 3.85752 17.0711 2.92893C16.1425 2.00035 15.0401 1.26375 13.8268 0.761205C12.6136 0.258658 11.3132 0 10 0Z" fill="currentColor"/> +</g> +<defs> +<clipPath id="clip0_1042_1585"> +<rect width="20" height="20" rx="8" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/HDesign/src/assets/index.ts b/HDesign/src/assets/index.ts new file mode 100644 index 000000000..a9c277581 --- /dev/null +++ b/HDesign/src/assets/index.ts @@ -0,0 +1,7 @@ +export {default as InputDelete} from '@assets/inputDelete.svg'; +export {default as Buljusa} from '@assets/buljusa.svg'; +export {default as Error} from '@assets/error.svg'; +export {default as Confirm} from '@assets/confirm.svg'; +export {default as Trash} from '@assets/trash.svg'; +export {default as Search} from '@assets/search.svg'; +export {default as RightChevron} from '@assets/rightChevron.svg'; diff --git a/HDesign/src/assets/inputDelete.svg b/HDesign/src/assets/inputDelete.svg new file mode 100644 index 000000000..4356bb854 --- /dev/null +++ b/HDesign/src/assets/inputDelete.svg @@ -0,0 +1,10 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_940_872)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20ZM6.70711 5.29289C6.31658 4.90237 5.68342 4.90237 5.29289 5.29289C4.90237 5.68342 4.90237 6.31658 5.29289 6.70711L8.58579 10L5.29289 13.2929C4.90237 13.6834 4.90237 14.3166 5.29289 14.7071C5.68342 15.0976 6.31658 15.0976 6.70711 14.7071L10 11.4142L13.2929 14.7071C13.6834 15.0976 14.3166 15.0976 14.7071 14.7071C15.0976 14.3166 15.0976 13.6834 14.7071 13.2929L11.4142 10L14.7071 6.70711C15.0976 6.31658 15.0976 5.68342 14.7071 5.29289C14.3166 4.90237 13.6834 4.90237 13.2929 5.29289L10 8.58579L6.70711 5.29289Z" fill="currentColor"/> +</g> +<defs> +<clipPath id="clip0_940_872"> +<rect width="20" height="20" rx="8" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/HDesign/src/assets/loadingAnimation.json b/HDesign/src/assets/loadingAnimation.json new file mode 100644 index 000000000..4f507a7ea --- /dev/null +++ b/HDesign/src/assets/loadingAnimation.json @@ -0,0 +1,1176 @@ +{ + "nm": "Main Scene", + "ddd": 0, + "h": 48, + "w": 128, + "meta": { + "g": "@lottiefiles/creator 1.24.1" + }, + "layers": [ + { + "ty": 0, + "nm": " Loading Dots", + "sr": 1, + "st": 0, + "op": 81, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 962.9629629629629, + 540.7407407407408 + ] + }, + "s": { + "a": 0, + "k": [ + 27, + 27 + ] + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 64.25999999999999, + 24.2 + ] + }, + "r": { + "a": 0, + "k": 0 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100 + } + }, + "w": 1920, + "h": 1080, + "refId": "precomp_Loading Dots_139596b3-8049-4b90-9165-55e00cf10251", + "ind": 1 + } + ], + "v": "5.7.0", + "fr": 60, + "op": 81, + "ip": 0, + "assets": [ + { + "nm": "Loading Dots", + "id": "precomp_Loading Dots_139596b3-8049-4b90-9165-55e00cf10251", + "fr": 60, + "layers": [ + { + "ty": 4, + "nm": "Dot4", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 25 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 39 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 55 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1142, + 540, + 0 + ], + "t": 25 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1142, + 500, + 0 + ], + "t": 39 + }, + { + "s": [ + 1142, + 540, + 0 + ], + "t": 55 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 25 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 39 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 55 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 1 + }, + { + "ty": 4, + "nm": "Dot3", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 17 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 31 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 47 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1022, + 540, + 0 + ], + "t": 17 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 1022, + 500, + 0 + ], + "t": 31 + }, + { + "s": [ + 1022, + 540, + 0 + ], + "t": 47 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 17 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 31 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 47 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 2 + }, + { + "ty": 4, + "nm": "Dot2", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 9 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 23 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 39 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 902, + 540, + 0 + ], + "t": 9 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 902, + 500, + 0 + ], + "t": 23 + }, + { + "s": [ + 902, + 540, + 0 + ], + "t": 39 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 9 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 23 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 39 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 3 + }, + { + "ty": 4, + "nm": "Dot1", + "sr": 1, + "st": 0, + "op": 360, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -284, + 92, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 50, + 50, + 100 + ], + "t": 0 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 75, + 75, + 100 + ], + "t": 14 + }, + { + "s": [ + 50, + 50, + 100 + ], + "t": 30 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 782, + 540, + 0 + ], + "t": 0 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 782, + 500, + 0 + ], + "t": 14 + }, + { + "s": [ + 782, + 540, + 0 + ], + "t": 30 + } + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + } + }, + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 120, + 120 + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 0 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0.7098, + 0.4588, + 1 + ], + "t": 14 + }, + { + "s": [ + 0.8784, + 0.7804, + 0.9961 + ], + "t": 30 + } + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + -284, + 92 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 4 + } + ] + } + ] +} \ No newline at end of file diff --git a/HDesign/src/assets/rightChevron.svg b/HDesign/src/assets/rightChevron.svg new file mode 100644 index 000000000..5cd777f1b --- /dev/null +++ b/HDesign/src/assets/rightChevron.svg @@ -0,0 +1,3 @@ +<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M2 2L6 6L2 10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> +</svg> diff --git a/HDesign/src/assets/search.svg b/HDesign/src/assets/search.svg new file mode 100644 index 000000000..4f33e89c3 --- /dev/null +++ b/HDesign/src/assets/search.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M15.977 14.472H15.187L14.907 14.202C15.532 13.4759 15.9887 12.6207 16.2446 11.6976C16.5004 10.7744 16.5491 9.80612 16.387 8.86197C15.917 6.08197 13.597 3.86197 10.797 3.52197C9.81264 3.39744 8.81281 3.49974 7.87405 3.82106C6.93529 4.14238 6.08247 4.67419 5.38086 5.3758C4.67924 6.07742 4.14743 6.93023 3.82611 7.869C3.5048 8.80776 3.40249 9.80759 3.52703 10.792C3.86703 13.592 6.08703 15.912 8.86703 16.382C9.81118 16.544 10.7795 16.4954 11.7026 16.2395C12.6258 15.9837 13.481 15.5269 14.207 14.902L14.477 15.182V15.972L18.727 20.222C19.137 20.632 19.807 20.632 20.217 20.222C20.627 19.812 20.627 19.142 20.217 18.732L15.977 14.472ZM9.97703 14.472C7.48703 14.472 5.47703 12.462 5.47703 9.97197C5.47703 7.48197 7.48703 5.47197 9.97703 5.47197C12.467 5.47197 14.477 7.48197 14.477 9.97197C14.477 12.462 12.467 14.472 9.97703 14.472Z" fill="currentColor"/> +</svg> diff --git a/HDesign/src/assets/svg.d.ts b/HDesign/src/assets/svg.d.ts new file mode 100644 index 000000000..2db81e756 --- /dev/null +++ b/HDesign/src/assets/svg.d.ts @@ -0,0 +1,6 @@ +declare module '*.svg' { + import type React from 'react'; + + const SVG: React.FC<React.SVGProps<SVGSVGElement>>; + export default SVG; +} diff --git a/HDesign/src/assets/trash.svg b/HDesign/src/assets/trash.svg new file mode 100644 index 000000000..09b228b17 --- /dev/null +++ b/HDesign/src/assets/trash.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"> +<path d="M9.5 4H14.5C14.5 3.33696 14.2366 2.70107 13.7678 2.23223C13.2989 1.76339 12.663 1.5 12 1.5C11.337 1.5 10.7011 1.76339 10.2322 2.23223C9.76339 2.70107 9.5 3.33696 9.5 4ZM8 4C8 2.93913 8.42143 1.92172 9.17157 1.17157C9.92172 0.421427 10.9391 0 12 0C13.0609 0 14.0783 0.421427 14.8284 1.17157C15.5786 1.92172 16 2.93913 16 4H22.25C22.4489 4 22.6397 4.07902 22.7803 4.21967C22.921 4.36032 23 4.55109 23 4.75C23 4.94891 22.921 5.13968 22.7803 5.28033C22.6397 5.42098 22.4489 5.5 22.25 5.5H20.94L19.723 20.103C19.6345 21.1653 19.1499 22.1556 18.3655 22.8774C17.5811 23.5992 16.554 23.9999 15.488 24H8.512C7.44599 23.9999 6.41894 23.5992 5.6345 22.8774C4.85007 22.1556 4.36554 21.1653 4.277 20.103L3.06 5.5H1.75C1.55109 5.5 1.36032 5.42098 1.21967 5.28033C1.07902 5.13968 1 4.94891 1 4.75C1 4.55109 1.07902 4.36032 1.21967 4.21967C1.36032 4.07902 1.55109 4 1.75 4H8ZM10.5 9.75C10.5 9.55109 10.421 9.36032 10.2803 9.21967C10.1397 9.07902 9.94891 9 9.75 9C9.55109 9 9.36032 9.07902 9.21967 9.21967C9.07902 9.36032 9 9.55109 9 9.75V18.25C9 18.4489 9.07902 18.6397 9.21967 18.7803C9.36032 18.921 9.55109 19 9.75 19C9.94891 19 10.1397 18.921 10.2803 18.7803C10.421 18.6397 10.5 18.4489 10.5 18.25V9.75ZM14.25 9C14.0511 9 13.8603 9.07902 13.7197 9.21967C13.579 9.36032 13.5 9.55109 13.5 9.75V18.25C13.5 18.4489 13.579 18.6397 13.7197 18.7803C13.8603 18.921 14.0511 19 14.25 19C14.4489 19 14.6397 18.921 14.7803 18.7803C14.921 18.6397 15 18.4489 15 18.25V9.75C15 9.55109 14.921 9.36032 14.7803 9.21967C14.6397 9.07902 14.4489 9 14.25 9Z"/> +</svg> diff --git a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx b/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx new file mode 100644 index 000000000..67d4cdb37 --- /dev/null +++ b/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx @@ -0,0 +1,33 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useState} from 'react'; + +import Button from '@components/Button/Button'; +import BottomSheet from '@components/BottomSheet/BottomSheet'; + +const meta = { + title: 'Components/BottomSheet', + component: BottomSheet, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: {}, +} satisfies Meta<typeof BottomSheet>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + const [isOpened, setIsOpened] = useState(false); + return ( + <> + <Button variants="tertiary" children="show modal" onClick={() => setIsOpened(true)} /> + <BottomSheet {...args} isOpened={isOpened} onClose={() => setIsOpened(false)} /> + </> + ); + }, +}; diff --git a/HDesign/src/components/BottomSheet/BottomSheet.style.ts b/HDesign/src/components/BottomSheet/BottomSheet.style.ts new file mode 100644 index 000000000..08c373835 --- /dev/null +++ b/HDesign/src/components/BottomSheet/BottomSheet.style.ts @@ -0,0 +1,60 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const display = (visible: boolean) => + css({ + visibility: visible ? 'visible' : 'hidden', + }); + +export const dimmedLayerStyle = (theme: Theme, isOpened: boolean) => + css({ + position: 'fixed', + zIndex: '30', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + maxWidth: '768px', + width: '100vw', + height: '100vh', + backgroundColor: theme.colors.black, + opacity: isOpened ? '0.48' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); + +export const bottomSheetContainerStyle = (theme: Theme, isOpened: boolean, isDragging: boolean, translateY: number) => + css({ + position: 'fixed', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: '1.5rem', + zIndex: '50', + inset: 'auto 0 0 50%', + maxWidth: '768px', + width: '100%', + height: '80%', + borderRadius: '1.5rem 1.5rem 0 0', + backgroundColor: theme.colors.white, + + transform: isOpened ? `translate(-50%, ${translateY}px)` : 'translate(-50%, 100%)', + transition: isDragging ? 'none' : 'transform 0.2s ease-in-out', + }); + +export const indicatorContainerStyle = css({ + display: 'flex', + justifyContent: 'center', + padding: '0.5rem 0', + width: '100%', +}); + +export const indicatorStyle = (theme: Theme) => + css({ + display: 'flex', + width: '5rem', + height: '0.25rem', + borderRadius: '0.125rem', + backgroundColor: theme.colors.gray, + }); diff --git a/HDesign/src/components/BottomSheet/BottomSheet.tsx b/HDesign/src/components/BottomSheet/BottomSheet.tsx new file mode 100644 index 000000000..3ffadc323 --- /dev/null +++ b/HDesign/src/components/BottomSheet/BottomSheet.tsx @@ -0,0 +1,55 @@ +/** @jsxImportSource @emotion/react */ +import {createPortal} from 'react-dom'; + +import {BottomSheetProps} from '@components/BottomSheet/BottomSheet.type'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {useBottomSheet} from './useBottomSheet'; +import { + bottomSheetContainerStyle, + dimmedLayerStyle, + display, + indicatorContainerStyle, + indicatorStyle, +} from './BottomSheet.style'; + +const BottomSheet: React.FC<BottomSheetProps> = ({ + isOpened = false, + children, + onClose, + onOpen, + ...props +}: BottomSheetProps) => { + const {theme} = useTheme(); + const {opened, visible, handleClose, handleDragStart, handleDrag, handleDragEnd, isDragging, translateY} = + useBottomSheet({ + isOpened, + onClose, + onOpen, + }); + + // TODO: (@todari) : children 길이 길 때 overflow button에 안가리는 영역 처리 + return createPortal( + <div css={display(visible)}> + <div css={dimmedLayerStyle(theme, opened)} onClick={handleClose} /> + <div css={bottomSheetContainerStyle(theme, opened, isDragging, translateY)}> + <div + css={indicatorContainerStyle} + onMouseDown={handleDragStart} + onMouseMove={handleDrag} + onMouseUp={handleDragEnd} + onTouchStart={handleDragStart} + onTouchMove={handleDrag} + onTouchEnd={handleDragEnd} + > + <div css={indicatorStyle(theme)} /> + </div> + {children} + </div> + </div>, + document.body, + ); +}; + +export default BottomSheet; diff --git a/HDesign/src/components/BottomSheet/BottomSheet.type.ts b/HDesign/src/components/BottomSheet/BottomSheet.type.ts new file mode 100644 index 000000000..0cc05841c --- /dev/null +++ b/HDesign/src/components/BottomSheet/BottomSheet.type.ts @@ -0,0 +1,17 @@ +import {ComponentPropsWithoutRef} from 'react'; + +import {Theme} from '@theme/theme.type'; + +export interface BottomSheetStyleProps { + theme?: Theme; +} + +export interface BottomSheetCustomProps { + isOpened?: boolean; + onOpen?: () => void; + onClose?: () => void; +} + +export type BottomSheetOptionProps = BottomSheetStyleProps & BottomSheetCustomProps; + +export type BottomSheetProps = ComponentPropsWithoutRef<'div'> & BottomSheetOptionProps; diff --git a/HDesign/src/components/BottomSheet/useBottomSheet.ts b/HDesign/src/components/BottomSheet/useBottomSheet.ts new file mode 100644 index 000000000..3e2564550 --- /dev/null +++ b/HDesign/src/components/BottomSheet/useBottomSheet.ts @@ -0,0 +1,87 @@ +import {useCallback, useEffect, useRef, useState} from 'react'; + +interface UseBottomSheetProps { + isOpened: boolean; + onClose?: () => void; + onOpen?: () => void; +} + +export const useBottomSheet = ({isOpened, onClose, onOpen}: UseBottomSheetProps) => { + const [opened, setOpened] = useState(isOpened); + const [visible, setVisible] = useState(isOpened); + + const [isDragging, setIsDragging] = useState(false); + const [translateY, setTranslateY] = useState(0); + const startY = useRef(0); + + useEffect(() => { + if (opened) { + setVisible(true); + } else { + const timer = setTimeout(() => setVisible(false), 200); + + return () => clearTimeout(timer); + } + }, [opened]); + + useEffect(() => { + setOpened(isOpened); + if (!isOpened) { + handleClose(); + } else { + handleOpen(); + } + + document.body.style.overflow = 'hidden'; + document.body.addEventListener('keydown', handleKeyDownEsc); + + return () => { + document.body.style.overflow = 'scroll'; + document.body.removeEventListener('keydown', handleKeyDownEsc); + }; + }, [isOpened]); + + const handleClose = useCallback(() => { + setOpened(false); + if (onClose) { + onClose(); + } + }, [onClose]); + + const handleOpen = useCallback(() => { + setOpened(true); + if (onOpen) { + onOpen(); + } + }, [onOpen]); + + const handleDragStart = (e: React.TouchEvent | React.MouseEvent) => { + setIsDragging(true); + startY.current = 'touches' in e ? e.touches[0].clientY : e.clientY; + }; + + const handleDrag = (e: React.TouchEvent | React.MouseEvent) => { + if (!isDragging) return; + const currentY = 'touches' in e ? e.touches[0].clientY : e.clientY; + const deltaY = currentY - startY.current; + setTranslateY(Math.max(deltaY, 0)); + }; + + const threshold = window.screen.height / 10; + + const handleDragEnd = () => { + setIsDragging(false); + if (translateY > threshold) { + handleClose(); + } + setTranslateY(0); + }; + + const handleKeyDownEsc = (e: KeyboardEvent) => { + if (e.key === 'Escape' && isOpened) { + handleClose(); + } + }; + + return {opened, visible, handleClose, handleDragStart, handleDrag, handleDragEnd, isDragging, translateY}; +}; diff --git a/HDesign/src/components/Button/Button.stories.tsx b/HDesign/src/components/Button/Button.stories.tsx new file mode 100644 index 000000000..64288bcb5 --- /dev/null +++ b/HDesign/src/components/Button/Button.stories.tsx @@ -0,0 +1,40 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Button from './Button'; + +const meta = { + title: 'Components/Button', + component: Button, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + variants: { + description: '', + control: {type: 'select'}, + options: ['', 'primary', 'secondary', 'tertiary', 'destructive', 'loading'], + }, + size: { + description: '', + control: {type: 'select'}, + options: ['', 'small', 'medium', 'large'], + }, + disabled: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + variants: 'primary', + size: 'medium', + disabled: false, + children: 'button', + }, +} satisfies Meta<typeof Button>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Button/Button.style.ts b/HDesign/src/components/Button/Button.style.ts new file mode 100644 index 000000000..24c46ec5b --- /dev/null +++ b/HDesign/src/components/Button/Button.style.ts @@ -0,0 +1,113 @@ +import {css} from '@emotion/react'; + +import {setDarker, setEmphasize, setLighter} from '@utils/colors'; + +import {Theme} from '../../theme/theme.type'; + +import {ButtonStyleProps, ButtonSize, ButtonVariants} from './Button.type'; + +export const buttonStyle = (props: Required<ButtonStyleProps>) => { + return [ + getButtonDefaultStyle(props.theme), + getButtonSizeStyle(props.size), + getButtonVariantsStyle(props.variants, props.theme), + ]; +}; + +const getButtonDefaultStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + lineHeight: '1', + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + whiteSpace: 'nowrap', + + '&:disabled': { + backgroundColor: theme.colors.tertiary, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + +const getHoverAndActiveBackground = (color: string) => + css({ + ':not(:disabled)': { + '&:hover': { + backgroundColor: setLighter(color, 0.15), + }, + '&:active': { + backgroundColor: setDarker(color, 0.15), + }, + }, + }); + +const getButtonSizeStyle = (size: ButtonSize) => { + const style = { + small: css({ + padding: '0.5rem 0.75rem', + borderRadius: '0.5rem', + fontFamily: 'Pretendard', + fontSize: '0.75rem', + fontWeight: '400', + }), + medium: css({ + padding: '0.75rem 1rem', + borderRadius: '0.75rem', + fontFamily: 'Pretendard', + fontSize: '1rem', + fontWeight: '700', + }), + large: css({ + padding: '1rem 1.5rem', + borderRadius: '1rem', + fontFamily: 'Pretendard', + fontSize: '1.25rem', + fontWeight: '700', + }), + }; + + return style[size]; +}; + +const getButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => { + const style = { + primary: [ + css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.primary), + ], + secondary: [ + css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + getHoverAndActiveBackground(theme.colors.secondary), + ], + tertiary: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + destructive: [ + css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.error), + ], + loading: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + }; + + return style[variants]; +}; diff --git a/HDesign/src/components/Button/Button.tsx b/HDesign/src/components/Button/Button.tsx new file mode 100644 index 000000000..f0277590b --- /dev/null +++ b/HDesign/src/components/Button/Button.tsx @@ -0,0 +1,47 @@ +/** @jsxImportSource @emotion/react */ + +import React, {forwardRef} from 'react'; +import Lottie from 'lottie-react'; + +import {buttonStyle} from '@components/Button/Button.style'; +import {ButtonProps, ButtonSize} from '@components/Button/Button.type'; + +import loadingAnimation from '@assets/loadingAnimation.json'; + +import {useTheme} from '@theme/HDesignProvider'; + +const animationSize = (size: ButtonSize) => { + switch (size) { + case 'small': + return {width: 30, height: 12}; + + case 'large': + return {width: 50, height: 20}; + + default: + return {width: 40, height: 16}; + } +}; + +export const Button: React.FC<ButtonProps> = forwardRef<HTMLButtonElement, ButtonProps>(function Button( + {variants = 'primary', size = 'medium', disabled, children, ...htmlProps}: ButtonProps, + ref, +) { + const {theme} = useTheme(); + return ( + <button + css={buttonStyle({variants, size, theme})} + ref={ref} + disabled={variants === 'loading' ? true : disabled} + {...htmlProps} + > + {variants === 'loading' ? ( + <Lottie animationData={loadingAnimation} loop={true} style={animationSize(size)} /> + ) : ( + children + )} + </button> + ); +}); + +export default Button; diff --git a/HDesign/src/components/Button/Button.type.ts b/HDesign/src/components/Button/Button.type.ts new file mode 100644 index 000000000..a0402b1dc --- /dev/null +++ b/HDesign/src/components/Button/Button.type.ts @@ -0,0 +1,16 @@ +import {Theme} from '@theme/theme.type'; + +export type ButtonSize = 'small' | 'medium' | 'large'; +export type ButtonVariants = 'primary' | 'secondary' | 'tertiary' | 'destructive' | 'loading'; + +export interface ButtonStyleProps { + variants?: ButtonVariants; + size?: ButtonSize; + theme?: Theme; +} + +export interface ButtonCustomProps {} + +export type ButtonOptionProps = ButtonStyleProps & ButtonCustomProps; + +export type ButtonProps = React.ComponentProps<'button'> & ButtonOptionProps; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx new file mode 100644 index 000000000..c7125d4d8 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx @@ -0,0 +1,51 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; + +const meta = { + title: 'Components/DragHandleItem', + component: DragHandleItem, + tags: ['autodocs'], + parameters: {}, + argTypes: { + backgroundColor: { + description: '', + control: {type: 'select'}, + options: ['white', 'gray', 'darkGray', 'black', 'primary', 'onPrimary', 'secondary', 'onSecondary'], + }, + hasDragHandler: { + description: '드래그할 수 있는 핸들러(불주사 자국)를 켜고 끌 수 있습니다.', + control: {type: 'boolean'}, + }, + prefix: { + description: '', + control: {type: 'text'}, + }, + suffix: { + description: '', + control: {type: 'text'}, + }, + isFixed: { + description: '컴포넌트가 고정되어 있는지 여부를 나타냅니다.', + control: {type: 'boolean'}, + }, + }, + args: { + backgroundColor: 'white', + hasDragHandler: true, + prefix: '뽕쟁이족발', + suffix: '398,000 원', + }, +} satisfies Meta<typeof DragHandleItem>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; + +export const FixedItem: Story = { + args: { + isFixed: true, + }, +}; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts new file mode 100644 index 000000000..b641c5fb3 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts @@ -0,0 +1,20 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgroundColor: ColorKeys) => + css({ + display: 'flex', + justifyContent: 'space-between', + padding: hasDragHandle ? '0.5rem 1rem 0.5rem 0.5rem' : '0.5rem 1rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors[backgroundColor], + }); + +export const dragHandlerStyle = css({ + display: 'flex', + gap: '0.25rem', + width: '100%', +}); diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx new file mode 100644 index 000000000..9acf38084 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.tsx @@ -0,0 +1,44 @@ +/** @jsxImportSource @emotion/react */ +import Icon from '@components/Icon/Icon'; +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; +import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import IconButton from '../IconButton/IconButton'; + +import {dragHandleItemStyle, dragHandlerStyle} from './DragHandleItem.style'; +import {DragHandleItemProps} from './DragHandleItem.type'; + +export const DragHandleItem = ({ + hasDragHandler = false, + backgroundColor = 'white', + isFixed = false, + prefix, + suffix, + ...htmlProps +}: DragHandleItemProps) => { + const {theme} = useTheme(); + + // TODO: (@toari) : 사람 수 많을 때 UX writing 처리 + return ( + <div css={dragHandleItemStyle(theme, hasDragHandler, backgroundColor)} {...htmlProps}> + <div css={dragHandlerStyle}> + {hasDragHandler && ( + <IconButton variants="none"> + <Icon iconType="buljusa" /> + </IconButton> + )} + <Flex justifyContent="spaceBetween" width="100%"> + <Text size="bodyBold">{prefix}</Text> + <Flex flexDirection="row"> + {isFixed && <IsFixedIcon />} + <Text>{suffix}</Text> + </Flex> + </Flex> + </div> + </div> + ); +}; +export default DragHandleItem; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts b/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts new file mode 100644 index 000000000..fc0a1f520 --- /dev/null +++ b/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts @@ -0,0 +1,19 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export interface DragHandleItemStyleProps { + theme?: Theme; + backgroundColor?: ColorKeys; +} + +export interface DragHandleItemCustomProps { + hasDragHandler?: boolean; + prefix?: string; + suffix?: string; + isFixed?: boolean; +} + +export type DragHandleItemOptionProps = DragHandleItemStyleProps & DragHandleItemCustomProps; + +export type DragHandleItemProps = React.ComponentProps<'div'> & DragHandleItemOptionProps; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx new file mode 100644 index 000000000..46c3db8a2 --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx @@ -0,0 +1,90 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; + +const meta = { + title: 'Components/DragHandleItemContainer', + component: DragHandleItemContainer, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + topLeftText: { + description: '', + control: {type: 'text'}, + }, + topRightText: { + description: '', + control: {type: 'text'}, + }, + bottomLeftText: { + description: '', + control: {type: 'text'}, + }, + bottomRightText: { + description: '', + control: {type: 'text'}, + }, + backgroundColor: { + description: '', + control: { + type: 'select', + options: [ + 'white', + 'black', + 'primary', + 'onPrimary', + 'secondary', + 'onSecondary', + 'tertiary', + 'onTertiary', + 'gray', + 'darkGray', + 'grayContainer', + 'lightGrayContainer', + 'error', + 'errorContainer', + 'onErrorContainer', + 'warn', + 'complete', + ], + }, + }, + }, + args: { + topLeftText: '으아니차', + topRightText: '8명', + bottomLeftText: '총액', + bottomRightText: '214,000 원', + onTopLeftTextClick: () => alert('왼쪽 위'), + onTopRightTextClick: () => alert('오른쪽 위'), + onBottomLeftTextClick: () => alert('왼쪽 아래'), + onBottomRightTextClick: () => alert('오른쪽 아래'), + backgroundColor: 'white', + children: ( + <> + <DragHandleItem + hasDragHandler={true} + prefix="뽕쟁이족발" + suffix="198,000원" + backgroundColor="lightGrayContainer" + /> + <DragHandleItem + hasDragHandler={true} + prefix="인생네컷" + suffix="16,000원" + backgroundColor="lightGrayContainer" + /> + </> + ), + }, +} satisfies Meta<typeof DragHandleItemContainer>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts new file mode 100644 index 000000000..b5bab9422 --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts @@ -0,0 +1,34 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export const containerStyle = (theme: Theme, backgroundColor: ColorKeys) => + css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + padding: '0.5rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors[backgroundColor], + }); + +export const topRightTextStyle = (theme: Theme) => + css({ + position: 'relative', + cursor: 'pointer', + + '&::after': { + position: 'absolute', + bottom: '0.125rem', + left: 0, + + width: '100%', + height: '0.03125rem', + + backgroundColor: theme.colors.gray, + + content: "''", + }, + }); diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx new file mode 100644 index 000000000..a95bfb5de --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx @@ -0,0 +1,47 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {containerStyle, topRightTextStyle} from './DragHandleItemContainer.style'; +import {DragHandleItemContainerProps} from './DragHandleItemContainer.type'; + +export const DragHandleItemContainer: React.FC<DragHandleItemContainerProps> = ({ + topLeftText, + bottomLeftText, + topRightText, + bottomRightText, + onTopLeftTextClick, + onBottomLeftTextClick, + onTopRightTextClick, + onBottomRightTextClick, + backgroundColor = 'white', + children, + ...htmlProps +}: DragHandleItemContainerProps) => { + const {theme} = useTheme(); + + return ( + <div css={containerStyle(theme, backgroundColor)} {...htmlProps}> + <Flex justifyContent="spaceBetween" paddingInline="1rem"> + <Text textColor="gray" size="captionBold" onClick={onTopLeftTextClick}> + {topLeftText} + </Text> + <Text textColor="gray" size="caption" onClick={onTopRightTextClick} css={topRightTextStyle(theme)}> + {topRightText} + </Text> + </Flex> + {children} + <Flex justifyContent="spaceBetween" paddingInline="1rem"> + <Text textColor="gray" size="captionBold" onClick={onBottomLeftTextClick}> + {bottomLeftText} + </Text> + <Text textColor="gray" size="caption" onClick={onBottomRightTextClick}> + {bottomRightText} + </Text> + </Flex> + </div> + ); +}; +export default DragHandleItemContainer; diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts new file mode 100644 index 000000000..1bf1129e4 --- /dev/null +++ b/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts @@ -0,0 +1,20 @@ +import {ColorKeys} from '@token/colors'; + +export interface DragHandleItemContainerStyleProps { + backgroundColor?: ColorKeys; +} + +export interface DragHandleItemContainerCustomProps { + topLeftText?: string; + onTopLeftTextClick?: () => void; + bottomLeftText?: string; + onBottomLeftTextClick?: () => void; + topRightText?: string; + onTopRightTextClick?: () => void; + bottomRightText?: string; + onBottomRightTextClick?: () => void; +} + +export type DragHandleItemContainerOptionProps = DragHandleItemContainerStyleProps & DragHandleItemContainerCustomProps; + +export type DragHandleItemContainerProps = React.ComponentProps<'div'> & DragHandleItemContainerOptionProps; diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts new file mode 100644 index 000000000..eadff482e --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.style.ts @@ -0,0 +1,84 @@ +import {css} from '@emotion/react'; + +import {TextSize} from '@components/Text/Text.type'; +import {WithTheme} from '@type/withTheme'; + +import TYPOGRAPHY from '@token/typography'; + +type UnderlineProps = { + hasFocus: boolean; + hasError: boolean; +}; + +type InputSizeStyleProps = { + textSize: TextSize; +}; + +type InputStyleProps = InputSizeStyleProps; + +export const inputWrapperStyle = css({ + display: 'inline-block', +}); + +export const inputStyle = ({theme, textSize}: WithTheme<InputStyleProps>) => [ + inputSizeStyle({textSize}), + inputBaseStyle({theme}), +]; + +const inputSizeStyle = ({textSize}: InputSizeStyleProps) => { + const style = { + head: css(TYPOGRAPHY.head), + title: css(TYPOGRAPHY.title), + subTitle: css(TYPOGRAPHY.subTitle), + bodyBold: css(TYPOGRAPHY.bodyBold), + body: css(TYPOGRAPHY.body), + smallBodyBold: css(TYPOGRAPHY.smallBodyBold), + smallBody: css(TYPOGRAPHY.smallBody), + captionBold: css(TYPOGRAPHY.captionBold), + caption: css(TYPOGRAPHY.caption), + tiny: css(TYPOGRAPHY.tiny), + }; + + return [style[textSize]]; +}; + +const inputBaseStyle = ({theme}: WithTheme) => + css({ + border: 'none', + outline: 'none', + paddingBottom: '0.125rem', + + color: theme.colors.black, + + '&:placeholder': { + color: theme.colors.darkGray, + }, + }); + +export const editingContainerStyle = css({ + opacity: 0, + whiteSpace: 'pre', + position: 'absolute', + pointerEvents: 'none', + padding: 0, + margin: 0, +}); + +export const underlineStyle = ({theme, hasFocus, hasError}: WithTheme<UnderlineProps>) => + css({ + position: 'relative', + display: 'inline-block', + + '&::after': { + content: '""', + position: 'absolute', + + left: 0, + right: 0, + bottom: 0, + height: '0.125rem', + backgroundColor: hasFocus ? theme.colors.primary : hasError ? theme.colors.error : 'transparent', + transition: 'background-color 0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }, + }); diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/HDesign/src/components/EditableItem/EditableItem.Input.tsx new file mode 100644 index 000000000..c0a08bc0e --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.tsx @@ -0,0 +1,54 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef, useEffect, useImperativeHandle, useRef} from 'react'; + +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; +import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {editingContainerStyle, inputStyle, inputWrapperStyle, underlineStyle} from './EditableItem.Input.style'; +import {InputProps} from './EditableItem.Input.type'; +import useEditableItemInput from './useEditableItemInput'; + +export const EditableItemInput = forwardRef<HTMLInputElement, InputProps>(function Input( + {isFixed = false, textSize = 'body', hasError = false, readOnly = false, ...htmlProps}, + ref, +) { + const {theme} = useTheme(); + const inputRef = useRef<HTMLInputElement>(null); + const shadowRef = useRef<HTMLDivElement>(null); + const {hasFocus} = useEditableItemInput({inputRef}); + useImperativeHandle(ref, () => inputRef.current!); + + useEffect(() => { + if (shadowRef.current && inputRef.current) { + inputRef.current.style.width = `${shadowRef.current.offsetWidth}px`; + } + }, [htmlProps.value]); + + return ( + <div css={inputWrapperStyle}> + <Flex flexDirection="row"> + <div ref={shadowRef} css={editingContainerStyle}> + <Text size={textSize}>{htmlProps.value || htmlProps.placeholder}</Text> + </div> + {isFixed && <IsFixedIcon />} + <div css={underlineStyle({theme, hasError, hasFocus})}> + <input + css={inputStyle({ + theme, + textSize, + })} + ref={inputRef} + readOnly={readOnly} + {...htmlProps} + placeholder={htmlProps.placeholder} + /> + </div> + </Flex> + </div> + ); +}); + +export default EditableItemInput; diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.type.ts b/HDesign/src/components/EditableItem/EditableItem.Input.type.ts new file mode 100644 index 000000000..8fdd3d64a --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.Input.type.ts @@ -0,0 +1,22 @@ +import {TextSize} from '@components/Text/Text.type'; + +import {Theme} from '@theme/theme.type'; + +export interface InputStyleProps { + hasError?: boolean; + textSize?: TextSize; +} + +export interface InputCustomProps { + isFixed?: boolean; + value: string | number; + readOnly?: boolean; +} + +export interface InputStylePropsWithTheme extends InputStyleProps { + theme: Theme; +} + +export type InputOptionProps = InputStyleProps & InputCustomProps; + +export type InputProps = React.ComponentProps<'input'> & InputOptionProps; diff --git a/HDesign/src/components/EditableItem/EditableItem.context.tsx b/HDesign/src/components/EditableItem/EditableItem.context.tsx new file mode 100644 index 000000000..a2aeef4bc --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.context.tsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, PropsWithChildren, useContext, useState} from 'react'; + +interface EditableItemContextProps { + hasAnyFocus: boolean; + setHasAnyFocus: React.Dispatch<React.SetStateAction<boolean>>; +} + +const EditableItemContext = createContext<EditableItemContextProps | null>(null); + +export const useEditableItemContext = () => { + const context = useContext(EditableItemContext); + if (!context) { + throw new Error('useEditableItemContext must be used within an EditableItemProvider'); + } + return context; +}; + +export const EditableItemProvider: React.FC<PropsWithChildren> = ({children}: React.PropsWithChildren) => { + const [hasAnyFocus, setHasAnyFocus] = useState(false); + + return <EditableItemContext.Provider value={{hasAnyFocus, setHasAnyFocus}}>{children}</EditableItemContext.Provider>; +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx new file mode 100644 index 000000000..370d07c89 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx @@ -0,0 +1,45 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import EditableItemInput from '@components/EditableItem/EditableItem.Input'; + +import EditableItem from './EditableItem'; +import {EditableItemProvider} from './EditableItem.context'; + +const meta = { + title: 'Components/EditableItemInput', + component: EditableItemInput, + tags: ['autodocs'], + parameters: {}, + argTypes: { + textSize: { + description: '', + control: {type: 'select'}, + }, + hasError: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + placeholder: '지출 내역', + textSize: 'body', + hasError: false, + autoFocus: true, + value: '값', + }, +} satisfies Meta<typeof EditableItemInput>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + return ( + <EditableItemProvider> + <EditableItem.Input {...args} /> + </EditableItemProvider> + ); + }, +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.stories.tsx new file mode 100644 index 000000000..38406727e --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.stories.tsx @@ -0,0 +1,276 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useState} from 'react'; + +import EditableItem from '@components/EditableItem/EditableItem'; +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; + +const meta = { + title: 'Components/EditableItem', + component: EditableItem, + tags: ['autodocs'], + parameters: {}, + argTypes: { + backgroundColor: { + description: '', + control: {type: 'select'}, + }, + }, + args: { + backgroundColor: 'lightGrayContainer', + }, +} satisfies Meta<typeof EditableItem>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + <EditableItem + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={value} + onChange={e => setValue(e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={value2} + onChange={e => setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const WithLabel: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + <EditableItem + prefixLabelText="라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={value} + onChange={e => setValue(e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={value2} + onChange={e => setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const WithLabelAndIsFixedIcon: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + <EditableItem + prefixLabelText="라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={value} + onChange={e => setValue(e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={value2} + onChange={e => setValue2(e.target.value)} + isFixed={true} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const WithLabels: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [value2, setValue2] = useState(''); + + return ( + <EditableItem + prefixLabelText="왼쪽 라벨" + suffixLabelText="오른쪽 라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={value} + onChange={e => setValue(e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={value2} + onChange={e => setValue2(e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const ReadOnly: Story = { + render: ({...args}) => { + return ( + <EditableItem + prefixLabelText="왼쪽 라벨" + suffixLabelText="오른쪽 라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={'훠궈무한리필'} + readOnly + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={'10000'} + readOnly + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const ReadOnlyWithIsFixedIcon: Story = { + render: ({...args}) => { + return ( + <EditableItem + prefixLabelText="왼쪽 라벨" + suffixLabelText="오른쪽 라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <EditableItem.Input + value={'훠궈무한리필'} + readOnly + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + isFixed + value={'10000'} + readOnly + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </EditableItem> + ); + }, +}; + +export const ListView: Story = { + render: ({...args}) => { + const LENGTH = 5; + const [valueList, setValueList] = useState(new Array(LENGTH).fill('')); + const [valueList2, setValueList2] = useState(new Array(LENGTH).fill('')); + + const handleValueListChange = (index: number, newValue: string) => { + const updatedList = [...valueList]; + updatedList[index] = newValue; + setValueList(updatedList); + }; + + const handleValueList2Change = (index: number, newValue: string) => { + const updatedList = [...valueList2]; + updatedList[index] = newValue; + setValueList2(updatedList); + }; + + return ( + <EditableItem + prefixLabelText="라벨" + backgroundColor={args.backgroundColor} + onFocus={() => console.log('focus')} + onBlur={() => console.log('blur')} + > + <Flex flexDirection="column" width="100%" gap="1rem"> + {valueList.map((value, index) => ( + <Flex key={index} justifyContent="spaceBetween"> + <EditableItem.Input + value={value} + onChange={e => handleValueListChange(index, e.target.value)} + placeholder="지출 내역" + textSize="bodyBold" + ></EditableItem.Input> + <Flex gap="0.25rem" alignItems="center"> + <EditableItem.Input + value={valueList2[index]} + onChange={e => handleValueList2Change(index, e.target.value)} + placeholder="0" + type="number" + style={{textAlign: 'right'}} + ></EditableItem.Input> + <Text size="caption">원</Text> + </Flex> + </Flex> + ))} + </Flex> + </EditableItem> + ); + }, +}; diff --git a/HDesign/src/components/EditableItem/EditableItem.style.ts b/HDesign/src/components/EditableItem/EditableItem.style.ts new file mode 100644 index 000000000..97142f2d8 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.style.ts @@ -0,0 +1,21 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export const editableItemStyle = (theme: Theme, backgroundColor: ColorKeys) => + css({ + display: 'flex', + justifyContent: 'space-between', + padding: '0.5rem 1rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors[backgroundColor], + }); + +export const labelTextStyle = (theme: Theme, side: 'prefix' | 'suffix') => + css({ + color: theme.colors.gray, + paddingLeft: side === 'prefix' ? '0.375rem' : 0, + paddingRight: side === 'suffix' ? '0.375rem' : 0, + }); diff --git a/HDesign/src/components/EditableItem/EditableItem.tsx b/HDesign/src/components/EditableItem/EditableItem.tsx new file mode 100644 index 000000000..f8b9ca434 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.tsx @@ -0,0 +1,54 @@ +/** @jsxImportSource @emotion/react */ +import Text from '@components/Text/Text'; +import Flex from '@components/Flex/Flex'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {editableItemStyle, labelTextStyle} from './EditableItem.style'; +import EditableItemInput from './EditableItem.Input'; +import {EditableItemProps} from './EditableItem.type'; +import {EditableItemProvider} from './EditableItem.context'; +import useEditableItem from './useEditableItem'; + +const EditableItemBase = ({ + onInputFocus, + onInputBlur, + prefixLabelText, + suffixLabelText, + backgroundColor = 'white', + children, + ...htmlProps +}: EditableItemProps) => { + const {theme} = useTheme(); + + useEditableItem({onInputFocus, onInputBlur}); + + return ( + <Flex flexDirection="column"> + <Flex justifyContent="spaceBetween" width="100%"> + <Text size="caption" css={labelTextStyle(theme, 'prefix')}> + {prefixLabelText} + </Text> + <Text size="caption" css={labelTextStyle(theme, 'suffix')}> + {suffixLabelText} + </Text> + </Flex> + + <div css={editableItemStyle(theme, backgroundColor)} {...htmlProps}> + {children} + </div> + </Flex> + ); +}; + +export const EditableItem = (props: EditableItemProps) => { + return ( + <EditableItemProvider> + <EditableItemBase {...props} /> + </EditableItemProvider> + ); +}; + +EditableItem.Input = EditableItemInput; + +export default EditableItem; diff --git a/HDesign/src/components/EditableItem/EditableItem.type.ts b/HDesign/src/components/EditableItem/EditableItem.type.ts new file mode 100644 index 000000000..a56835855 --- /dev/null +++ b/HDesign/src/components/EditableItem/EditableItem.type.ts @@ -0,0 +1,22 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export interface EditableItemStyleProps { + backgroundColor?: ColorKeys; +} + +export interface EditableItemCustomProps { + onInputFocus?: () => void; + onInputBlur?: () => void; + prefixLabelText?: string; + suffixLabelText?: string; +} + +export interface EditableItemStylePropsWithTheme extends EditableItemStyleProps { + theme: Theme; +} + +export type EditableItemOptionProps = EditableItemStyleProps & EditableItemCustomProps; + +export type EditableItemProps = React.ComponentProps<'div'> & EditableItemOptionProps; diff --git a/HDesign/src/components/EditableItem/useEditableItem.ts b/HDesign/src/components/EditableItem/useEditableItem.ts new file mode 100644 index 000000000..86880deb6 --- /dev/null +++ b/HDesign/src/components/EditableItem/useEditableItem.ts @@ -0,0 +1,23 @@ +import {useEffect} from 'react'; + +import {useEditableItemContext} from './EditableItem.context'; + +interface UseEditableItemProps { + onInputFocus?: () => void; + onInputBlur?: () => void; +} + +const useEditableItem = ({onInputFocus, onInputBlur}: UseEditableItemProps) => { + const {hasAnyFocus} = useEditableItemContext(); + + useEffect(() => { + if (hasAnyFocus && onInputFocus) { + onInputFocus(); + } + if (!hasAnyFocus && onInputBlur) { + onInputBlur(); + } + }, [hasAnyFocus, onInputFocus, onInputBlur]); +}; + +export default useEditableItem; diff --git a/HDesign/src/components/EditableItem/useEditableItemInput.ts b/HDesign/src/components/EditableItem/useEditableItemInput.ts new file mode 100644 index 000000000..3253ad0ea --- /dev/null +++ b/HDesign/src/components/EditableItem/useEditableItemInput.ts @@ -0,0 +1,46 @@ +import {useCallback, useEffect, useState} from 'react'; + +import {useEditableItemContext} from './EditableItem.context'; + +interface UseEditableItemInputProps { + inputRef: React.RefObject<HTMLInputElement>; +} + +const useEditableItemInput = ({inputRef}: UseEditableItemInputProps) => { + const [hasFocus, setHasFocus] = useState(false); + const {setHasAnyFocus} = useEditableItemContext(); + + const handleFocus = useCallback(() => { + setHasFocus(true); + setHasAnyFocus(true); + }, [setHasAnyFocus]); + + const handleBlur = useCallback(() => { + setHasFocus(false); + setHasAnyFocus(false); + }, [setHasAnyFocus]); + + useEffect(() => { + const input = inputRef.current; + + if (input) { + input.addEventListener('focus', handleFocus); + input.addEventListener('blur', handleBlur); + + return () => { + input.removeEventListener('focus', handleFocus); + input.removeEventListener('blur', handleBlur); + }; + } + }, [handleFocus, handleBlur, inputRef]); + + useEffect(() => { + if (document.activeElement === inputRef.current) { + handleFocus(); + } + }, [handleFocus, inputRef]); + + return {hasFocus}; +}; + +export default useEditableItemInput; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx b/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx new file mode 100644 index 000000000..ccf8e28de --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ExpenseList from '@components/ExpenseList/ExpenseList'; + +const meta = { + title: 'Components/ExpenseList', + component: ExpenseList, + tags: ['autodocs'], + argTypes: { + expenseList: { + description: '', + }, + }, + args: { + expenseList: [ + {name: '소하', price: 2000}, + {name: '토다리', price: 2000}, + {name: '웨디', price: 1080}, + {name: '쿠키', price: 3020}, + ], + }, +} satisfies Meta<typeof ExpenseList>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.style.ts b/HDesign/src/components/ExpenseList/ExpenseList.style.ts new file mode 100644 index 000000000..8dbd227aa --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.style.ts @@ -0,0 +1,29 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const expenseItemStyle = () => + css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + height: '2.5rem', + padding: '0.5rem 1rem', + }); + +export const expenseItemLeftStyle = () => + css({ + display: 'flex', + alignItems: 'center', + gap: '1rem', + }); + +export const expenseListStyle = (theme: Theme) => + css({ + width: '100%', + backgroundColor: theme.colors.white, + padding: '0.5rem 0', + borderRadius: '1rem', + height: '100%', + }); diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/HDesign/src/components/ExpenseList/ExpenseList.tsx new file mode 100644 index 000000000..1f57810e5 --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.tsx @@ -0,0 +1,37 @@ +/** @jsxImportSource @emotion/react */ + +import Text from '@components/Text/Text'; +import Icon from '@components/Icon/Icon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; +import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle} from './ExpenseList.style'; + +// TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 +// TODO: (@todari) : 추후 클릭 시 상호작용이 생기면 iconButton으로 변경할 수 있음 +function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { + const {theme} = useTheme(); + return ( + <button css={expenseItemStyle} {...buttonProps}> + <Text size="bodyBold">{name}</Text> + <div css={expenseItemLeftStyle}> + <Text>{price.toLocaleString('ko-kr')}원</Text> + <Icon iconType="rightChevron" /> + </div> + </button> + ); +} + +function ExpenseList({expenseList = []}: ExpenseListProps) { + const {theme} = useTheme(); + return ( + <div css={expenseListStyle(theme)}> + {expenseList.map(({name, price}, index: number) => ( + <ExpenseItem key={name + index} name={name} price={price} /> + ))} + </div> + ); +} + +export default ExpenseList; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.type.ts b/HDesign/src/components/ExpenseList/ExpenseList.type.ts new file mode 100644 index 000000000..939cd2f68 --- /dev/null +++ b/HDesign/src/components/ExpenseList/ExpenseList.type.ts @@ -0,0 +1,10 @@ +export interface ExpenseItemCustomProps { + name: string; + price: number; +} + +export type ExpenseItemProps = React.ComponentProps<'button'> & ExpenseItemCustomProps; + +export type ExpenseListProps = { + expenseList: ExpenseItemProps[]; +}; diff --git a/HDesign/src/components/FixedButton/FixedButton.stories.tsx b/HDesign/src/components/FixedButton/FixedButton.stories.tsx new file mode 100644 index 000000000..47485f851 --- /dev/null +++ b/HDesign/src/components/FixedButton/FixedButton.stories.tsx @@ -0,0 +1,46 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import FixedButton from '@components/FixedButton/FixedButton'; + +const meta = { + title: 'Components/FixedButton', + component: FixedButton, + tags: ['autodocs'], + parameters: {}, + argTypes: { + variants: { + description: '', + control: {type: 'select'}, + options: ['', 'primary', 'secondary', 'tertiary', 'loading'], + }, + disabled: { + description: '', + control: {type: 'boolean'}, + }, + onDeleteClick: { + description: '', + control: {type: 'select'}, + options: [undefined, () => alert('delete')], + }, + }, + args: { + variants: 'primary', + disabled: false, + children: 'button', + onDeleteClick: () => alert('delete'), + }, + decorators: [ + Story => ( + <div style={{height: '420px'}}> + <Story /> + </div> + ), + ], +} satisfies Meta<typeof FixedButton>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/HDesign/src/components/FixedButton/FixedButton.style.ts new file mode 100644 index 000000000..2e774918d --- /dev/null +++ b/HDesign/src/components/FixedButton/FixedButton.style.ts @@ -0,0 +1,127 @@ +import {css} from '@emotion/react'; + +import {ButtonVariants} from '@components/Button/Button.type'; +import {FixedButtonStyleProps} from '@components/FixedButton/FixedButton.type'; + +import {Theme} from '@theme/theme.type'; + +import {setDarker, setLighter} from '@utils/colors'; + +export const fixedButtonContainerStyle = (theme: Theme) => + css({ + display: 'flex', + position: 'fixed', + maxWidth: '768px', + inset: 'auto 0 0', + margin: '0 auto', + backgroundColor: theme.colors.white, + boxSizing: 'border-box', + }); + +export const buttonContainerStyle = css({ + display: 'flex', + gap: '1rem', + margin: '1rem 1rem 2rem 1rem', + width: '100%', +}); + +const getHoverAndActiveBackground = (color: string) => + css({ + ':not(:disabled)': { + '&:hover': { + backgroundColor: setLighter(color, 0.15), + }, + '&:active': { + backgroundColor: setDarker(color, 0.15), + }, + }, + }); + +export const deleteButtonStyle = (theme: Theme) => [ + css({ + display: 'flex', + justifyContent: 'center', + padding: '0.875rem 1rem', + borderRadius: '1.25rem', + backgroundColor: theme.colors.error, + color: theme.colors.white, + + fontFamily: 'Pretendard', + fontSize: '1rem', + fontWeight: '700', + lineHeight: '1', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }), + getHoverAndActiveBackground(theme.colors.error), +]; + +export const fixedButtonStyle = (props: Required<FixedButtonStyleProps>) => { + return [getFixedButtonDefaultStyle(props.theme), getFixedButtonVariantsStyle(props.variants, props.theme)]; +}; + +const getFixedButtonDefaultStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + padding: '1rem 1.5rem', + borderRadius: '1rem', + width: '100%', + + fontFamily: 'Pretendard', + fontSize: '1.25rem', + fontWeight: '700', + lineHeight: '1', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + '&:disabled': { + backgroundColor: theme.colors.tertiary, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + +const getFixedButtonVariantsStyle = (variants: ButtonVariants, theme: Theme) => { + const style = { + primary: [ + css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.primary), + ], + secondary: [ + css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + getHoverAndActiveBackground(theme.colors.secondary), + ], + tertiary: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + destructive: [ + css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.error), + ], + loading: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + }; + + return style[variants]; +}; diff --git a/HDesign/src/components/FixedButton/FixedButton.tsx b/HDesign/src/components/FixedButton/FixedButton.tsx new file mode 100644 index 000000000..4430016d6 --- /dev/null +++ b/HDesign/src/components/FixedButton/FixedButton.tsx @@ -0,0 +1,48 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef} from 'react'; +import Lottie from 'lottie-react'; + +import { + fixedButtonContainerStyle, + fixedButtonStyle, + buttonContainerStyle, +} from '@components/FixedButton/FixedButton.style'; +import {FixedButtonProps} from '@components/FixedButton/FixedButton.type'; +import IconButton from '@components/IconButton/IconButton'; +import Icon from '@components/Icon/Icon'; + +import loadingAnimation from '@assets/loadingAnimation.json'; + +import {useTheme} from '@theme/HDesignProvider'; + +export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElement, FixedButtonProps>(function Button( + {variants = 'primary', onDeleteClick, disabled, children, ...htmlProps}: FixedButtonProps, + ref, +) { + const {theme} = useTheme(); + return ( + <div css={fixedButtonContainerStyle(theme)}> + <div css={buttonContainerStyle}> + {onDeleteClick && ( + <IconButton type="button" size="large" variants="destructive" onClick={onDeleteClick}> + <Icon iconType="trash" /> + </IconButton> + )} + <button + css={fixedButtonStyle({variants, theme})} + ref={ref} + disabled={variants === 'loading' ? true : disabled} + {...htmlProps} + > + {variants === 'loading' ? ( + <Lottie animationData={loadingAnimation} loop={true} style={{width: 240, height: 20}} /> + ) : ( + children + )} + </button> + </div> + </div> + ); +}); + +export default FixedButton; diff --git a/HDesign/src/components/FixedButton/FixedButton.type.ts b/HDesign/src/components/FixedButton/FixedButton.type.ts new file mode 100644 index 000000000..1e8c55144 --- /dev/null +++ b/HDesign/src/components/FixedButton/FixedButton.type.ts @@ -0,0 +1,16 @@ +import {ButtonVariants} from '@components/Button/Button.type'; + +import {Theme} from '@theme/theme.type'; + +export interface FixedButtonStyleProps { + variants?: ButtonVariants; + theme?: Theme; +} + +export interface ButtonCustomProps { + onDeleteClick?: () => void; +} + +export type FixedButtonOptionProps = FixedButtonStyleProps & ButtonCustomProps; + +export type FixedButtonProps = React.ComponentProps<'button'> & FixedButtonOptionProps; diff --git a/HDesign/src/components/Flex/Flex.style.ts b/HDesign/src/components/Flex/Flex.style.ts new file mode 100644 index 000000000..672cf2dd6 --- /dev/null +++ b/HDesign/src/components/Flex/Flex.style.ts @@ -0,0 +1,49 @@ +import {css} from '@emotion/react'; + +import {changeCamelCaseToKebabCase} from '@utils/changeCamelCaseToKebabCase'; + +import {FlexDirectionStrictType, FlexProps} from './Flex.type'; + +export const flexStyle = ({ + justifyContent = 'flexStart', + alignItems = 'stretch', + flexDirection = 'row', + gap = '0', + padding = '0', + paddingInline = '0', + margin = '0', + width = 'auto', + height = 'auto', + minHeight, + backgroundColor, + theme, + ...rest +}: FlexProps) => + css({ + display: 'flex', + justifyContent: changeCamelCaseToKebabCase(justifyContent), + alignItems: changeCamelCaseToKebabCase(alignItems), + // TODO: (@weadie) as를 사용하지 않으면 방법이 없음. css의 flexDirection속성은 string을 받지 않고 명확한 속성명(ex row-reverse)를 받고 싶어함. 다만 as를 사용해도 된다고 생각한 근거는 케밥함수가 FlexDirectionType에 명시된 모든 타입을 정확하게 변환하며, 받는 문자열이 FlexDirectionType에 제한되기 때문. + flexDirection: changeCamelCaseToKebabCase(flexDirection) as FlexDirectionStrictType, + gap, + padding, + paddingInline, + margin, + width, + height, + minHeight, + ...rest, + + backgroundColor: (() => { + switch (backgroundColor) { + case 'white': + return theme?.colors.white; + case 'gray': + return theme?.colors.grayContainer; + case 'lightGray': + return theme?.colors.lightGrayContainer; + default: + return 'none'; + } + })(), + }); diff --git a/HDesign/src/components/Flex/Flex.tsx b/HDesign/src/components/Flex/Flex.tsx new file mode 100644 index 000000000..26ce953f7 --- /dev/null +++ b/HDesign/src/components/Flex/Flex.tsx @@ -0,0 +1,17 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {FlexProps} from './Flex.type'; +import {flexStyle} from './Flex.style'; + +// TODO: (@weadie) 지정된 프롭 말고 다른 프롭도 가져올 수 있게 하자. +function Flex({children, ...props}: StrictPropsWithChildren<FlexProps>) { + const {theme} = useTheme(); + return <div css={flexStyle({theme, ...props})}>{children}</div>; +} + +export default Flex; diff --git a/HDesign/src/components/Flex/Flex.type.ts b/HDesign/src/components/Flex/Flex.type.ts new file mode 100644 index 000000000..e70fb4c21 --- /dev/null +++ b/HDesign/src/components/Flex/Flex.type.ts @@ -0,0 +1,20 @@ +import {Theme} from '@theme/theme.type'; + +export type FlexDirectionType = 'row' | 'column' | 'rowReverse' | 'columnReverse'; +export type FlexDirectionStrictType = 'row' | 'column' | 'row-reverse' | 'column-reverse'; +export type FlexBackgroundColor = 'gray' | 'white' | 'lightGray'; + +export interface FlexProps { + justifyContent?: 'flexStart' | 'center' | 'flexEnd' | 'spaceBetween' | 'spaceAround' | 'spaceEvenly'; + alignItems?: 'flexStart' | 'center' | 'flexEnd' | 'stretch' | 'baseline'; + flexDirection?: FlexDirectionType; + gap?: string; + padding?: string; + paddingInline?: string; + margin?: string; + width?: string; + height?: string; + backgroundColor?: FlexBackgroundColor; + theme?: Theme; + minHeight?: string; +} diff --git a/HDesign/src/components/Icon/Icon.stories.tsx b/HDesign/src/components/Icon/Icon.stories.tsx new file mode 100644 index 000000000..3d2ef4aae --- /dev/null +++ b/HDesign/src/components/Icon/Icon.stories.tsx @@ -0,0 +1,28 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Icon from '@components/Icon/Icon'; + +const meta = { + title: 'Components/Icon', + component: Icon, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + iconType: { + description: '', + control: {type: 'select'}, + options: ['inputDelete', 'buljusa', 'rightChevron', 'search', 'confirm', 'error', 'trash'], + }, + }, + args: { + iconType: 'rightChevron', + }, +} satisfies Meta<typeof Icon>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Icon/Icon.style.ts b/HDesign/src/components/Icon/Icon.style.ts new file mode 100644 index 000000000..b19601da6 --- /dev/null +++ b/HDesign/src/components/Icon/Icon.style.ts @@ -0,0 +1,38 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +import {IconColor, IconStylePropsWithTheme, IconType} from './Icon.type'; + +const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { + inputDelete: 'gray', + buljusa: 'gray', + rightChevron: 'gray', + search: 'gray', + confirm: 'complete', + error: 'warn', + trash: 'white', +}; + +export const iconStyle = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { + return [ + css({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + }), + getIconColor({iconType, theme, iconColor}), + ]; +}; + +const getIconColor = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { + if (iconColor) { + return css({ + color: theme.colors[iconColor as ColorKeys], + }); + } else { + return css({color: theme.colors[ICON_DEFAULT_COLOR[iconType]]}); + } +}; diff --git a/HDesign/src/components/Icon/Icon.tsx b/HDesign/src/components/Icon/Icon.tsx new file mode 100644 index 000000000..13d8e7835 --- /dev/null +++ b/HDesign/src/components/Icon/Icon.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ + +import {IconProps} from '@components/Icon/Icon.type'; +import {InputDelete, Buljusa, RightChevron, Search, Trash, Confirm, Error} from '@assets'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {iconStyle} from './Icon.style'; + +const ICON = { + inputDelete: <InputDelete />, + buljusa: <Buljusa />, + rightChevron: <RightChevron />, + search: <Search />, + error: <Error />, + confirm: <Confirm />, + trash: <Trash />, +}; + +export const Icon: React.FC<IconProps> = ({iconColor, iconType, ...htmlProps}: IconProps) => { + const {theme} = useTheme(); + return ( + <div css={iconStyle({iconType, theme, iconColor})} {...htmlProps}> + {ICON[iconType]} + </div> + ); +}; + +export default Icon; diff --git a/HDesign/src/components/Icon/Icon.type.ts b/HDesign/src/components/Icon/Icon.type.ts new file mode 100644 index 000000000..57fc25cfb --- /dev/null +++ b/HDesign/src/components/Icon/Icon.type.ts @@ -0,0 +1,21 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export type IconType = 'inputDelete' | 'buljusa' | 'rightChevron' | 'search' | 'error' | 'confirm' | 'trash'; +export type IconColor = ColorKeys; + +export interface IconStyleProps { + iconColor?: IconColor; + iconType: IconType; +} + +export interface IconStylePropsWithTheme extends IconStyleProps { + theme: Theme; +} + +export interface IconCustomProps {} + +export type IconOptionProps = IconStyleProps & IconCustomProps; + +export type IconProps = React.ComponentProps<'div'> & IconOptionProps; diff --git a/HDesign/src/components/IconButton/IconButton.stories.tsx b/HDesign/src/components/IconButton/IconButton.stories.tsx new file mode 100644 index 000000000..6cc2b5f3d --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.stories.tsx @@ -0,0 +1,51 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import IconButton from '@components/IconButton/IconButton'; +import Icon from '@components/Icon/Icon'; + +const meta = { + title: 'Components/IconButton', + component: IconButton, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + size: { + description: '', + control: {type: 'select'}, + options: ['large', 'medium', 'small'], + }, + variants: { + description: '', + control: {type: 'select'}, + options: ['none', 'primary', 'secondary', 'tertiary', 'destructive'], + }, + children: { + description: '', + control: {type: 'select'}, + // TODO: (@todari) : Icon의 색상을 variants에 의해 자동으로 변경해 줄 수 있는 로직 추가 + options: [ + <Icon iconType="inputDelete" />, + <Icon iconType="buljusa" />, + <Icon iconType="rightChevron" />, + <Icon iconType="search" />, + <Icon iconType="confirm" />, + <Icon iconType="error" />, + <Icon iconType="trash" />, + ], + }, + }, + args: { + size: 'medium', + variants: 'destructive', + children: <Icon iconType="trash" />, + }, +} satisfies Meta<typeof IconButton>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/IconButton/IconButton.style.ts b/HDesign/src/components/IconButton/IconButton.style.ts new file mode 100644 index 000000000..53036eb68 --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.style.ts @@ -0,0 +1,102 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {setDarker, setLighter} from '@utils/colors'; + +import { + IconButtonSize, + IconButtonStyleProps, + IconButtonStylePropsWithTheme, + IconButtonVariants, +} from './IconButton.type'; + +export const iconButtonStyle = ({theme, size = 'large', variants}: IconButtonStylePropsWithTheme) => { + if (variants === 'none') { + return 'none'; + } + return [getIconButtonBase(theme), getIconButtonSize(size), getIconButtonVariants({variants, theme})]; +}; + +const getHoverAndActiveBackground = (color: string) => + css({ + ':not(:disabled)': { + '&:hover': { + backgroundColor: setLighter(color, 0.15), + }, + '&:active': { + backgroundColor: setDarker(color, 0.15), + }, + }, + }); + +const getIconButtonBase = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + whiteSpace: 'nowrap', + + '&:disabled': { + backgroundColor: theme.colors.tertiary, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + +const getIconButtonSize = (size: IconButtonSize) => { + const style = { + small: css({ + padding: '0.5rem', + borderRadius: '0.75rem', + }), + medium: css({ + padding: '0.75rem', + borderRadius: '1rem', + }), + large: css({ + padding: '0.875rem', + borderRadius: '1.125rem', + }), + }; + + return style[size]; +}; + +const getIconButtonVariants = ({variants, theme}: IconButtonStylePropsWithTheme) => { + const style = { + none: [css({})], + primary: [ + css({ + backgroundColor: theme.colors.primary, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.primary), + ], + secondary: [ + css({ + backgroundColor: theme.colors.secondary, + color: theme.colors.onSecondary, + }), + getHoverAndActiveBackground(theme.colors.secondary), + ], + tertiary: [ + css({ + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + }), + getHoverAndActiveBackground(theme.colors.tertiary), + ], + destructive: [ + css({ + backgroundColor: theme.colors.error, + color: theme.colors.onPrimary, + }), + getHoverAndActiveBackground(theme.colors.error), + ], + }; + + return style[variants]; +}; diff --git a/HDesign/src/components/IconButton/IconButton.tsx b/HDesign/src/components/IconButton/IconButton.tsx new file mode 100644 index 000000000..bc704db67 --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.tsx @@ -0,0 +1,22 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef} from 'react'; + +import {IconButtonProps} from '@components/IconButton/IconButton.type'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {iconButtonStyle} from './IconButton.style'; + +export const IconButton: React.FC<IconButtonProps> = forwardRef<HTMLButtonElement, IconButtonProps>(function Button( + {size, variants, children, ...htmlProps}: IconButtonProps, + ref, +) { + const {theme} = useTheme(); + return ( + <button ref={ref} css={iconButtonStyle({theme, size, variants})} {...htmlProps}> + {children} + </button> + ); +}); + +export default IconButton; diff --git a/HDesign/src/components/IconButton/IconButton.type.ts b/HDesign/src/components/IconButton/IconButton.type.ts new file mode 100644 index 000000000..de891e0ba --- /dev/null +++ b/HDesign/src/components/IconButton/IconButton.type.ts @@ -0,0 +1,19 @@ +import {Theme} from '@theme/theme.type'; + +export type IconButtonSize = 'large' | 'medium' | 'small'; +export type IconButtonVariants = 'none' | 'primary' | 'secondary' | 'tertiary' | 'destructive'; + +export interface IconButtonStyleProps { + size?: IconButtonSize; + variants: IconButtonVariants; +} + +export interface IconButtonStylePropsWithTheme extends IconButtonStyleProps { + theme: Theme; +} + +export interface IconButtonCustomProps {} + +export type IconButtonOptionProps = IconButtonStyleProps & IconButtonCustomProps; + +export type IconButtonProps = React.ComponentProps<'button'> & IconButtonOptionProps; diff --git a/HDesign/src/components/Input/Input.stories.tsx b/HDesign/src/components/Input/Input.stories.tsx new file mode 100644 index 000000000..dc46e022f --- /dev/null +++ b/HDesign/src/components/Input/Input.stories.tsx @@ -0,0 +1,56 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import React, {useEffect, useState} from 'react'; + +import Input from '@components/Input/Input'; +import Flex from '@components/Flex/Flex'; +import Button from '@components/Button/Button'; + +const meta = { + title: 'Components/Input', + component: Input, + tags: ['autodocs'], + argTypes: { + inputType: { + // TODO: (@cookie) 스토리북 라디오버튼 보이도록 설정해야 함 + control: {type: 'radio'}, + }, + }, + args: { + placeholder: 'placeholder', + autoFocus: true, + }, +} satisfies Meta<typeof Input>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + const regex = /^[ㄱ-ㅎ가-힣]*$/; + const [value, setValue] = useState(''); + const [isError, setIsError] = useState(false); + + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + if (regex.test(newValue)) { + setValue(newValue); + setIsError(false); + } else { + setIsError(true); + } + }; + + const changeRandomValue = () => { + setValue('외부에서 값 변경됨'); + }; + + return ( + <div style={{display: 'flex', flexDirection: 'column', gap: '1rem'}}> + <Button onClick={changeRandomValue}>input 값 변경</Button> + <Input value={value} onChange={handleChange} isError={isError} {...args} /> + </div> + ); + }, +}; diff --git a/HDesign/src/components/Input/Input.style.ts b/HDesign/src/components/Input/Input.style.ts new file mode 100644 index 000000000..a9ddff89d --- /dev/null +++ b/HDesign/src/components/Input/Input.style.ts @@ -0,0 +1,56 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {InputType} from './Input.type'; + +const getBackgroundColorStyle = (theme: Theme, inputType: InputType = 'input') => { + switch (inputType) { + case 'input': + return theme.colors.lightGrayContainer; + + case 'search': + return theme.colors.white; + + default: + return theme.colors.lightGrayContainer; + } +}; + +const getBorderStyle = (isFocus: boolean, theme: Theme, isError?: boolean) => + isError ? `0 0 0 1px ${theme.colors.error} inset` : isFocus ? `0 0 0 1px ${theme.colors.primary} inset` : 'none'; + +export const inputBoxStyle = ( + theme: Theme, + inputType: InputType = 'input', + isFocus: boolean, + isError: boolean | undefined, +) => + css({ + display: 'flex', + justifyContent: 'space-between', + gap: '1rem', + padding: '0.75rem 1rem', + borderRadius: '1rem', + backgroundColor: getBackgroundColorStyle(theme, inputType), + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + boxSizing: 'border-box', + boxShadow: getBorderStyle(isFocus, theme, isError), + }); + +export const inputStyle = (theme: Theme) => + css( + { + display: 'flex', + width: '100%', + color: theme.colors.black, + + '&:placeholder': { + color: theme.colors.gray, + }, + }, + theme.typography.body, + ); diff --git a/HDesign/src/components/Input/Input.tsx b/HDesign/src/components/Input/Input.tsx new file mode 100644 index 000000000..37945e434 --- /dev/null +++ b/HDesign/src/components/Input/Input.tsx @@ -0,0 +1,51 @@ +/** @jsxImportSource @emotion/react */ +import React, {forwardRef, useImperativeHandle, useRef} from 'react'; + +import IconButton from '@components/IconButton/IconButton'; +import {InputProps} from '@components/Input/Input.type'; +import {inputBoxStyle, inputStyle} from '@components/Input/Input.style'; +import {useInput} from '@components/Input/useInput'; +import Icon from '@components/Icon/Icon'; + +import {useTheme} from '@theme/HDesignProvider'; + +export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( + {value: propsValue, onChange, onFocus, onBlur, inputType, isError, placeholder, autoFocus, ...htmlProps}: InputProps, + ref, +) { + const {theme} = useTheme(); + const inputRef = useRef<HTMLInputElement>(null); + const {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown} = useInput({ + propsValue, + onChange, + onBlur, + onFocus, + inputRef, + autoFocus, + }); + useImperativeHandle(ref, () => inputRef.current!); + + return ( + <div css={inputBoxStyle(theme, inputType, hasFocus, isError)}> + <input + css={inputStyle(theme)} + ref={inputRef} + value={value} + onChange={handleChange} + onBlur={handleBlur} + onFocus={handleFocus} + placeholder={value ? '' : placeholder} + onKeyDown={handleKeyDown} + autoFocus={autoFocus} + {...htmlProps} + /> + {value && hasFocus && ( + <IconButton tabIndex={-1} variants="none" onMouseDown={handleClickDelete}> + <Icon iconType="inputDelete" /> + </IconButton> + )} + </div> + ); +}); + +export default Input; diff --git a/HDesign/src/components/Input/Input.type.ts b/HDesign/src/components/Input/Input.type.ts new file mode 100644 index 000000000..2cfdfcd4a --- /dev/null +++ b/HDesign/src/components/Input/Input.type.ts @@ -0,0 +1,16 @@ +import {Theme} from '@theme/theme.type'; + +export interface InputStyleProps { + theme?: Theme; +} + +export type InputType = 'input' | 'search'; + +export interface InputCustomProps { + inputType?: InputType; + isError?: boolean; +} + +export type InputOptionProps = InputStyleProps & InputCustomProps; + +export type InputProps = React.ComponentProps<'input'> & InputOptionProps; diff --git a/HDesign/src/components/Input/useInput.ts b/HDesign/src/components/Input/useInput.ts new file mode 100644 index 000000000..a9e531a07 --- /dev/null +++ b/HDesign/src/components/Input/useInput.ts @@ -0,0 +1,71 @@ +import {RefObject, useEffect, useState} from 'react'; + +interface UseInputProps<T> { + propsValue: T; + onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void; + onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void; + onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void; + inputRef: RefObject<HTMLInputElement>; + autoFocus?: boolean; +} + +export const useInput = <T>({propsValue, onChange, onBlur, onFocus, autoFocus, inputRef}: UseInputProps<T>) => { + const [value, setValue] = useState<T>(propsValue); + const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); + + useEffect(() => { + if (autoFocus && inputRef.current) { + inputRef.current.focus(); + setHasFocus(true); + } + }, [autoFocus, inputRef]); + + useEffect(() => { + setValue(propsValue); + }, [propsValue, value]); + + const handleClickDelete = (event: React.MouseEvent) => { + event.preventDefault(); + setValue('' as T); + if (onChange) { + onChange({target: {value: ''}} as React.ChangeEvent<HTMLInputElement>); + } + if (inputRef.current) { + inputRef.current.focus(); + } + }; + + const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { + setValue(e.target.value as T); + if (onChange) { + onChange(e); + } + }; + + const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => { + setHasFocus(false); + if (onBlur) { + onBlur(e); + } + }; + + const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => { + setHasFocus(true); + if (onFocus) { + onFocus(e); + } + }; + + const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.nativeEvent.isComposing) return; + + if (event.key === 'Enter' || event.key === 'Escape') { + setHasFocus(false); + if (inputRef.current) { + inputRef.current.blur(); + } + } + }; + + return {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown}; +}; diff --git a/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts b/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts new file mode 100644 index 000000000..6ba001e05 --- /dev/null +++ b/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +import {WithTheme} from '@type/withTheme'; + +export const isFixedIconStyle = ({theme}: WithTheme) => + css({ + color: theme.colors.error, + paddingRight: '0.25rem', + }); diff --git a/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx b/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx new file mode 100644 index 000000000..a7b62d959 --- /dev/null +++ b/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx @@ -0,0 +1,13 @@ +/** @jsxImportSource @emotion/react */ + +import {useTheme} from '@theme/HDesignProvider'; + +import {isFixedIconStyle} from './IsFixedIcon.style'; + +const IsFixedIcon = () => { + const {theme} = useTheme(); + + return <div css={isFixedIconStyle({theme})}>*</div>; +}; + +export default IsFixedIcon; diff --git a/HDesign/src/components/LabelGroupInput/Element.tsx b/HDesign/src/components/LabelGroupInput/Element.tsx new file mode 100644 index 000000000..5ffd852bd --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/Element.tsx @@ -0,0 +1,63 @@ +/** @jsxImportSource @emotion/react */ + +import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; + +import Input from '../Input/Input'; + +import {ElementProps} from './Element.type'; +import {useGroupInputContext} from './GroupInputContext'; + +const Element: React.FC<ElementProps> = forwardRef<HTMLInputElement, ElementProps>(function Element( + {elementKey, value: propsValue, onChange, onBlur, onFocus, isError, autoFocus, ...htmlProps}: ElementProps, + + ref, +) { + useImperativeHandle(ref, () => inputRef.current!); + const inputRef = useRef<HTMLInputElement>(null); + const {setHasAnyFocus, values, setValues, errors, setErrors} = useGroupInputContext(); + + useEffect(() => { + setValues({...values, [elementKey]: `${propsValue}`}); + }, [propsValue]); + + const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { + const newValue = e.target.value; + setValues({...values, [elementKey]: newValue}); + if (onChange) { + onChange(e); + } + }; + + useEffect(() => { + setErrors({...errors, [elementKey]: isError ?? false}); + }, [isError]); + + const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => { + setHasAnyFocus(false); + if (onBlur) { + onBlur(e); + } + }; + + const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => { + setHasAnyFocus(true); + if (onFocus) { + onFocus(e); + } + }; + + return ( + <Input + ref={inputRef} + isError={isError} + value={propsValue} + onChange={handleChange} + onBlur={handleBlur} + onFocus={handleFocus} + autoFocus={autoFocus} + {...htmlProps} + /> + ); +}); + +export default Element; diff --git a/HDesign/src/components/LabelGroupInput/Element.type.ts b/HDesign/src/components/LabelGroupInput/Element.type.ts new file mode 100644 index 000000000..2ec2ef9ed --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/Element.type.ts @@ -0,0 +1,10 @@ +export interface ElementStyleProps {} + +export interface ElementCustomProps { + elementKey: string; + isError?: boolean; +} + +export type ElementOptionProps = ElementStyleProps & ElementCustomProps; + +export type ElementProps = React.ComponentProps<'input'> & ElementOptionProps; diff --git a/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx b/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx new file mode 100644 index 000000000..142183e6b --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx @@ -0,0 +1,32 @@ +import React, {createContext, PropsWithChildren, useContext, useState} from 'react'; + +interface GroupInputContextProps { + hasAnyFocus: boolean; + setHasAnyFocus: React.Dispatch<React.SetStateAction<boolean>>; + values: {[key: string]: string}; + setValues: React.Dispatch<React.SetStateAction<{[key: string]: string}>>; + errors: {[key: string]: boolean}; + setErrors: React.Dispatch<React.SetStateAction<{[key: string]: boolean}>>; +} + +const GroupInputContext = createContext<GroupInputContextProps | undefined>(undefined); + +export const useGroupInputContext = () => { + const context = useContext(GroupInputContext); + if (!context) { + throw new Error('useGroupInputContext must be used within an GroupInputProvider'); + } + return context; +}; + +export const GroupInputProvider: React.FC<PropsWithChildren> = ({children}: React.PropsWithChildren) => { + const [hasAnyFocus, setHasAnyFocus] = useState(false); + const [values, setValues] = useState<{[key: string]: string}>({}); + const [errors, setErrors] = useState<{[key: string]: boolean}>({}); + + return ( + <GroupInputContext.Provider value={{hasAnyFocus, setHasAnyFocus, values, setValues, errors, setErrors}}> + {children} + </GroupInputContext.Provider> + ); +}; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx b/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx new file mode 100644 index 000000000..4eec9634f --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx @@ -0,0 +1,75 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useState} from 'react'; + +import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; + +const meta = { + title: 'Components/LabelGroupInput', + component: LabelGroupInput, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + labelText: { + description: 'label에 들어갈 텍스트를 작성', + control: {type: 'text'}, + }, + errorText: { + description: 'error에 들어갈 텍스트를 작성', + control: {type: 'text'}, + }, + }, + args: { + labelText: '지출내역 / 금액', + errorText: 'error가 발생했을 때 나타납니다!', + }, +} satisfies Meta<typeof LabelGroupInput>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + const [name, setName] = useState(''); + const [price, setPrice] = useState(''); + const [isError, setIsError] = useState(false); + const handleChangeName = (event: React.ChangeEvent<HTMLInputElement>) => { + if (event.target.value.length < 4) { + setName(event.target.value); + setIsError(false); + } else { + event.target.value = name; + setIsError(true); + } + }; + const handleChangePrice = (event: React.ChangeEvent<HTMLInputElement>) => { + setPrice(event.target.value); + }; + return ( + <LabelGroupInput {...args}> + <LabelGroupInput.Element + elementKey="name" + placeholder="지출내역" + value={name} + onChange={e => handleChangeName(e)} + onBlur={() => console.log('!!!')} + isError={isError} + autoFocus + /> + <LabelGroupInput.Element + value={price} + onChange={handleChangePrice} + elementKey="price" + placeholder="금액" + onBlur={() => console.log('!!!')} + isError={false} + autoFocus + /> + </LabelGroupInput> + ); + }, +}; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts b/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts new file mode 100644 index 000000000..8339ef4a4 --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts @@ -0,0 +1,25 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@/theme/theme.type'; + +export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => + css({ + height: '1.125rem', + color: theme.colors.gray, + + opacity: hasFocus || hasValue ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); + +export const errorTextStyle = (theme: Theme, isError: boolean) => + css({ + height: '1.125rem', + color: theme.colors.onErrorContainer, + + opacity: isError ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx b/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx new file mode 100644 index 000000000..33d1d447d --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx @@ -0,0 +1,48 @@ +/** @jsxImportSource @emotion/react */ + +import Text from '@components/Text/Text'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Flex from '../Flex/Flex'; + +import {LabelGroupInputProps} from './LabelGroupInput.type'; +import {errorTextStyle, labelTextStyle} from './LabelGroupInput.style'; +import Element from './Element'; +import {GroupInputProvider, useGroupInputContext} from './GroupInputContext'; + +const LabelGroupInput: React.FC<LabelGroupInputProps> = ({labelText, errorText, children}: LabelGroupInputProps) => { + const {theme} = useTheme(); + const {hasAnyFocus, values, errors} = useGroupInputContext(); + + const hasAnyValue = !Object.values(values).every(value => value === ''); + const hasAnyError = !Object.values(errors).every(error => !error); + + return ( + <Flex flexDirection="column" gap="0.375rem"> + <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> + <Text size="caption" css={labelTextStyle(theme, hasAnyFocus, hasAnyValue)}> + {labelText} + </Text> + {errorText && ( + <Text size="caption" css={errorTextStyle(theme, hasAnyError)}> + {errorText} + </Text> + )} + </Flex> + <Flex flexDirection="column" gap="0.5rem"> + {children} + </Flex> + </Flex> + ); +}; + +const LabelGroupInputContainer = (props: LabelGroupInputProps) => ( + <GroupInputProvider> + <LabelGroupInput {...props} /> + </GroupInputProvider> +); + +LabelGroupInputContainer.Element = Element; + +export default LabelGroupInputContainer; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts b/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts new file mode 100644 index 000000000..8507311b5 --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts @@ -0,0 +1,10 @@ +export interface LabelGroupInputStyleProps {} + +export interface LabelGroupInputCustomProps { + labelText: string; + errorText: string | null; +} + +export type LabelGroupInputOptionProps = LabelGroupInputStyleProps & LabelGroupInputCustomProps; + +export type LabelGroupInputProps = React.ComponentProps<'input'> & LabelGroupInputOptionProps; diff --git a/HDesign/src/components/LabelGroupInput/index.ts b/HDesign/src/components/LabelGroupInput/index.ts new file mode 100644 index 000000000..c31f35eaf --- /dev/null +++ b/HDesign/src/components/LabelGroupInput/index.ts @@ -0,0 +1,3 @@ +import LabelGroupInputContainer from './LabelGroupInput'; + +export {LabelGroupInputContainer as LabelGroupInput}; diff --git a/HDesign/src/components/LabelInput/LabelInput.stories.tsx b/HDesign/src/components/LabelInput/LabelInput.stories.tsx new file mode 100644 index 000000000..a272037a4 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.stories.tsx @@ -0,0 +1,56 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useEffect, useState} from 'react'; + +import LabelInput from '@components/LabelInput/LabelInput'; + +const meta = { + title: 'Components/LabelInput', + component: LabelInput, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + labelText: { + description: 'label에 들어갈 텍스트를 작성', + control: {type: 'text'}, + }, + isError: { + description: '', + control: {type: 'boolean'}, + }, + errorText: { + description: 'error에 들어갈 텍스트를 작성', + control: {type: 'text'}, + }, + }, + args: { + // value: '', + labelText: '이름', + errorText: 'error가 발생했을 때 나타납니다!', + autoFocus: true, + }, +} satisfies Meta<typeof LabelInput>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + const [value, setValue] = useState(''); + const [isError, setIsError] = useState(false); + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + if (event.target.value.length < 4) { + setValue(event.target.value); + setIsError(false); + } else { + event.target.value = value; + setIsError(true); + } + }; + return <LabelInput value={value} onChange={e => handleChange(e)} isError={isError} {...args} />; + }, +}; diff --git a/HDesign/src/components/LabelInput/LabelInput.style.ts b/HDesign/src/components/LabelInput/LabelInput.style.ts new file mode 100644 index 000000000..df64636e9 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.style.ts @@ -0,0 +1,25 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => + css({ + height: '1.125rem', + color: theme.colors.gray, + + opacity: hasFocus || hasValue ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); + +export const errorTextStyle = (theme: Theme, isError: boolean) => + css({ + height: '1.125rem', + color: theme.colors.onErrorContainer, + + opacity: isError ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); diff --git a/HDesign/src/components/LabelInput/LabelInput.tsx b/HDesign/src/components/LabelInput/LabelInput.tsx new file mode 100644 index 000000000..43f60c220 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.tsx @@ -0,0 +1,45 @@ +/** @jsxImportSource @emotion/react */ + +import {forwardRef, useImperativeHandle, useRef} from 'react'; + +import Text from '@components/Text/Text'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Input from '../Input/Input'; +import Flex from '../Flex/Flex'; + +import {errorTextStyle, labelTextStyle} from './LabelInput.style'; +import {useLabelInput} from './useLabelInput'; +import {LabelInputProps} from './LabelInput.type'; + +const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, LabelInputProps>(function LabelInput( + {labelText, errorText, isError, ...htmlProps}: LabelInputProps, + ref, +) { + useImperativeHandle(ref, () => inputRef.current!); + + const {theme} = useTheme(); + const inputRef = useRef<HTMLInputElement>(null); + const {hasFocus} = useLabelInput({inputRef}); + + return ( + <Flex flexDirection="column" gap="0.375rem"> + <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> + <Text size="caption" css={labelTextStyle(theme, hasFocus, !!htmlProps.value)}> + {labelText} + </Text> + {errorText && ( + <Text size="caption" css={errorTextStyle(theme, isError ?? false)}> + {errorText} + </Text> + )} + </Flex> + <Flex flexDirection="column" gap="0.5rem"> + <Input ref={inputRef} isError={isError} placeholder={labelText} {...htmlProps} /> + </Flex> + </Flex> + ); +}); + +export default LabelInput; diff --git a/HDesign/src/components/LabelInput/LabelInput.type.ts b/HDesign/src/components/LabelInput/LabelInput.type.ts new file mode 100644 index 000000000..83e7e9751 --- /dev/null +++ b/HDesign/src/components/LabelInput/LabelInput.type.ts @@ -0,0 +1,12 @@ +export interface LabelInputStyleProps {} + +export interface LabelInputCustomProps { + labelText: string; + errorText: string | null; + isError?: boolean; + autoFocus: boolean; +} + +export type LabelInputOptionProps = LabelInputCustomProps & LabelInputCustomProps; + +export type LabelInputProps = React.ComponentProps<'input'> & LabelInputOptionProps; diff --git a/HDesign/src/components/LabelInput/useLabelInput.ts b/HDesign/src/components/LabelInput/useLabelInput.ts new file mode 100644 index 000000000..e967c5f89 --- /dev/null +++ b/HDesign/src/components/LabelInput/useLabelInput.ts @@ -0,0 +1,26 @@ +import {RefObject, useEffect, useState} from 'react'; + +interface UseLabelInput<T> { + inputRef: RefObject<HTMLInputElement>; + autoFocus?: boolean; +} + +export const useLabelInput = <T>({inputRef, autoFocus}: UseLabelInput<T>) => { + const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); + + useEffect(() => { + setHasFocus(inputRef.current === document.activeElement); + }, []); + + useEffect(() => { + inputRef.current?.addEventListener('focus', () => setHasFocus(true)); + inputRef.current?.addEventListener('blur', () => setHasFocus(false)); + + return () => { + inputRef.current?.removeEventListener('focus', () => setHasFocus(true)); + inputRef.current?.removeEventListener('blur', () => setHasFocus(false)); + }; + }, []); + + return {hasFocus}; +}; diff --git a/HDesign/src/components/ListButton/ListButton.stories.tsx b/HDesign/src/components/ListButton/ListButton.stories.tsx new file mode 100644 index 000000000..27f7744d1 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.stories.tsx @@ -0,0 +1,32 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import ListButton from '@components/ListButton/ListButton'; + +const meta = { + title: 'Components/ListButton', + component: ListButton, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: { + prefix: { + description: '', + control: {type: 'text'}, + }, + suffix: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + prefix: '전체 참여자', + suffix: '7명', + }, +} satisfies Meta<typeof ListButton>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/ListButton/ListButton.style.ts b/HDesign/src/components/ListButton/ListButton.style.ts new file mode 100644 index 000000000..fcca0ca01 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.style.ts @@ -0,0 +1,16 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const listButtonStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + width: '100%', + padding: '0.375rem 1rem', + backgroundColor: theme.colors.white, + + boxShadow: `0 1px 0 0 ${theme.colors.grayContainer} inset `, + }); diff --git a/HDesign/src/components/ListButton/ListButton.tsx b/HDesign/src/components/ListButton/ListButton.tsx new file mode 100644 index 000000000..10c417310 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.tsx @@ -0,0 +1,36 @@ +/** @jsxImportSource @emotion/react */ +import React, {forwardRef} from 'react'; + +import Text from '@components/Text/Text'; +import IconButton from '@components/IconButton/IconButton'; +import Flex from '@components/Flex/Flex'; +import Icon from '@components/Icon/Icon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {ListButtonProps} from './ListButton.type'; +import {listButtonStyle} from './ListButton.style'; + +export const ListButton: React.FC<ListButtonProps> = forwardRef<HTMLButtonElement, ListButtonProps>(function Button( + {prefix, suffix, ...htmlProps}: ListButtonProps, + ref, +) { + const {theme} = useTheme(); + return ( + <button css={listButtonStyle(theme)} ref={ref} {...htmlProps}> + <Text size="caption" textColor="gray"> + {prefix} + </Text> + <Flex gap="0.5rem" alignItems="center"> + <Text size="caption" textColor="gray"> + {suffix} + </Text> + <IconButton variants="none"> + <Icon iconType="rightChevron" /> + </IconButton> + </Flex> + </button> + ); +}); + +export default ListButton; diff --git a/HDesign/src/components/ListButton/ListButton.type.ts b/HDesign/src/components/ListButton/ListButton.type.ts new file mode 100644 index 000000000..788117870 --- /dev/null +++ b/HDesign/src/components/ListButton/ListButton.type.ts @@ -0,0 +1,10 @@ +export interface ListButtonStyleProps {} + +export interface ListButtonCustomProps { + prefix?: string; + suffix?: string; +} + +export type ListButtonOptionProps = ListButtonStyleProps & ListButtonCustomProps; + +export type ListButtonProps = React.ComponentProps<'button'> & ListButtonOptionProps; diff --git a/HDesign/src/components/Search/Search.stories.tsx b/HDesign/src/components/Search/Search.stories.tsx new file mode 100644 index 000000000..6b5d821cd --- /dev/null +++ b/HDesign/src/components/Search/Search.stories.tsx @@ -0,0 +1,32 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import React from 'react'; + +import Search from '@components/Search/Search'; + +const meta = { + title: 'Components/Search', + component: Search, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + decorators: [ + Story => ( + <div style={{minHeight: '10rem'}}> + <Story /> + </div> + ), + ], + args: { + isShowTargetInput: true, + matchItems: ['todari', 'cookie'], + onMatchItemClick: keyword => alert(keyword), + }, +} satisfies Meta<typeof Search>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Search/Search.style.ts b/HDesign/src/components/Search/Search.style.ts new file mode 100644 index 000000000..d75e8fe25 --- /dev/null +++ b/HDesign/src/components/Search/Search.style.ts @@ -0,0 +1,42 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const searchStyle = css({ + position: 'relative', + + width: '100%', +}); + +export const searchTermsStyle = (theme: Theme) => + css({ + position: 'absolute', + top: '3.5rem', + zIndex: 1, + + width: '100%', + padding: '0.5rem 1rem', + + borderRadius: '1rem', + + backgroundColor: theme.colors.white, + + boxShadow: '0 0.25rem 0.5rem 0 rgba(0, 0, 0, 0.12)', + }); + +export const searchTermStyle = (theme: Theme) => + css( + { + width: '100%', + padding: '0.5rem', + + color: theme.colors.onTertiary, + + '&:hover': { + borderRadius: '0.5rem', + + backgroundColor: theme.colors.lightGrayContainer, + }, + }, + theme.typography.body, + ); diff --git a/HDesign/src/components/Search/Search.tsx b/HDesign/src/components/Search/Search.tsx new file mode 100644 index 000000000..58c292cc4 --- /dev/null +++ b/HDesign/src/components/Search/Search.tsx @@ -0,0 +1,37 @@ +/** @jsxImportSource @emotion/react */ +import Flex from '@components/Flex/Flex'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {searchStyle, searchTermsStyle, searchTermStyle} from './Search.style'; + +export interface SearchProps { + isShowTargetInput: boolean; + matchItems: string[]; + onMatchItemClick: (term: string) => void; +} + +const Search = ({isShowTargetInput, matchItems, onMatchItemClick, children}: React.PropsWithChildren<SearchProps>) => { + const {theme} = useTheme(); + + return ( + <fieldset css={searchStyle}> + {children} + {matchItems.length > 0 && isShowTargetInput && ( + <ul css={searchTermsStyle(theme)}> + <Flex flexDirection="column" gap="0.5rem"> + {matchItems.map((matchItem, index) => ( + <li key={`${matchItem}-${index}`}> + <button type="button" css={searchTermStyle(theme)} onClick={() => onMatchItemClick(matchItem)}> + {matchItem} + </button> + </li> + ))} + </Flex> + </ul> + )} + </fieldset> + ); +}; + +export default Search; diff --git a/HDesign/src/components/Switch/Switch.stories.tsx b/HDesign/src/components/Switch/Switch.stories.tsx new file mode 100644 index 000000000..a3558754a --- /dev/null +++ b/HDesign/src/components/Switch/Switch.stories.tsx @@ -0,0 +1,35 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Switch from '@components/Switch/Switch'; + +const meta = { + title: 'Components/Switch', + component: Switch, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + value: { + description: '', + control: {type: 'select', options: ['홈', '관리']}, + }, + values: { + description: '', + }, + onChange: { + description: '', + }, + }, + args: { + value: '홈', + values: ['홈', '관리'], + onChange: value => alert(`${value} 선택됨`), + }, +} satisfies Meta<typeof Switch>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Switch/Switch.style.ts b/HDesign/src/components/Switch/Switch.style.ts new file mode 100644 index 000000000..d88c18748 --- /dev/null +++ b/HDesign/src/components/Switch/Switch.style.ts @@ -0,0 +1,6 @@ +import {css} from '@emotion/react'; + +export const switchContainerStyle = css({ + display: 'flex', + gap: '0.75rem', +}); diff --git a/HDesign/src/components/Switch/Switch.tsx b/HDesign/src/components/Switch/Switch.tsx new file mode 100644 index 000000000..4a1275185 --- /dev/null +++ b/HDesign/src/components/Switch/Switch.tsx @@ -0,0 +1,24 @@ +/** @jsxImportSource @emotion/react */ +import TextButton from '../TextButton/TextButton'; + +import {switchContainerStyle} from './Switch.style'; +import {SwitchProps} from './Switch.type'; + +function Switch({value, values, onChange}: SwitchProps) { + return ( + <div css={switchContainerStyle}> + {values.map((item, index) => ( + <TextButton + key={`${index}_${item}`} + textColor={value === item ? 'black' : 'gray'} + textSize="bodyBold" + onClick={() => onChange(values[index])} + > + {item} + </TextButton> + ))} + </div> + ); +} + +export default Switch; diff --git a/HDesign/src/components/Switch/Switch.type.ts b/HDesign/src/components/Switch/Switch.type.ts new file mode 100644 index 000000000..7e0d31d0f --- /dev/null +++ b/HDesign/src/components/Switch/Switch.type.ts @@ -0,0 +1,5 @@ +export interface SwitchProps { + value: string; + values: string[]; + onChange: (value: string) => void; +} diff --git a/HDesign/src/components/Tabs/Tab.tsx b/HDesign/src/components/Tabs/Tab.tsx new file mode 100644 index 000000000..2a79c1b78 --- /dev/null +++ b/HDesign/src/components/Tabs/Tab.tsx @@ -0,0 +1,8 @@ +/** @jsxImportSource @emotion/react */ +import {TabProps} from './Tab.type'; + +const Tab: React.FC<TabProps> = () => { + return <></>; +}; + +export default Tab; diff --git a/HDesign/src/components/Tabs/Tab.type.ts b/HDesign/src/components/Tabs/Tab.type.ts new file mode 100644 index 000000000..6b9e4972e --- /dev/null +++ b/HDesign/src/components/Tabs/Tab.type.ts @@ -0,0 +1,16 @@ +import {FlexProps} from '../Flex/Flex.type'; + +export interface TabProps { + label: string; + content: React.ReactNode; +} + +export interface TabsCustomProps { + children: React.ReactElement<TabProps>[]; +} + +export interface TabsStyleProps { + tabsContainerStyle?: FlexProps; +} + +export type TabsProps = TabsCustomProps & TabsStyleProps; diff --git a/HDesign/src/components/Tabs/Tabs.stories.tsx b/HDesign/src/components/Tabs/Tabs.stories.tsx new file mode 100644 index 000000000..a40e60b07 --- /dev/null +++ b/HDesign/src/components/Tabs/Tabs.stories.tsx @@ -0,0 +1,31 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import React from 'react'; + +import Tabs from '@components/Tabs/Tabs'; + +import Tab from './Tab'; + +const meta = { + title: 'Components/Tabs', + component: Tabs, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + args: { + children: [ + <Tab label="전체 지출 내역" content={<div>없지롱</div>} />, + <Tab label="참여자 별 정산" content={<div>있지롱</div>} />, + ], + tabsContainerStyle: { + gap: '0.5rem', + }, + }, +} satisfies Meta<typeof Tabs>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Tabs/Tabs.style.ts b/HDesign/src/components/Tabs/Tabs.style.ts new file mode 100644 index 000000000..3ea38924c --- /dev/null +++ b/HDesign/src/components/Tabs/Tabs.style.ts @@ -0,0 +1,53 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const tabListStyle = (theme: Theme) => + css({ + position: 'relative', + + backgroundColor: theme.colors.white, + + cursor: 'pointer', + + WebkitTapHighlightColor: 'transparent', + + '&::after': { + position: 'absolute', + left: 0, + bottom: 0, + zIndex: 1, + + width: '100%', + height: '0.0625rem', + + backgroundColor: theme.colors.gray, + + content: '""', + }, + }); + +export const tabItemStyle = css({ + flex: 1, + + textAlign: 'center', +}); + +export const tabTextStyle = (theme: Theme, selected: boolean) => + css({ + color: selected ? theme.colors.onTertiary : theme.colors.gray, + }); + +export const indicatorStyle = (theme: Theme, leftPosition: string, tabLength: number) => + css({ + position: 'absolute', + left: leftPosition, + bottom: 0, + zIndex: 2, + + width: `calc(100% / ${tabLength})`, + height: '0.125rem', + + backgroundColor: theme.colors.onSecondary, + transition: 'left 0.3s', + }); diff --git a/HDesign/src/components/Tabs/Tabs.tsx b/HDesign/src/components/Tabs/Tabs.tsx new file mode 100644 index 000000000..0245b5ba7 --- /dev/null +++ b/HDesign/src/components/Tabs/Tabs.tsx @@ -0,0 +1,53 @@ +/** @jsxImportSource @emotion/react */ +import React, {useState} from 'react'; +import {css} from '@emotion/react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {tabListStyle, indicatorStyle, tabItemStyle, tabTextStyle} from './Tabs.style'; +import {TabsProps} from './Tab.type'; + +const Tabs: React.FC<TabsProps> = ({children, tabsContainerStyle}) => { + const {theme} = useTheme(); + const [activeTabIndex, setActiveTabIndex] = useState(0); + + const isActive = (index: number) => activeTabIndex === index; + const tabItemCount = children.length; + + return ( + <Flex flexDirection="column" {...tabsContainerStyle}> + <ul role="tablist" css={tabListStyle(theme)}> + <Flex justifyContent="spaceBetween" alignItems="center" padding="0.5rem"> + {children.map((tabItem, index) => ( + <li + key={tabItem.props.label} + role="tab" + id={`tab-${tabItem.props.label}`} + css={tabItemStyle} + aria-selected={isActive(index)} + onClick={() => setActiveTabIndex(index)} + aria-controls={`tabpanel-${tabItem.props.label}`} + > + <Text css={tabTextStyle(theme, isActive(index))} size={isActive(index) ? 'bodyBold' : 'body'}> + {tabItem.props.label} + </Text> + </li> + ))} + <div css={indicatorStyle(theme, `${(activeTabIndex * 100) / tabItemCount}%`, tabItemCount)} /> + </Flex> + </ul> + <section + role="tabpanel" + id={`tabpanel-${children[activeTabIndex].props.label}`} + aria-labelledby={`tab-${children[activeTabIndex].props.label}}`} + > + {children[activeTabIndex].props.content} + </section> + </Flex> + ); +}; + +export default Tabs; diff --git a/HDesign/src/components/Text/Text.stories.tsx b/HDesign/src/components/Text/Text.stories.tsx new file mode 100644 index 000000000..5e5ec2287 --- /dev/null +++ b/HDesign/src/components/Text/Text.stories.tsx @@ -0,0 +1,40 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Text from '@components/Text/Text'; + +const meta = { + title: 'Components/Text', + component: Text, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + size: { + description: '', + control: {type: 'select'}, + options: [ + 'head', + 'title', + 'subTitle', + 'bodyBold', + 'body', + 'smallBodyBold', + 'smallBody', + 'caption', + 'captionBold', + 'tiny', + ], + }, + }, + args: { + size: 'body', + children: 'text', + }, +} satisfies Meta<typeof Text>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Text/Text.style.ts b/HDesign/src/components/Text/Text.style.ts new file mode 100644 index 000000000..650260e62 --- /dev/null +++ b/HDesign/src/components/Text/Text.style.ts @@ -0,0 +1,29 @@ +import type {TextStylePropsWithTheme} from './Text.type'; + +import {css} from '@emotion/react'; + +// TODO: (@todari) themeProvider 이용하도록 변경 +import TYPOGRAPHY from '@token/typography'; + +export const getSizeStyling = ({size, textColor, theme}: Required<TextStylePropsWithTheme>) => { + const style = { + head: css(TYPOGRAPHY.head), + title: css(TYPOGRAPHY.title), + subTitle: css(TYPOGRAPHY.subTitle), + bodyBold: css(TYPOGRAPHY.bodyBold), + body: css(TYPOGRAPHY.body), + smallBodyBold: css(TYPOGRAPHY.smallBodyBold), + smallBody: css(TYPOGRAPHY.smallBody), + captionBold: css(TYPOGRAPHY.captionBold), + caption: css(TYPOGRAPHY.caption), + tiny: css(TYPOGRAPHY.tiny), + }; + + const colorStyle = css({color: theme.colors[textColor]}); + + const baseStyle = css({ + whiteSpace: 'pre-line', + }); + + return [style[size], colorStyle, baseStyle]; +}; diff --git a/HDesign/src/components/Text/Text.tsx b/HDesign/src/components/Text/Text.tsx new file mode 100644 index 000000000..9b7853aa8 --- /dev/null +++ b/HDesign/src/components/Text/Text.tsx @@ -0,0 +1,19 @@ +/** @jsxImportSource @emotion/react */ +import type {TextProps} from '@components/Text/Text.type'; + +import React from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import {getSizeStyling} from './Text.style'; + +const Text: React.FC<TextProps> = ({size = 'body', textColor = 'black', children, ...attributes}: TextProps) => { + const {theme} = useTheme(); + return ( + <p css={getSizeStyling({size, textColor, theme})} {...attributes}> + {children} + </p> + ); +}; + +export default Text; diff --git a/HDesign/src/components/Text/Text.type.ts b/HDesign/src/components/Text/Text.type.ts new file mode 100644 index 000000000..157591abf --- /dev/null +++ b/HDesign/src/components/Text/Text.type.ts @@ -0,0 +1,30 @@ +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +export type TextSize = + | 'head' + | 'title' + | 'subTitle' + | 'body' + | 'smallBody' + | 'caption' + | 'tiny' + | 'bodyBold' + | 'smallBodyBold' + | 'captionBold'; + +export interface TextStyleProps { + size?: TextSize; + textColor?: ColorKeys; +} + +export interface TextStylePropsWithTheme extends TextStyleProps { + theme: Theme; +} + +export interface TextCustomProps {} + +export type TextOptionProps = TextStyleProps & TextCustomProps; + +export type TextProps = React.ComponentProps<'p'> & TextOptionProps; diff --git a/HDesign/src/components/TextButton/TextButton.stories.tsx b/HDesign/src/components/TextButton/TextButton.stories.tsx new file mode 100644 index 000000000..9873df3f4 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.stories.tsx @@ -0,0 +1,50 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import TextButton from '@components/TextButton/TextButton'; + +const meta = { + title: 'Components/TextButton', + component: TextButton, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + textSize: { + description: '', + control: {type: 'select'}, + options: [ + 'head', + 'title', + 'subTitle', + 'bodyBold', + 'body', + 'smallBodyBold', + 'smallBody', + 'caption', + 'captionBold', + 'tiny', + ], + }, + textColor: { + description: '', + control: {type: 'select'}, + options: ['black', 'gray'], + }, + children: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + textColor: 'black', + textSize: 'bodyBold', + children: '뒤로가기', + }, +} satisfies Meta<typeof TextButton>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/TextButton/TextButton.style.ts b/HDesign/src/components/TextButton/TextButton.style.ts new file mode 100644 index 000000000..c8d8738fe --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.style.ts @@ -0,0 +1,10 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ColorKeys} from '@token/colors'; + +interface TextButtonStyleProps { + textColor: ColorKeys; + theme: Theme; +} diff --git a/HDesign/src/components/TextButton/TextButton.tsx b/HDesign/src/components/TextButton/TextButton.tsx new file mode 100644 index 000000000..9e73667d5 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.tsx @@ -0,0 +1,25 @@ +/** @jsxImportSource @emotion/react */ +import {forwardRef} from 'react'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {TextButtonProps} from './TextButton.type'; + +export const TextButton: React.FC<TextButtonProps> = forwardRef<HTMLButtonElement, TextButtonProps>(function Button( + {textColor, textSize, children, ...htmlProps}: TextButtonProps, + ref, +) { + const {theme} = useTheme(); + + return ( + <button ref={ref} {...htmlProps}> + <Text size={textSize} textColor={textColor}> + {children} + </Text> + </button> + ); +}); + +export default TextButton; diff --git a/HDesign/src/components/TextButton/TextButton.type.ts b/HDesign/src/components/TextButton/TextButton.type.ts new file mode 100644 index 000000000..0299d89b9 --- /dev/null +++ b/HDesign/src/components/TextButton/TextButton.type.ts @@ -0,0 +1,15 @@ +import {TextSize} from '../Text/Text.type'; + +export type TextColor = 'black' | 'gray'; + +export interface TextButtonStyleProps { + textColor: TextColor; +} + +export interface TextButtonCustomProps { + textSize: TextSize; +} + +export type TextButtonOptionProps = TextButtonStyleProps & TextButtonCustomProps; + +export type TextButtonProps = React.ComponentProps<'button'> & TextButtonOptionProps; diff --git a/HDesign/src/components/Title/Title.stories.tsx b/HDesign/src/components/Title/Title.stories.tsx new file mode 100644 index 000000000..2c91287b4 --- /dev/null +++ b/HDesign/src/components/Title/Title.stories.tsx @@ -0,0 +1,38 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import Title from '@components/Title/Title'; + +const meta = { + title: 'Components/Title', + component: Title, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + title: { + description: '', + control: {type: 'text'}, + }, + description: { + description: '', + control: {type: 'text'}, + }, + price: { + description: '', + control: {type: 'number'}, + }, + }, + args: { + title: '페이지 제목이에요', + description: `이곳에는 페이지 설명이 들어가요. + 페이지에 대한 설명을 자세하게 적어주면 좋아요 :)`, + price: 100000, + }, +} satisfies Meta<typeof Title>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/Title/Title.style.ts b/HDesign/src/components/Title/Title.style.ts new file mode 100644 index 000000000..ab347a214 --- /dev/null +++ b/HDesign/src/components/Title/Title.style.ts @@ -0,0 +1,19 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +export const titleContainerStyle = (theme: Theme) => + css({ + display: 'flex', + flexDirection: 'column', + width: '100%', + gap: '0.5rem', + backgroundColor: theme.colors.white, + padding: '1rem', + }); + +export const priceContainerStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'end', +}); diff --git a/HDesign/src/components/Title/Title.tsx b/HDesign/src/components/Title/Title.tsx new file mode 100644 index 000000000..e17de5e88 --- /dev/null +++ b/HDesign/src/components/Title/Title.tsx @@ -0,0 +1,34 @@ +/** @jsxImportSource @emotion/react */ +import Flex from '@components/Flex/Flex'; +import Text from '@components/Text/Text'; +import {priceContainerStyle, titleContainerStyle} from '@components/Title/Title.style'; +import {TitleProps} from '@components/Title/Title.type'; + +import {useTheme} from '@theme/HDesignProvider'; + +export const Title: React.FC<TitleProps> = ({title, description, price}: TitleProps) => { + const {theme} = useTheme(); + return ( + <div css={titleContainerStyle(theme)}> + <Text size="subTitle">{title}</Text> + {description && ( + <Text textColor="darkGray" size="body"> + {description} + </Text> + )} + {price !== undefined && ( + <div css={priceContainerStyle}> + <Text textColor="gray" size="caption"> + 전체 지출 금액 + </Text> + <Flex alignItems="center" gap="0.25rem"> + <Text>{price.toLocaleString('ko-kr')}</Text> + <Text size="caption">원</Text> + </Flex> + </div> + )} + </div> + ); +}; + +export default Title; diff --git a/HDesign/src/components/Title/Title.type.ts b/HDesign/src/components/Title/Title.type.ts new file mode 100644 index 000000000..4b12f23b2 --- /dev/null +++ b/HDesign/src/components/Title/Title.type.ts @@ -0,0 +1,11 @@ +export interface TitleStyleProps {} + +export interface TitleCustomProps { + title: string; + description?: string; + price?: number; +} + +export type TitleOptionProps = TitleStyleProps & TitleCustomProps; + +export type TitleProps = React.ComponentProps<'div'> & TitleOptionProps; diff --git a/HDesign/src/components/Toast/Toast.stories.tsx b/HDesign/src/components/Toast/Toast.stories.tsx new file mode 100644 index 000000000..fd672959c --- /dev/null +++ b/HDesign/src/components/Toast/Toast.stories.tsx @@ -0,0 +1,71 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Toast from '@components/Toast/Toast'; + +const meta = { + title: 'Components/Toast', + component: Toast, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + args: { + type: 'confirm', + position: 'top', + top: '80px', + message: `서버 오류로 인해 인원을 설정하는데 실패했어요. +두글자면 이렇게 보여요.`, + onUndo: () => alert('되돌리기 버튼이 눌렸습니다. 실행할 로직을 전달해주세요'), + }, +} satisfies Meta<typeof Toast>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const ConfirmToast: Story = { + args: { + ...meta.args, + type: 'confirm', + top: '80px', + message: `이 첫번째 토스트 그림자 짙은거 두 개 떠서 그런거임 css 잘못한거 아닙니다. 잘못 없습니다. 스토리북이 잘못한거에요. 저희는 최선을 다했어요.. `, + }, +}; + +export const ConfirmToastWithoutUndo: Story = { + args: { + ...meta.args, + onUndo: undefined, + top: '160px', + }, +}; + +export const ErrorToast: Story = { + args: { + ...meta.args, + top: '240px', + type: 'error', + message: `님 이거 다 작성했는데, 혹시 되돌림? + 되돌릴 수도 있음 ㅇㅇ 굿`, + }, +}; + +export const ErrorToastWithoutUndo: Story = { + args: { + ...meta.args, + top: '320px', + onUndo: undefined, + type: 'error', + }, +}; + +export const NoneToast: Story = { + args: { + ...meta.args, + top: '400px', + onUndo: undefined, + type: 'none', + message: '웨디는 커비의 먹잇감인가요? 그치만 감자는 웨디한테 먹힘 쿠스쿠스 ㅋ', + }, +}; diff --git a/HDesign/src/components/Toast/Toast.style.ts b/HDesign/src/components/Toast/Toast.style.ts new file mode 100644 index 000000000..0496bc722 --- /dev/null +++ b/HDesign/src/components/Toast/Toast.style.ts @@ -0,0 +1,44 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; + +import {ToastPosition} from './Toast.type'; + +type ToastMarginStyle = { + position?: ToastPosition; + bottom?: string; + top?: string; +}; + +export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => + css({ + position: 'absolute', + bottom: position === 'bottom' ? `${bottom}` : 'auto', + top: position === 'top' ? `${top}` : 'auto', + left: '50%', + transform: 'translate(-50%)', + + width: '100%', + maxWidth: '48rem', + paddingInline: '0.5rem', + }); + +export const toastStyle = (theme: Theme) => + css({ + width: '100%', + padding: '0.625rem 1rem', + + backgroundColor: theme.colors.gray, + boxShadow: '0 8px 12px rgba(0, 0, 0, 0.16);', + + borderRadius: '1.25rem', + }); + +export const textStyle = (theme: Theme) => + css({ + width: '100%', + + color: theme.colors.white, + + whiteSpace: 'pre-line', + }); diff --git a/HDesign/src/components/Toast/Toast.tsx b/HDesign/src/components/Toast/Toast.tsx new file mode 100644 index 000000000..972ce6220 --- /dev/null +++ b/HDesign/src/components/Toast/Toast.tsx @@ -0,0 +1,73 @@ +/** @jsxImportSource @emotion/react */ +import {createPortal} from 'react-dom'; + +import Text from '@components/Text/Text'; +import Flex from '@components/Flex/Flex'; +import Icon from '@components/Icon/Icon'; + +import {useTheme} from '@theme/HDesignProvider'; + +import Button from '../Button/Button'; + +import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; +import {ToastProps, ToastType} from './Toast.type'; + +const renderIcon = (type: ToastType) => { + switch (type) { + case 'error': + return <Icon iconType="error" />; + + case 'confirm': + return <Icon iconType="confirm" />; + + case 'none': + return null; + + default: + return null; + } +}; + +const Toast = ({ + type = 'confirm', + top = '0px', + bottom = '0px', + isClickToClose = true, + position = 'bottom', + message, + onUndo, + onClose, + ...htmlProps +}: ToastProps) => { + const {theme} = useTheme(); + const styleProps = {position, top, bottom}; + + const handleClickToClose = () => { + if (!isClickToClose || !onClose) return; + + onClose(); + }; + + return createPortal( + <div css={toastMarginStyle({...styleProps})} {...htmlProps} onClick={handleClickToClose}> + <div css={toastStyle(theme)}> + <Flex justifyContent="spaceBetween" alignItems="center"> + <Flex alignItems="center" gap="0.5rem"> + {renderIcon(type)} + <Text size="smallBodyBold" css={textStyle(theme)}> + {message} + </Text> + </Flex> + {onUndo && ( + <Button variants="tertiary" size="small" onClick={onUndo}> + 되돌리기 + </Button> + )} + </Flex> + </div> + </div>, + document.body, + ); +}; + +export default Toast; diff --git a/HDesign/src/components/Toast/Toast.type.ts b/HDesign/src/components/Toast/Toast.type.ts new file mode 100644 index 000000000..12a436c2d --- /dev/null +++ b/HDesign/src/components/Toast/Toast.type.ts @@ -0,0 +1,21 @@ +export type ToastPosition = 'bottom' | 'top'; +export type ToastType = 'error' | 'confirm' | 'none'; + +export interface ToastStyleProps { + bottom?: string; + top?: string; +} + +export interface ToastOptionProps { + position?: ToastPosition; + type?: ToastType; + onUndo?: () => void; + isClickToClose?: boolean; + onClose?: () => void; +} + +export interface ToastRequiredProps { + message: string; +} + +export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; diff --git a/HDesign/src/components/Toast/ToastProvider.stories.tsx b/HDesign/src/components/Toast/ToastProvider.stories.tsx new file mode 100644 index 000000000..32c8c6917 --- /dev/null +++ b/HDesign/src/components/Toast/ToastProvider.stories.tsx @@ -0,0 +1,46 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Button from '../Button/Button'; + +import {ToastProvider, useToast} from './ToastProvider'; + +const meta = { + title: 'Components/ToastProvider', + component: ToastProvider, + tags: ['autodocs'], + decorators: [ + Story => ( + <ToastProvider> + <Story /> + </ToastProvider> + ), + ], +} satisfies Meta<typeof ToastProvider>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + decorators: [ + () => { + const {showToast} = useToast(); + + return ( + <Button + onClick={() => + showToast({ + isAlwaysOn: true, + message: '이거자냥 (feat. 쿠키)', + type: 'confirm', + position: 'top', + }) + } + > + 토스트 열기 + </Button> + ); + }, + ], +}; diff --git a/HDesign/src/components/Toast/ToastProvider.tsx b/HDesign/src/components/Toast/ToastProvider.tsx new file mode 100644 index 000000000..9201fdc6d --- /dev/null +++ b/HDesign/src/components/Toast/ToastProvider.tsx @@ -0,0 +1,59 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, useCallback, useContext, useEffect, useState} from 'react'; + +import {ToastProps} from './Toast.type'; +import Toast from './Toast'; + +export const ToastContext = createContext<ToastContextProps | null>(null); + +interface ToastContextProps { + showToast: (args: ShowToast) => void; +} + +type ShowToast = ToastProps & { + showingTime?: number; + isAlwaysOn?: boolean; +}; + +const ToastProvider = ({children}: React.PropsWithChildren) => { + const [currentToast, setCurrentToast] = useState<ShowToast | null>(null); + + const showToast = useCallback(({showingTime = 3000, isAlwaysOn = false, ...toastProps}: ShowToast) => { + setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); + }, []); + + const closeToast = () => { + setCurrentToast(null); + }; + + useEffect(() => { + if (!currentToast) return; + + if (!currentToast.isAlwaysOn) { + const timer = setTimeout(() => { + setCurrentToast(null); + }, currentToast.showingTime); + + return () => clearTimeout(timer); + } + }, [currentToast]); + + return ( + <ToastContext.Provider value={{showToast}}> + {currentToast && <Toast onClose={closeToast} {...currentToast} />} + {children} + </ToastContext.Provider> + ); +}; + +const useToast = () => { + const context = useContext(ToastContext); + + if (!context) { + throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); + } + + return context; +}; + +export {ToastProvider, useToast}; diff --git a/HDesign/src/components/TopNav/Back.tsx b/HDesign/src/components/TopNav/Back.tsx new file mode 100644 index 000000000..cfb55e24d --- /dev/null +++ b/HDesign/src/components/TopNav/Back.tsx @@ -0,0 +1,17 @@ +/** @jsxImportSource @emotion/react */ +import React from 'react'; +import {useNavigate} from 'react-router-dom'; + +import TextButton from '@components/TextButton/TextButton'; + +function Back() { + const navigate = useNavigate(); + + return ( + <TextButton onClick={() => navigate(-1)} textSize="bodyBold" textColor="gray"> + 뒤로가기 + </TextButton> + ); +} + +export default Back; diff --git a/HDesign/src/components/TopNav/TopNav.stories.tsx b/HDesign/src/components/TopNav/TopNav.stories.tsx new file mode 100644 index 000000000..0c96161a5 --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.stories.tsx @@ -0,0 +1,50 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import React from 'react'; +import {reactRouterParameters, withRouter} from 'storybook-addon-react-router-v6'; + +import TopNav from '@components/TopNav/TopNav'; + +import Switch from '../Switch/Switch'; + +import Back from './Back'; + +const meta = { + title: 'Components/TopNav', + component: TopNav, + tags: ['autodocs'], + decorators: [withRouter], + parameters: { + reactRouter: reactRouterParameters({ + location: { + pathParams: { + eventId: '123123', + }, + }, + routing: {path: '/event/:eventId/home'}, + }), + // layout: 'centered', + }, + argTypes: { + children: { + description: '', + control: {type: 'select'}, + options: ['Back', 'Switch', 'Any'], + mapping: { + Back: <Back />, + Switch: <Switch values={['홈', '관리']} value="홈" onChange={value => console.log(value)} />, + Any: <div />, + }, + }, + }, + args: { + children: 'Back', + }, +} satisfies Meta<typeof TopNav>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/HDesign/src/components/TopNav/TopNav.style.ts new file mode 100644 index 000000000..9ca69c7b0 --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.style.ts @@ -0,0 +1,18 @@ +import {css} from '@emotion/react'; + +export const topNavStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '0 1rem', + width: '100%', +}); + +export const topNavNonStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '0 1rem', + width: '100%', + height: '1.5rem', +}); diff --git a/HDesign/src/components/TopNav/TopNav.tsx b/HDesign/src/components/TopNav/TopNav.tsx new file mode 100644 index 000000000..643cd5e3b --- /dev/null +++ b/HDesign/src/components/TopNav/TopNav.tsx @@ -0,0 +1,20 @@ +/** @jsxImportSource @emotion/react */ +import React from 'react'; + +import Switch from '@components/Switch/Switch'; + +import {topNavNonStyle, topNavStyle} from './TopNav.style'; +import Back from './Back'; + +const TopNav: React.FC<React.PropsWithChildren> = ({children}) => { + const hasBack = React.Children.toArray(children).some(child => React.isValidElement(child) && child.type === Back); + const hasSwitch = React.Children.toArray(children).some( + child => React.isValidElement(child) && child.type === Switch, + ); + + const isExistNav = hasBack || hasSwitch; + + return <div css={isExistNav ? topNavStyle : topNavNonStyle}>{children}</div>; +}; + +export default TopNav; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx new file mode 100644 index 000000000..656690951 --- /dev/null +++ b/HDesign/src/index.tsx @@ -0,0 +1,62 @@ +import BottomSheet from '@components/BottomSheet/BottomSheet'; +import Button from '@components/Button/Button'; +import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; +import EditableItem from '@components/EditableItem/EditableItem'; +import ExpenseList from '@components/ExpenseList/ExpenseList'; +import FixedButton from '@components/FixedButton/FixedButton'; +import Flex from '@components/Flex/Flex'; +import Icon from '@components/Icon/Icon'; +import IconButton from '@components/IconButton/IconButton'; +import Input from '@components/Input/Input'; +import LabelInput from '@components/LabelInput/LabelInput'; +import ListButton from '@components/ListButton/ListButton'; +import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; +import Search from '@components/Search/Search'; +import Switch from '@components/Switch/Switch'; +import Tab from '@components/Tabs/Tab'; +import Tabs from '@components/Tabs/Tabs'; +import Text from '@components/Text/Text'; +import TextButton from '@components/TextButton/TextButton'; +import Title from '@components/Title/Title'; +import Toast from '@components/Toast/Toast'; +import Back from '@components/TopNav/Back'; +import TopNav from '@components/TopNav/TopNav'; +import {ToastProvider, useToast} from '@components/Toast/ToastProvider'; + +import {MainLayout} from '@layouts/MainLayout'; +import {ContentLayout} from '@layouts/ContentLayout'; + +import {HDesignProvider} from '@theme/HDesignProvider'; + +export { + BottomSheet, + Button, + DragHandleItem, + DragHandleItemContainer, + EditableItem, + ExpenseList, + FixedButton, + Flex, + Icon, + IconButton, + Input, + LabelInput, + ListButton, + LabelGroupInput, + Search, + Switch, + Tab, + Tabs, + Text, + TextButton, + Title, + Toast, + TopNav, + Back, + MainLayout, + ContentLayout, + ToastProvider, + useToast, + HDesignProvider, +}; diff --git a/HDesign/src/layouts/ContentLayout.tsx b/HDesign/src/layouts/ContentLayout.tsx new file mode 100644 index 000000000..757a580ec --- /dev/null +++ b/HDesign/src/layouts/ContentLayout.tsx @@ -0,0 +1,25 @@ +import {PropsWithChildren} from 'react'; + +import {Flex} from '..'; + +type ContentLayoutBackground = 'white' | 'gray'; + +interface ContentLayoutProps extends PropsWithChildren { + backgroundColor?: ContentLayoutBackground; +} + +export function ContentLayout({backgroundColor, children}: ContentLayoutProps) { + return ( + <Flex + backgroundColor={backgroundColor} + justifyContent="flexStart" + flexDirection="column" + padding="0 1rem" + gap="1rem" + width="100%" + height="100%" + > + {children} + </Flex> + ); +} diff --git a/HDesign/src/layouts/MainLayout.tsx b/HDesign/src/layouts/MainLayout.tsx new file mode 100644 index 000000000..22012fde8 --- /dev/null +++ b/HDesign/src/layouts/MainLayout.tsx @@ -0,0 +1,26 @@ +import {PropsWithChildren} from 'react'; + +import {Flex} from '..'; + +type MainLayoutBackground = 'white' | 'gray' | 'lightGray'; + +interface MainLayoutProps extends PropsWithChildren { + backgroundColor?: MainLayoutBackground; +} + +export function MainLayout({backgroundColor, children}: MainLayoutProps) { + return ( + <Flex + backgroundColor={backgroundColor} + justifyContent="flexStart" + flexDirection="column" + padding="1rem 0 0 0" + gap="1rem" + width="100%" + height="100%" + minHeight="100vh" + > + {children} + </Flex> + ); +} diff --git a/HDesign/src/theme/GlobalStyle.ts b/HDesign/src/theme/GlobalStyle.ts new file mode 100644 index 000000000..f1b7b699b --- /dev/null +++ b/HDesign/src/theme/GlobalStyle.ts @@ -0,0 +1,123 @@ +import {css} from '@emotion/react'; + +export const GlobalStyle = css` + *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { + all: unset; + display: revert; + } + + /* Preferred box-sizing value */ + *, + *::before, + *::after { + box-sizing: border-box; + } + + /* Fix mobile Safari increase font-size on landscape mode */ + html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; + } + + /* Reapply the pointer cursor for anchor tags */ + a, + button { + cursor: revert; + line-height: 0; + } + + button:disabled { + cursor: default; + } + + /* Remove list styles (bullets/numbers) */ + ol, + ul, + menu, + summary { + list-style: none; + } + + /* Removes spacing between cells in tables */ + table { + border-collapse: collapse; + } + + /* Safari - solving issue when using user-select:none on the <body> text input doesn't working */ + input, + textarea { + -webkit-user-select: auto; + } + + /* Revert the 'white-space' property for textarea elements on Safari */ + textarea { + white-space: revert; + } + + /* Minimum style to allow to style meter element */ + meter { + -webkit-appearance: revert; + appearance: revert; + } + + /* Preformatted text - use only for this feature */ + :where(pre) { + all: revert; + box-sizing: border-box; + } + + /* Fix the feature of 'hidden' attribute. + display: revert; revert to element instead of attribute */ + :where([hidden]) { + display: none; + } + + /* Revert for bug in Chromium browsers + - Fix for the content editable attribute will work properly. + - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element */ + :where([contenteditable]:not([contenteditable='false'])) { + -moz-user-modify: read-write; + -webkit-user-modify: read-write; + overflow-wrap: break-word; + -webkit-line-break: after-white-space; + -webkit-user-select: auto; + } + + /* Apply back the draggable feature - exist only in Chromium and Safari */ + :where([draggable='true']) { + -webkit-user-drag: element; + } + + /* Revert Modal native behavior */ + :where(dialog:modal) { + all: revert; + box-sizing: border-box; + } + + /* Remove details summary webkit styles */ + ::-webkit-details-marker { + display: none; + } + + /* Chrome, Safari, Edge, Opera */ + input::-webkit-outer-spin-button, + input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; + } + + /* Firefox */ + input[type='number'] { + -moz-appearance: textfield; + } + + #root { + display: flex; + justify-content: center; + } + + button { + cursor: pointer; + } +`; diff --git a/HDesign/src/theme/HDesignProvider.tsx b/HDesign/src/theme/HDesignProvider.tsx new file mode 100644 index 000000000..6c7c571a3 --- /dev/null +++ b/HDesign/src/theme/HDesignProvider.tsx @@ -0,0 +1,37 @@ +import React, {createContext, useContext, useState, ReactNode} from 'react'; +import {Global} from '@emotion/react'; + +import {Theme} from '@theme/theme.type'; +import {GlobalStyle} from '@theme/GlobalStyle'; + +import {COLORS} from '@token/colors'; +import {TYPOGRAPHY} from '@token/typography'; + +interface ThemeContextProps { + theme: Theme; +} + +const defaultTheme: Theme = { + colors: COLORS, + typography: TYPOGRAPHY, +}; + +const ThemeContext = createContext<ThemeContextProps | undefined>(undefined); + +export const HDesignProvider: React.FC<{children: ReactNode}> = ({children}) => { + const [theme, _] = useState<Theme>(defaultTheme); + return ( + <ThemeContext.Provider value={{theme}}> + <Global styles={GlobalStyle} /> + {children} + </ThemeContext.Provider> + ); +}; + +export const useTheme = (): ThemeContextProps => { + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within a HDesignProvider'); + } + return context; +}; diff --git a/HDesign/src/theme/theme.type.ts b/HDesign/src/theme/theme.type.ts new file mode 100644 index 000000000..dffd961f0 --- /dev/null +++ b/HDesign/src/theme/theme.type.ts @@ -0,0 +1,7 @@ +import {ColorTokens} from '@token/colors'; +import {TypographyTokens} from '@token/typography'; + +export interface Theme { + colors: ColorTokens; + typography: TypographyTokens; +} diff --git a/HDesign/src/token/colors.ts b/HDesign/src/token/colors.ts new file mode 100644 index 000000000..3dccdf2d3 --- /dev/null +++ b/HDesign/src/token/colors.ts @@ -0,0 +1,109 @@ +const PRIMITIVE_COLORS = { + white: '#FFFFFF', + purple: { + 50: '#f4e8ff', + 100: '#e0c7fe', + 200: '#cba0fe', + 300: '#b575ff', + 400: '#a350fd', + 500: '#8f2bf3', + 600: '#8425ec', + 700: '#7519e3', + 800: '#6712db', + 900: '#5100cd', + }, + pink: { + 50: '#ffe1ff', + 100: '#feafd9', + 200: '#ff75bf', + 300: '#fc28a1', + 400: '#f60087', + 500: '#f2006d', + 600: '#e1006a', + 700: '#ca0065', + 800: '#b30062', + 900: '#8b005b', + }, + yellow: { + 50: '#fdffe9', + 100: '#f7fdc5', + 200: '#f0fb9d', + 300: '#e8f972', + 400: '#ecff59', + 500: '#e5fb31', + 600: '#daeb2e', + 700: '#c9d323', + 800: '#b9bb17', + 900: '#9e9305', + }, + green: { + 50: '#f4ffe8', + 100: '#e4ffc6', + 200: '#d1ff9f', + 300: '#bfff75', + 400: '#b0fd51', + 500: '#a4f932', + 600: '#9de728', + 700: '#90cf18', + 800: '#85b704', + 900: '#748f00', + }, + gray: { + 50: '#F9F8FD', + 100: '#F1F0F5', + 200: '#E7E6EB', + 300: '#D6D5DA', + 400: '#B2B1B6', + 500: '#929195', + 600: '#6A696D', + 700: '#56555A', + 800: '#38373B', + 900: '#18171B', + }, +}; + +type Color = string; + +export type ColorKeys = + | 'white' + | 'black' + | 'primary' + | 'onPrimary' + | 'secondary' + | 'onSecondary' + | 'tertiary' + | 'onTertiary' + | 'gray' + | 'darkGray' + | 'grayContainer' + | 'lightGrayContainer' + | 'error' + | 'errorContainer' + | 'onErrorContainer' + | 'warn' + | 'complete'; +export type ColorTokens = Record<ColorKeys, Color>; + +// TODO: (@soha) 대괄호 사용에 대해 논의 +export const COLORS: ColorTokens = { + white: PRIMITIVE_COLORS.white, + black: PRIMITIVE_COLORS.gray[700], + + primary: PRIMITIVE_COLORS.purple[300], + onPrimary: PRIMITIVE_COLORS.white, + secondary: PRIMITIVE_COLORS.purple[50], + onSecondary: PRIMITIVE_COLORS.purple[600], + tertiary: PRIMITIVE_COLORS.gray[200], + onTertiary: PRIMITIVE_COLORS.gray[700], + + gray: PRIMITIVE_COLORS.gray[400], + darkGray: PRIMITIVE_COLORS.gray[500], + grayContainer: PRIMITIVE_COLORS.gray[100], + lightGrayContainer: PRIMITIVE_COLORS.gray[50], + + error: PRIMITIVE_COLORS.pink[200], + errorContainer: PRIMITIVE_COLORS.pink[50], + onErrorContainer: PRIMITIVE_COLORS.pink[300], + warn: PRIMITIVE_COLORS.yellow[400], + complete: PRIMITIVE_COLORS.green[300], +}; diff --git a/HDesign/src/token/typography.ts b/HDesign/src/token/typography.ts new file mode 100644 index 000000000..c88d61ea9 --- /dev/null +++ b/HDesign/src/token/typography.ts @@ -0,0 +1,67 @@ +type Typography = Record<string, string>; +export type TypographyTokens = Record<string, Typography>; + +export const TYPOGRAPHY: TypographyTokens = { + head: { + fontFamily: 'Pretendard', + fontSize: '3rem', + lineHeight: '1.5', + fontWeight: '700', + }, + title: { + fontFamily: 'Pretendard', + fontSize: '2rem', + lineHeight: '1.5', + fontWeight: '700', + }, + subTitle: { + fontFamily: 'Pretendard', + fontSize: '1.5rem', + lineHeight: '1.5', + fontWeight: '700', + }, + bodyBold: { + fontFamily: 'Pretendard', + fontSize: '1rem', + lineHeight: '1.5', + fontWeight: '700', + }, + body: { + fontFamily: 'Pretendard', + fontSize: '1rem', + lineHeight: '1.5', + fontWeight: '400', + }, + smallBodyBold: { + fontFamily: 'Pretendard', + fontSize: '0.875rem', + lineHeight: '1.5', + fontWeight: '700', + }, + smallBody: { + fontFamily: 'Pretendard', + fontSize: '0.875rem', + lineHeight: '1.5', + fontWeight: '400', + }, + captionBold: { + fontFamily: 'Pretendard', + fontSize: '0.75rem', + lineHeight: '1.5', + fontWeight: '700', + }, + caption: { + fontFamily: 'Pretendard', + fontSize: '0.75rem', + lineHeight: '1.5', + fontWeight: '400', + }, + tiny: { + fontFamily: 'Pretendard', + fontSize: '0.625rem', + lineHeight: '1.5', + fontWeight: '400', + }, +}; + +export default TYPOGRAPHY; diff --git a/HDesign/src/type/strictPropsWithChildren.ts b/HDesign/src/type/strictPropsWithChildren.ts new file mode 100644 index 000000000..684fbcc76 --- /dev/null +++ b/HDesign/src/type/strictPropsWithChildren.ts @@ -0,0 +1,3 @@ +export type StrictPropsWithChildren<P = unknown> = P & { + children: React.ReactNode; +}; diff --git a/HDesign/src/type/withTheme.ts b/HDesign/src/type/withTheme.ts new file mode 100644 index 000000000..bae8dc318 --- /dev/null +++ b/HDesign/src/type/withTheme.ts @@ -0,0 +1,5 @@ +import {Theme} from '@theme/theme.type'; + +export type WithTheme<P = unknown> = P & { + theme: Theme; +}; diff --git a/HDesign/src/utils/changeCamelCaseToKebabCase.ts b/HDesign/src/utils/changeCamelCaseToKebabCase.ts new file mode 100644 index 000000000..2bca7c1b7 --- /dev/null +++ b/HDesign/src/utils/changeCamelCaseToKebabCase.ts @@ -0,0 +1,3 @@ +export const changeCamelCaseToKebabCase = (str: string) => { + return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); +}; diff --git a/HDesign/src/utils/colors.ts b/HDesign/src/utils/colors.ts new file mode 100644 index 000000000..116c670b0 --- /dev/null +++ b/HDesign/src/utils/colors.ts @@ -0,0 +1,88 @@ +export const hexToRgb = (hex: string) => { + hex = hex.slice(1); + if (hex.length === 3) { + hex = hex + .split('') + .reduce<string[]>((acc, a) => { + acc.push(a + a); + return acc; + }, []) + .join(''); + } + + if (hex.length !== 6) { + throw new Error(`잘못된 색상값이 입력됐습니다. : ${hex} 3자리(#fff), 6자리(#fe0000)hex 값만 입력 가능합니다.`); + } + + const regex = new RegExp(`.{1,2}`, 'g'); + const hexArray = hex.match(regex) as string[]; + + return `rgb(${hexArray.map(n => parseInt(n, 16)).join(', ')})`; +}; + +export const rgbToColors = (rgb: string) => { + if (rgb.slice(0, 3) !== 'rgb') { + throw new Error('잘못된 색상값이 입력됐습니다. rgb() 값만 입력 가능합니다.'); + } + + return rgb + .slice(4, -1) + .split(',') + .map(a => Number(a.trim())); +}; + +export const hexToColors = (hex: string) => { + return rgbToColors(hexToRgb(hex)); +}; + +function intToHex(int: number) { + const hex = int.toString(16); + return hex.length === 1 ? `0${hex}` : hex; +} + +export const colorsToRgb = (colors: number[]) => { + return `rgb(${colors.join(', ')})`; +}; + +export const rgbToHex = (rgb: string) => { + const colors = rgbToColors(rgb); + return `#${colors.map((n, i) => intToHex(i === 3 ? Math.round(255 * n) : n)).join('')}`; +}; + +export const colorsToHex = (colors: number[]) => { + return rgbToHex(colorsToRgb(colors)); +}; + +export const setDarker = (hex: string, coefficient: number) => { + const colors = hexToColors(hex); + const adjustCoefficient = coefficient > 1 ? 1 : coefficient < 0 ? 0 : coefficient; + const darkerColors = colors.map(color => Math.round(color * (1 - adjustCoefficient))); + + return colorsToHex(darkerColors); +}; + +export const setLighter = (hex: string, coefficient: number) => { + const colors = hexToColors(hex); + const adjustCoefficient = coefficient > 1 ? 1 : coefficient < 0 ? 0 : coefficient; + const lighterColors = colors.map(color => Math.round(color + (255 - color) * adjustCoefficient)); + + return colorsToHex(lighterColors); +}; + +export const getLuminance = (hex: string) => { + const colors = hexToColors(hex); + const values = colors.map(color => { + const value = color / 255; + return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4; + }); + + return Number((0.2126 * values[0] + 0.7152 * values[1] + 0.0722 * values[2]).toFixed(3)); +}; + +export const setEmphasize = (hex: string, threshold: number, coefficient = 0.15) => { + return getLuminance(hex) > threshold ? setDarker(hex, coefficient) : setLighter(hex, coefficient); +}; + +export const setOnTextColor = (hex: string, threshold: number, blackHex: string, whiteHex: string) => { + return getLuminance(hex) > threshold ? blackHex : whiteHex; +}; diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json new file mode 100644 index 000000000..ca7b8b78f --- /dev/null +++ b/HDesign/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "sourceMap": true, + "outDir": "./dist", + "target": "ES5", + "skipLibCheck": true, + "module": "commonjs", + "moduleResolution": "node", + "strict": true, + "declaration": true, + "declarationDir": "./dist", + "resolveJsonModule": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "jsx": "react-jsx", + "allowJs": true, + "baseUrl": ".", + "paths": { + "@*": ["src/*"], + "@components/*": ["src/components/*"], + "@layouts/*": ["src/layouts/*"], + "@token/*": ["src/token/*"], + "@type/*": ["src/type/*"], + "@theme/*": ["src/theme/*"], + "@assets/*": ["src/assets/*"], + "@utils/*": ["src/utils/*"] + }, + "jsxImportSource": "@emotion/react", + "allowSyntheticDefaultImports": true + }, + "include": ["src"], + "exclude": ["./node_modules", "dist"] +} diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 000000000..cf03bec6b --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,14 @@ +logs +*.log +npm-debug.log* + +node_modules +dist + +.env.* + +*storybook.log +.DS_Store + +# Sentry Config File +.env.sentry-build-plugin diff --git a/client/.npmrc b/client/.npmrc new file mode 100644 index 000000000..ece05f588 --- /dev/null +++ b/client/.npmrc @@ -0,0 +1,2 @@ +engine-strict = true +legacy-peer-deps = true diff --git a/client/.prettierrc b/client/.prettierrc new file mode 100644 index 000000000..94ad823ef --- /dev/null +++ b/client/.prettierrc @@ -0,0 +1,12 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "arrowParens": "avoid", + "endOfLine": "auto", + "jsxSingleQuote": false, + "bracketSpacing": false, + "proseWrap": "preserve" +} \ No newline at end of file diff --git a/client/cypress.config.ts b/client/cypress.config.ts new file mode 100644 index 000000000..2261e7871 --- /dev/null +++ b/client/cypress.config.ts @@ -0,0 +1,12 @@ +import {defineConfig} from 'cypress'; + +export default defineConfig({ + e2e: { + baseUrl: 'http://localhost:3000', + viewportWidth: 430, + viewportHeight: 930, + // setupNodeEvents(on, config) { + // // implement node event listeners here + // }, + }, +}); diff --git a/client/cypress/constants/constants.ts b/client/cypress/constants/constants.ts new file mode 100644 index 000000000..393ef5361 --- /dev/null +++ b/client/cypress/constants/constants.ts @@ -0,0 +1,6 @@ +const CONSTANTS = { + eventName: '테스트 이벤트', + eventPassword: '1234', +}; + +export default CONSTANTS; diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts new file mode 100644 index 000000000..5b4a93884 --- /dev/null +++ b/client/cypress/e2e/createEvent.cy.ts @@ -0,0 +1,79 @@ +import CONSTANTS from '../constants/constants'; +beforeEach(() => { + cy.blockSentry(); +}); + +describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 flow', () => { + it('랜딩페이지에서 "행사 생성하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { + cy.visit('/'); + cy.get('header').find('button').click(); + cy.url().should('include', '/event/create/name'); + }); + + context('행사 이름 입력 페이지', () => { + beforeEach(() => { + cy.visit('/event/create/name'); + }); + + it('행사 이름 입력 페이지에서 input이 포커싱 되어 있고, "다음" 버튼이 비활성화 되어 있어야 한다.', () => { + cy.get('input').focused(); + cy.get('button').contains('다음').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/name'); + }); + + it('행사 이름이 1자 이상 입력된 경우 "다음" 버튼이 활성화 되고, 값이 없는 경우 "다음" 버튼이 비활성화 되어야 한다.', () => { + cy.get('input').type(CONSTANTS.eventName); + cy.get('button').contains('다음').should('not.have.attr', 'disabled'); + cy.get('input').clear(); + cy.get('input').should('have.value', ''); + cy.get('button').contains('다음').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/name'); + }); + + it('행사 이름을 입력한 후 "다음" 버튼을 누르면 행사 비밀번호 설정 화면으로 이동해야 한다.', () => { + cy.get('input').type(CONSTANTS.eventName); + cy.get('button').contains('다음').click(); + cy.url().should('include', '/event/create/password'); + }); + }); + + context('행사 비밀번호 입력 페이지', () => { + beforeEach(() => { + cy.createEventName(CONSTANTS.eventName); + }); + + it('행사 비밀번호 입력 페이지에서 input이 포커싱 되어 있고, "행동 개시!" 버튼이 비활성화 되어 있어야 한다.', () => { + cy.get('input').focused(); + cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/password'); + }); + + it('행사 비밀번호에 숫자가 아닌 입력을 할 경우 값이 입력되지 않아야 한다.', () => { + cy.get('input').type('테스트'); + cy.get('input').should('have.value', ''); + }); + + it('행사 비밀번호에 4자리 이상 입력을 할 경우 처음 네 자리만 입력되어야 한다.', () => { + cy.get('input').type('12345'); + cy.get('input').should('have.value', CONSTANTS.eventPassword); + }); + + it('행사 비밀번호이 1자 이상 입력된 경우 "행동 개시!" 버튼이 활성화 되고, 값이 없는 경우 "행동 개시!" 버튼이 비활성화 되어야 한다.', () => { + cy.get('input').type(CONSTANTS.eventPassword); + cy.get('button').contains('행동 개시!').should('not.have.attr', 'disabled'); + cy.get('input').clear(); + cy.get('input').should('have.value', ''); + cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); + cy.url().should('include', '/event/create/password'); + }); + + it('행사 비밀번호을 입력한 후 "행동 개시!" 버튼을 누르면 행사 생성 완료 화면으로 이동해야 한다.', () => { + cy.interceptAPI({type: 'postEvent', statusCode: 200}); + cy.interceptAPI({type: 'getEventName', statusCode: 200}); + cy.get('input').type(CONSTANTS.eventPassword); + cy.get('button').contains('행동 개시!').click(); + + cy.url().should('include', '/event/create/complete'); + }); + }); +}); diff --git a/client/cypress/fixtures/postEvent.json b/client/cypress/fixtures/postEvent.json new file mode 100644 index 000000000..63b91e17b --- /dev/null +++ b/client/cypress/fixtures/postEvent.json @@ -0,0 +1,3 @@ +{ + "eventId": "550e8400-e29b-41d4-a716-446655440000" +} \ No newline at end of file diff --git a/client/cypress/support/commands.ts b/client/cypress/support/commands.ts new file mode 100644 index 000000000..c51d00580 --- /dev/null +++ b/client/cypress/support/commands.ts @@ -0,0 +1,58 @@ +import CONSTANTS from '../constants/constants'; + +type APIType = 'sentry' | 'postEvent' | 'getEventName'; + +interface InterceptAPIProps { + type: APIType; + delay?: number; + statusCode?: number; +} +const POST_EVENT = { + method: 'POST', + url: /.*api\/events.*/, +}; + +const GET_EVENT_NAME = { + method: 'GET', + url: /.*api\/events\.*/, +}; + +Cypress.Commands.add('blockSentry', () => { + cy.intercept('POST', /.*sentry.io\/api.*/, {statusCode: 200}).as('sentry'); +}); + +Cypress.Commands.add('interceptAPI', ({type, delay = 0, statusCode = 200}: InterceptAPIProps) => { + if (type === 'postEvent') + cy.intercept(POST_EVENT, { + delay, + statusCode, + fixture: 'postEvent.json', + }).as('postEvent'); + if (type === 'getEventName') + cy.intercept(GET_EVENT_NAME, { + delay, + statusCode, + body: { + eventName: CONSTANTS.eventName, + }, + }).as('getEventName'); +}); + +Cypress.Commands.add('createEventName', (eventName: string) => { + cy.visit('/event/create/name'); + cy.get('input').type(eventName); + cy.get('button').contains('다음').click(); + cy.url().should('include', '/event/create/password'); +}); + +declare global { + namespace Cypress { + interface Chainable { + blockSentry(): Chainable<void>; + interceptAPI(props: InterceptAPIProps): Chainable<void>; + createEventName(eventName: string): Chainable<void>; + } + } +} + +export {}; diff --git a/client/cypress/support/e2e.ts b/client/cypress/support/e2e.ts new file mode 100644 index 000000000..1221b17e0 --- /dev/null +++ b/client/cypress/support/e2e.ts @@ -0,0 +1 @@ +import './commands'; diff --git a/client/eslint.config.mjs b/client/eslint.config.mjs new file mode 100644 index 000000000..4ca5abb89 --- /dev/null +++ b/client/eslint.config.mjs @@ -0,0 +1,112 @@ +import {dirname} from 'path'; +import {fileURLToPath} from 'url'; +import reactPlugin from 'eslint-plugin-react'; +import tsPlugin from '@typescript-eslint/eslint-plugin'; +import importPlugin from 'eslint-plugin-import'; +import prettierPlugin from 'eslint-plugin-prettier'; +import typescriptParser from '@typescript-eslint/parser'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export default [ + { + files: ['src/**/*.{js,jsx,ts,tsx}'], + languageOptions: { + ecmaVersion: 2021, + sourceType: 'module', + parser: typescriptParser, + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + plugins: { + react: reactPlugin, + '@typescript-eslint': tsPlugin, + import: importPlugin, + prettier: prettierPlugin, + }, + rules: { + 'prettier/prettier': 'error', + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + 'react/jsx-uses-vars': 'error', + // '@typescript-eslint/no-use-before-define': ['error'], + // '@typescript-eslint/explicit-module-boundary-types': 'error', + // "import/no-unresolved": "error", + 'import/order': [ + 'error', + { + 'newlines-between': 'always', + groups: ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'], + pathGroups: [ + { + pattern: 'react*', + group: 'external', + position: 'before', + }, + { + pattern: '@hooks/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@apis/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@store/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@pages/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@components/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@utils/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@assets/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@constants/*', + group: 'internal', + position: 'after', + }, + { + pattern: '@mocks/*', + group: 'internal', + position: 'after', + }, + ], + }, + ], + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + typescript: { + directory: './src', + }, + }, + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'], + }, + }, + }, +]; diff --git a/client/favicon.ico b/client/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2be6241f8e7c02630efcc4cf714d8f9813cf7524 GIT binary patch literal 44932 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 Hu0mjfU8{Jm literal 0 HcmV?d00001 diff --git a/client/index.html b/client/index.html new file mode 100644 index 000000000..4a21293f2 --- /dev/null +++ b/client/index.html @@ -0,0 +1,33 @@ +<!doctype html> +<html lang="ko"> + <head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" /> + <meta content="upgrade-insecure-requests" /> + <meta name="haengdong" content="행동대장으로 간편하게 정산하세요" /> + <meta property="og:url" content="https://app.haengdong.pro" /> + <meta property="og:title" content="행동대장" /> + <meta property="og:type" content="website" /> + <meta property="og:description" content="행동대장으로 간편하게 정산하세요" /> + <meta + property="og:image" + content="https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%BF%A0%ED%82%A4%286%EA%B8%B0%29/4tyq1x19rsn.jpg" + /> + <meta property="og:image:type" content="image/png" /> + <meta property="og:image:alt" content="행댕이" /> + <link rel="icon" href="favicon.ico" type="image/x-icon" /> + <script src="https://cdn.amplitude.com/libs/analytics-browser-2.9.3-min.js.gz"></script> + <script src="https://cdn.amplitude.com/libs/plugin-session-replay-browser-1.6.8-min.js.gz"></script> + <script src="https://cdn.amplitude.com/libs/plugin-autocapture-browser-1.0.0-min.js.gz"></script> + <script> + window.amplitude.add(window.sessionReplay.plugin({sampleRate: 1})).promise.then(function () { + window.amplitude.add(window.amplitudeAutocapturePlugin.plugin()); + window.amplitude.init('<%= process.env.AMPLITUDE_KEY %>'); + }); + </script> + <title>행동대장 + + +
+ + diff --git a/client/jest.config.ts b/client/jest.config.ts new file mode 100644 index 000000000..a75677a5a --- /dev/null +++ b/client/jest.config.ts @@ -0,0 +1,49 @@ +import type {Config} from 'jest'; + +const config: Config = { + preset: 'ts-jest', + // testEnvironment: 'node', // Node.js 모듈(fs, path, http 등)을 사용한 서버 사이드 로직이나 파일 시스템 접근, 네트워크 요청 등을 테스트 + testEnvironment: 'jsdom', // 브라우저 내에서의 JavaScript 동작을 모방하여, DOM 조작, 이벤트 핸들링, 브라우저 관련 API 호출 + transform: { + '^.+\\.ts?$': 'ts-jest', + }, + collectCoverage: true, + coverageReporters: ['text'], + coveragePathIgnorePatterns: [ + '/node_modules/', + '/src/utils/', + '/src/mocks/', + '/src/apis/', + '/src/request/', + '/src/constants/', + '/src/errors/', + '/src/components/', + '/src/store/', + '/src/pages/', + '/src/hooks/queries', + ], + + verbose: true, + setupFiles: ['./jest.polyfills.ts'], + setupFilesAfterEnv: ['./jest.setup.ts'], + transformIgnorePatterns: ['/node_modules/'], + moduleNameMapper: { + '@/(.*)$': '/src/$1', // path alias를 적용하기 위함 + '^@apis/(.*)$': '/src/apis/$1', + '^@constants/(.*)$': '/src/constants/$1', + '^@components/(.*)$': '/src/components/$1', + '^@hooks/(.*)$': '/src/hooks/$1', + '^@utils/(.*)$': '/src/utils/$1', + '^@pages/(.*)$': '/src/pages/$1', + '^@types/(.*)$': '/src/types/$1', + '^@errors/(.*)$': '/src/errors/$1', + '^@mocks/(.*)$': '/src/mocks/$1', + '^@store/(.*)$': '/src/store/$1', + '\\.svg$': '/src/mocks/svg.ts', + }, + testEnvironmentOptions: { + customExportConditions: [''], + }, +}; + +export default config; diff --git a/client/jest.polyfills.ts b/client/jest.polyfills.ts new file mode 100644 index 000000000..16547bc80 --- /dev/null +++ b/client/jest.polyfills.ts @@ -0,0 +1,20 @@ +import {TextDecoder, TextEncoder} from 'node:util'; + +Object.defineProperties(globalThis, { + TextDecoder: {value: TextDecoder}, + TextEncoder: {value: TextEncoder}, +}); + +import {Blob, File} from 'node:buffer'; + +import {fetch, Headers, FormData, Request, Response} from 'undici'; + +Object.defineProperties(globalThis, { + fetch: {value: fetch, writable: true}, + Blob: {value: Blob}, + File: {value: File}, + Headers: {value: Headers}, + FormData: {value: FormData}, + Request: {value: Request}, + Response: {value: Response}, +}); diff --git a/client/jest.setup.ts b/client/jest.setup.ts new file mode 100644 index 000000000..33c8f6a70 --- /dev/null +++ b/client/jest.setup.ts @@ -0,0 +1,24 @@ +import {server} from './src/mocks/server'; +import * as router from 'react-router'; +import '@testing-library/jest-dom'; // toBeInTheDocument를 인식하기 위해 @testing-library/jest-dom/extend-expect추가 +import 'jest-canvas-mock'; // jsdom은 canvas를 추가할 수 없기 때문에 이를 해결하는 라이브러리 추가 + +beforeAll(() => { + server.listen(); + + Object.defineProperty(window, 'location', { + writable: true, + value: { + ...window.location, + pathname: '/event/abc-123/', // 원하는 pathname 설정 + }, + }); +}); +afterEach(() => server.resetHandlers()); +afterAll(() => server.close()); + +beforeAll(() => {}); +jest.mock('./src/utils/captureError'); +jest.mock('./src/utils/sendLogToSentry'); + +jest.spyOn(router, 'useNavigate').mockImplementation(() => jest.fn()); diff --git a/client/package-lock.json b/client/package-lock.json new file mode 100644 index 000000000..61a529538 --- /dev/null +++ b/client/package-lock.json @@ -0,0 +1,19037 @@ +{ + "name": "haengdong-client", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "haengdong-client", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@emotion/react": "^11.11.4", + "@sentry/react": "^8.25.0", + "@tanstack/react-query": "^5.51.23", + "haengdong-design": "^0.1.81", + "jest-canvas-mock": "^2.5.2", + "react": "^18.3.1", + "react-copy-to-clipboard": "^5.1.0", + "react-dom": "^18.3.1", + "react-error-boundary": "^4.0.13", + "react-router-dom": "^6.24.1", + "zustand": "^4.5.5" + }, + "devDependencies": { + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@jest/types": "^29.6.3", + "@sentry/webpack-plugin": "^2.22.0", + "@svgr/webpack": "^8.1.0", + "@tanstack/react-query-devtools": "^5.52.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.4.8", + "@testing-library/react": "^16.0.0", + "@types/dotenv-webpack": "^7.0.7", + "@types/jest": "^29.5.12", + "@types/react": "^18.3.3", + "@types/react-copy-to-clipboard": "^5.0.7", + "@types/react-dom": "^18.3.0", + "@types/testing-library__jest-dom": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "cypress": "^13.13.2", + "dotenv-webpack": "^8.1.0", + "eslint": "^9.6.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^4.6.2", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jsdom": "^24.1.1", + "modify-source-webpack-plugin": "^4.1.0", + "msw": "^2.3.5", + "prettier": "3.3.2", + "ts-jest": "^29.2.4", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typescript": "^5.5.4", + "typescript-eslint": "^7.16.0", + "undici": "^5.28.4", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^6.0.1" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", + "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", + "dependencies": { + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", + "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/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==" + }, + "node_modules/@babel/generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", + "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "dependencies": { + "@babel/types": "^7.25.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", + "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/traverse": "^7.25.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", + "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", + "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.24.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", + "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", + "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "dependencies": { + "@babel/types": "^7.25.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", + "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", + "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", + "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", + "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.25.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", + "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", + "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.0", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.0", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + }, + "node_modules/@babel/runtime": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", + "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", + "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", + "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/types": "^7.25.2", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", + "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "dependencies": { + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@bundled-es-modules/cookie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz", + "integrity": "sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==", + "dev": true, + "dependencies": { + "cookie": "^0.5.0" + } + }, + "node_modules/@bundled-es-modules/cookie/node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@bundled-es-modules/statuses": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz", + "integrity": "sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg==", + "dev": true, + "dependencies": { + "statuses": "^2.0.1" + } + }, + "node_modules/@bundled-es-modules/tough-cookie": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz", + "integrity": "sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw==", + "dev": true, + "dependencies": { + "@types/tough-cookie": "^4.0.5", + "tough-cookie": "^4.1.4" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@cypress/request": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz", + "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "http-signature": "~1.3.6", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "performance-now": "^2.1.0", + "qs": "6.10.4", + "safe-buffer": "^5.1.2", + "tough-cookie": "^4.1.3", + "tunnel-agent": "^0.6.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@cypress/request/node_modules/qs": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", + "integrity": "sha512-OQiU+C+Ds5qiH91qh/mg0w+8nwQuLjM4F4M/PbmhDOoYehPh+Fb0bDjtR1sOvy7YKxvj28Y/M0PhP5uVX0kB+g==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@cypress/xvfb": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", + "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "dev": true, + "dependencies": { + "debug": "^3.1.0", + "lodash.once": "^4.1.1" + } + }, + "node_modules/@cypress/xvfb/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", + "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.2.0", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" + }, + "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==" + }, + "node_modules/@emotion/react": { + "version": "11.13.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.0.tgz", + "integrity": "sha512-WkL+bw1REC2VNV1goQyfxjx1GYJkcc23CRQkXX+vZNLINyfI7o+uUn/rTGPt/xJ3bJHd5GcljgnxHf4wRw5VWQ==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.12.0", + "@emotion/cache": "^11.13.0", + "@emotion/serialize": "^1.3.0", + "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", + "@emotion/utils": "^1.4.0", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.0.tgz", + "integrity": "sha512-jACuBa9SlYajnpIVXB+XOXnfJHyckDfe6fOpORIM6yhBDlqGuExvDdZYHDQGoDf3bZXGv7tNr+LpLjJqiEQ6EA==", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.9.0", + "@emotion/utils": "^1.4.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" + }, + "node_modules/@emotion/unitless": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.9.0.tgz", + "integrity": "sha512-TP6GgNZtmtFaFcsOgExdnfxLLpRDla4Q66tnenA9CktvVSdNKDvMVuUah4QvWPIpNjrWsGg3qeGo9a43QooGZQ==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz", + "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==" + }, + "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==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", + "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/confirm": { + "version": "3.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", + "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", + "dev": true, + "dependencies": { + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.10.tgz", + "integrity": "sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==", + "dev": true, + "dependencies": { + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "@types/mute-stream": "^0.0.4", + "@types/node": "^22.1.0", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@inquirer/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@inquirer/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", + "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.2.tgz", + "integrity": "sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==", + "dev": true, + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/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/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", + "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@mswjs/interceptors": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", + "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "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", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sentry-internal/browser-utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", + "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", + "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", + "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", + "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", + "dependencies": { + "@sentry-internal/replay": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", + "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", + "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry-internal/feedback": "8.25.0", + "@sentry-internal/replay": "8.25.0", + "@sentry-internal/replay-canvas": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", + "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "2.22.0", + "@sentry/cli": "^2.33.1", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/cli": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", + "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", + "dependencies": { + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/react": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", + "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "dependencies": { + "@sentry/browser": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/types": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", + "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", + "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", + "dependencies": { + "@sentry/types": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/webpack-plugin": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", + "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "dev": true, + "dependencies": { + "@sentry/bundler-plugin-core": "2.22.0", + "unplugin": "1.0.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "webpack": ">=4.40.0" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "dependencies": { + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@swc/core": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.14.tgz", + "integrity": "sha512-9aeXeifnyuvc2pcuuhPQgVUwdpGEzZ+9nJu0W8/hNl/aESFsJGR5i9uQJRGu0atoNr01gK092fvmqMmQAPcKow==", + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.12" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.7.14", + "@swc/core-darwin-x64": "1.7.14", + "@swc/core-linux-arm-gnueabihf": "1.7.14", + "@swc/core-linux-arm64-gnu": "1.7.14", + "@swc/core-linux-arm64-musl": "1.7.14", + "@swc/core-linux-x64-gnu": "1.7.14", + "@swc/core-linux-x64-musl": "1.7.14", + "@swc/core-win32-arm64-msvc": "1.7.14", + "@swc/core-win32-ia32-msvc": "1.7.14", + "@swc/core-win32-x64-msvc": "1.7.14" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.14.tgz", + "integrity": "sha512-V0OUXjOH+hdGxDYG8NkQzy25mKOpcNKFpqtZEzLe5V/CpLJPnpg1+pMz70m14s9ZFda9OxsjlvPbg1FLUwhgIQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.14.tgz", + "integrity": "sha512-9iFvUnxG6FC3An5ogp5jbBfQuUmTTwy8KMB+ZddUoPB3NR1eV+Y9vOh/tfWcenSJbgOKDLgYC5D/b1mHAprsrQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.14.tgz", + "integrity": "sha512-zGJsef9qPivKSH8Vv4F/HiBXBTHZ5Hs3ZjVGo/UIdWPJF8fTL9OVADiRrl34Q7zOZEtGXRwEKLUW1SCQcbDvZA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.14.tgz", + "integrity": "sha512-AxV3MPsoI7i4B8FXOew3dx3N8y00YoJYvIPfxelw07RegeCEH3aHp2U2DtgbP/NV1ugZMx0TL2Z2DEvocmA51g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.14.tgz", + "integrity": "sha512-JDLdNjUj3zPehd4+DrQD8Ltb3B5lD8D05IwePyDWw+uR/YPc7w/TX1FUVci5h3giJnlMCJRvi1IQYV7K1n7KtQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.14.tgz", + "integrity": "sha512-Siy5OvPCLLWmMdx4msnEs8HvEVUEigSn0+3pbLjv78iwzXd0qSBNHUPZyC1xeurVaUbpNDxZTpPRIwpqNE2+Og==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.14.tgz", + "integrity": "sha512-FtEGm9mwtRYQNK43WMtUIadxHs/ja2rnDurB99os0ZoFTGG2IHuht2zD97W0wB8JbqEabT1XwSG9Y5wmN+ciEQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.14.tgz", + "integrity": "sha512-Jp8KDlfq7Ntt2/BXr0y344cYgB1zf0DaLzDZ1ZJR6rYlAzWYSccLYcxHa97VGnsYhhPspMpmCvHid97oe2hl4A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.14.tgz", + "integrity": "sha512-I+cFsXF0OU0J9J4zdWiQKKLURO5dvCujH9Jr8N0cErdy54l9d4gfIxdctfTF+7FyXtWKLTCkp+oby9BQhkFGWA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.14.tgz", + "integrity": "sha512-NNrprQCK6d28mG436jVo2TD+vACHseUECacEBGZ9Ef0qfOIWS1XIt2MisQKG0Oea2VvLFl6tF/V4Lnx/H0Sn3Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/types": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", + "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.51.21", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.51.21.tgz", + "integrity": "sha512-POQxm42IUp6n89kKWF4IZi18v3fxQWFRolvBA6phNVmA8psdfB1MvDnGacCJdS+EOX12w/CyHM62z//rHmYmvw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.51.16", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.51.16.tgz", + "integrity": "sha512-ajwuq4WnkNCMj/Hy3KR8d3RtZ6PSKc1dD2vs2T408MdjgKzQ3klVoL6zDgVO7X+5jlb5zfgcO3thh4ojPhfIaw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.51.23", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.51.23.tgz", + "integrity": "sha512-CfJCfX45nnVIZjQBRYYtvVMIsGgWLKLYC4xcUiYEey671n1alvTZoCBaU9B85O8mF/tx9LPyrI04A6Bs2THv4A==", + "dependencies": { + "@tanstack/query-core": "5.51.21" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.52.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.52.0.tgz", + "integrity": "sha512-oq8bDxMQ95edOlcWFaGsnSFzH11s06M1uiNiLtgsm+UG6Y5w+K6BJp0GeXN8q7sBNVBw/WPyeFdUH8rj9RT2Aw==", + "dev": true, + "dependencies": { + "@tanstack/query-devtools": "5.51.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.52.0", + "react": "^18 || ^19" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@testing-library/dom/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.8.tgz", + "integrity": "sha512-JD0G+Zc38f5MBHA4NgxQMR5XtO5Jx9g86jqturNTt2WUfRmLDIY7iKkWHDCCTiDuFMre6nxAD5wHw9W5kI4rGw==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", + "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true + }, + "node_modules/@types/dotenv-webpack": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", + "integrity": "sha512-tltVokFUeYuSjNmHc6N892Asu/JIQcnH2iUF5A29/VKqv9opq6KlrmnKd/Lt/bBikV/z0YN2K0kguTwWirYCMQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true + }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "dev": true, + "dependencies": { + "undici-types": "~6.13.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-copy-to-clipboard": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.7.tgz", + "integrity": "sha512-Gft19D+as4M+9Whq1oglhmK49vqPhcLzk8WfvfLvaYMIPYanyfLy0+CwFucMJfdKoSFyySPmkkWn8/E6voQXjQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", + "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", + "dev": true + }, + "node_modules/@types/sizzle": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz", + "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==", + "dev": true + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/statuses": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.5.tgz", + "integrity": "sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==", + "dev": true + }, + "node_modules/@types/testing-library__jest-dom": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-6.0.0.tgz", + "integrity": "sha512-bnreXCgus6IIadyHNlN/oI5FfX4dWgvGhOPvpr7zzCYDGAPIfvyIoAozMBINmhmsVuqV0cncejF2y5KC7ScqOg==", + "deprecated": "This is a stub types definition. @testing-library/jest-dom provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "@testing-library/jest-dom": "*" + } + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz", + "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", + "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/type-utils": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", + "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", + "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", + "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.18.0", + "@typescript-eslint/utils": "7.18.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", + "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", + "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/visitor-keys": "7.18.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", + "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.18.0", + "@typescript-eslint/types": "7.18.0", + "@typescript-eslint/typescript-estree": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", + "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.18.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", + "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", + "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.12.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", + "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-opt": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1", + "@webassemblyjs/wast-printer": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", + "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", + "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-buffer": "1.12.1", + "@webassemblyjs/wasm-gen": "1.12.1", + "@webassemblyjs/wasm-parser": "1.12.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", + "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", + "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.12.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz", + "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz", + "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz", + "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==", + "dev": true, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "webpack": "5.x.x", + "webpack-cli": "5.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "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": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "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, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "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, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz", + "integrity": "sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==", + "dev": true + }, + "node_modules/axe-core": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.0.tgz", + "integrity": "sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "dev": true + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cachedir": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", + "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001649", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz", + "integrity": "sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cliui/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cliui/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "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==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/core-js-compat": { + "version": "3.38.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", + "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/create-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/create-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssfontparser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssfontparser/-/cssfontparser-1.2.1.tgz", + "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==" + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", + "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", + "dev": true, + "dependencies": { + "rrweb-cssom": "^0.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", + "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/cypress": { + "version": "13.13.2", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.13.2.tgz", + "integrity": "sha512-PvJQU33933NvS1StfzEb8/mu2kMy4dABwCF+yd5Bi7Qly1HOVf+Bufrygee/tlmty/6j5lX+KIi8j9Q3JUMbhA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@cypress/request": "^3.0.1", + "@cypress/xvfb": "^1.2.4", + "@types/sinonjs__fake-timers": "8.1.1", + "@types/sizzle": "^2.3.2", + "arch": "^2.2.0", + "blob-util": "^2.0.2", + "bluebird": "^3.7.2", + "buffer": "^5.7.1", + "cachedir": "^2.3.0", + "chalk": "^4.1.0", + "check-more-types": "^2.24.0", + "cli-cursor": "^3.1.0", + "cli-table3": "~0.6.1", + "commander": "^6.2.1", + "common-tags": "^1.8.0", + "dayjs": "^1.10.4", + "debug": "^4.3.4", + "enquirer": "^2.3.6", + "eventemitter2": "6.4.7", + "execa": "4.1.0", + "executable": "^4.1.1", + "extract-zip": "2.0.1", + "figures": "^3.2.0", + "fs-extra": "^9.1.0", + "getos": "^3.2.1", + "is-ci": "^3.0.1", + "is-installed-globally": "~0.4.0", + "lazy-ass": "^1.6.0", + "listr2": "^3.8.3", + "lodash": "^4.17.21", + "log-symbols": "^4.0.0", + "minimist": "^1.2.8", + "ospath": "^1.2.2", + "pretty-bytes": "^5.6.0", + "process": "^0.11.10", + "proxy-from-env": "1.0.0", + "request-progress": "^3.0.0", + "semver": "^7.5.3", + "supports-color": "^8.1.1", + "tmp": "~0.2.3", + "untildify": "^4.0.0", + "yauzl": "^2.10.0" + }, + "bin": { + "cypress": "bin/cypress" + }, + "engines": { + "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + } + }, + "node_modules/cypress/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cypress/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cypress/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/cypress/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cypress/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cypress/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/cypress/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cypress/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cypress/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/cypress/node_modules/proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "dev": true + }, + "node_modules/cypress/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cypress/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "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.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", + "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "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, + "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-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-defaults": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dotenv-defaults/-/dotenv-defaults-2.0.2.tgz", + "integrity": "sha512-iOIzovWfsUHU91L5i8bJce3NYK5JXeAwH50Jh6+ARUdLiiGlYWfGw6UkzsYqaXZH/hjE/eCd/PlfM/qqyK0AMg==", + "dev": true, + "dependencies": { + "dotenv": "^8.2.0" + } + }, + "node_modules/dotenv-defaults/node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz", + "integrity": "sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag==", + "dev": true, + "dependencies": { + "dotenv-defaults": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "webpack": "^4 || ^5" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", + "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "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, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", + "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.17.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.8.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "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.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", + "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", + "dev": true, + "dependencies": { + "aria-query": "~5.1.3", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.9.1", + "axobject-query": "~3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.19", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", + "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": "*", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.35.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", + "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.19", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter2": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", + "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "dev": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "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 + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": 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==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.6.tgz", + "integrity": "sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/getos": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", + "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "dev": true, + "dependencies": { + "async": "^3.2.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals": { + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "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, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/haengdong-design": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.81.tgz", + "integrity": "sha512-IiXkt0zXSEmn7vstTLOeNZLFS35JO8lXbXavM55wdyAJd+w0e5kfRxyDk/K2oSiAnX2c2YPiGep/A0x2/gZPDg==", + "dependencies": { + "@emotion/react": "^11.11.4", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@svgr/webpack": "^8.1.0", + "lottie-react": "^2.4.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.24.1" + }, + "engines": { + "node": ">=20.15.1", + "npm": ">=10.7.0" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "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==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "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, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/headers-polyfill": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz", + "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==", + "dev": true + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-loader": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.1.0.tgz", + "integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==", + "dev": true, + "dependencies": { + "html-minifier-terser": "^7.2.0", + "parse5": "^7.1.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-signature": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", + "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^2.0.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.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", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-network-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", + "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-canvas-mock": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.2.tgz", + "integrity": "sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==", + "dependencies": { + "cssfontparser": "^1.2.1", + "moo-color": "^1.0.2" + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom/node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/jest-environment-jsdom/node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-jsdom/node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jest-environment-jsdom/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/jest-environment-jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-jsdom/node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-haste-map/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-haste-map/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jsdom": { + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz", + "integrity": "sha512-5O1wWV99Jhq4DV7rCLIoZ/UIhyQeDR7wHVyZAHAshbrvZsLs+Xzz7gtwnlJTJDjleiTKh54F4dXrX70vJQTyJQ==", + "dev": true, + "dependencies": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.4", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsprim": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", + "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/launch-editor": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", + "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "dev": true, + "engines": { + "node": "> 0.8" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/listr2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils-webpack-v4": { + "name": "loader-utils", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-update/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/modify-source-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/modify-source-webpack-plugin/-/modify-source-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-UaLQyFXoPWpWxkNUBFo9BotC20CCAGe7HEX9iKtB0P0MgNXgURf9TXUgNGuY5iVV5lDDQtcMjT2vneQWnNmwEw==", + "dev": true, + "dependencies": { + "loader-utils-webpack-v4": "npm:loader-utils@^2.0.4", + "schema-utils": "^4.0.0" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/modify-source-webpack-plugin/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/modify-source-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/moo-color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz", + "integrity": "sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==", + "dependencies": { + "color-name": "^1.1.4" + } + }, + "node_modules/moo-color/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/msw": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.3.5.tgz", + "integrity": "sha512-+GUI4gX5YC5Bv33epBrD+BGdmDvBg2XGruiWnI3GbIbRmMMBeZ5gs3mJ51OWSGHgJKztZ8AtZeYMMNMVrje2/Q==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@bundled-es-modules/cookie": "^2.0.0", + "@bundled-es-modules/statuses": "^1.0.1", + "@bundled-es-modules/tough-cookie": "^0.1.6", + "@inquirer/confirm": "^3.0.0", + "@mswjs/interceptors": "^0.29.0", + "@open-draft/until": "^2.1.0", + "@types/cookie": "^0.6.0", + "@types/statuses": "^2.0.4", + "chalk": "^4.1.2", + "graphql": "^16.8.1", + "headers-polyfill": "^4.0.2", + "is-node-process": "^1.2.0", + "outvariant": "^1.4.2", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.5.1", + "type-fest": "^4.9.0", + "yargs": "^17.7.2" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.7.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/msw/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/msw/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/msw/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/msw/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "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", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "dependencies": { + "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" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "dev": true, + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ospath": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", + "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", + "dev": true + }, + "node_modules/outvariant": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz", + "integrity": "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==", + "dev": true + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", + "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-error-boundary": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", + "integrity": "sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-router": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.0.tgz", + "integrity": "sha512-wVQq0/iFYd3iZ9H2l3N3k4PL8EEHcb0XlU2Na8nEwmiXgIUElEH6gaJDtUQxJ+JFzmIXaQjfdpcGWaM6IoQGxg==", + "dependencies": { + "@remix-run/router": "1.19.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.0.tgz", + "integrity": "sha512-RRGUIiDtLrkX3uYcFiCIxKFWMcWQGMojpYZfcstc63A1+sSnVgILGIm9gNUA6na3Fm1QuPGSBQH2EMbAZOnMsQ==", + "dependencies": { + "@remix-run/router": "1.19.0", + "react-router": "6.26.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "dev": true, + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", + "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.1", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "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", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/request-progress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", + "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", + "dev": true, + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "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, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/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 + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.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, + "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, + "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/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/strict-event-emitter": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz", + "integrity": "sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", + "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "dependencies": { + "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", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "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, + "dependencies": { + "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" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/svgo/node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/svgo/node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/svgo/node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/swc-loader": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", + "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dependencies": { + "@swc/counter": "^0.1.3" + }, + "peerDependencies": { + "@swc/core": "^1.2.147", + "webpack": ">=2" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/synckit": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", + "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", + "dev": true, + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.31.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", + "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.20", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "dev": true, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/throttleit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", + "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", + "dev": true, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "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==" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.2.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", + "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "ejs": "^3.1.10", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", + "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4", + "source-map": "^0.7.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ts-loader/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ts-loader/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ts-loader/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "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, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", + "integrity": "sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.18.0.tgz", + "integrity": "sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "7.18.0", + "@typescript-eslint/parser": "7.18.0", + "@typescript-eslint/utils": "7.18.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": 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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "dev": true, + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/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/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "node_modules/webpack": { + "version": "5.93.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", + "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.7.1", + "acorn-import-attributes": "^1.9.5", + "browserslist": "^4.21.10", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", + "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^2.1.1", + "@webpack-cli/info": "^2.0.2", + "@webpack-cli/serve": "^2.0.5", + "colorette": "^2.0.14", + "commander": "^10.0.1", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^3.1.1", + "rechoir": "^0.8.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.3.0.tgz", + "integrity": "sha512-xD2qnNew+F6KwOGZR7kWdbIou/ud7cVqLEXeK1q0nHcNsX/u7ul/fSdlOTX4ntSL5FNFy7ZJJXbf0piF591JYw==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.6.0", + "mime-types": "^2.1.31", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/memfs": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.11.1.tgz", + "integrity": "sha512-LZcMTBAgqUUKNXZagcZxvXXfgF1bHX7Y7nQ0QyEiNbRJgE29GhgPd8Yna1VQcLlPiHt/5RFJMWYN9Uv/VPNvjQ==", + "dev": true, + "dependencies": { + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + } + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-merge": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", + "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "dev": true + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.4.tgz", + "integrity": "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "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-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "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.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", + "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", + "dependencies": { + "use-sync-external-store": "1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + } + } +} diff --git a/client/package.json b/client/package.json new file mode 100644 index 000000000..6d673dd06 --- /dev/null +++ b/client/package.json @@ -0,0 +1,85 @@ +{ + "name": "haengdong-client", + "version": "1.0.0", + "description": "", + "type": "module", + "scripts": { + "prod": "NODE_ENV=production webpack server --open --config webpack.prod.mjs", + "dev": "NODE_ENV=development webpack server --open --config webpack.dev.mjs", + "build": "NODE_ENV=production webpack --config webpack.prod.mjs", + "build-dev": "NODE_ENV=development webpack --config webpack.dev.mjs", + "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", + "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", + "cypress-open": "cypress open", + "cypress-run": "cypress run", + "test": "jest" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.6.0", + "@jest/types": "^29.6.3", + "@sentry/webpack-plugin": "^2.22.0", + "@svgr/webpack": "^8.1.0", + "@tanstack/react-query-devtools": "^5.52.0", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.4.8", + "@testing-library/react": "^16.0.0", + "@types/dotenv-webpack": "^7.0.7", + "@types/jest": "^29.5.12", + "@types/react": "^18.3.3", + "@types/react-copy-to-clipboard": "^5.0.7", + "@types/react-dom": "^18.3.0", + "@types/testing-library__jest-dom": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^7.16.0", + "@typescript-eslint/parser": "^7.16.0", + "cypress": "^13.13.2", + "dotenv-webpack": "^8.1.0", + "eslint": "^9.6.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.9.0", + "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^4.6.2", + "fork-ts-checker-webpack-plugin": "^9.0.2", + "globals": "^15.8.0", + "html-loader": "^5.0.0", + "html-webpack-plugin": "^5.6.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jsdom": "^24.1.1", + "modify-source-webpack-plugin": "^4.1.0", + "msw": "^2.3.5", + "prettier": "3.3.2", + "ts-jest": "^29.2.4", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typescript": "^5.5.4", + "typescript-eslint": "^7.16.0", + "undici": "^5.28.4", + "webpack": "^5.93.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.4", + "webpack-merge": "^6.0.1" + }, + "dependencies": { + "@emotion/react": "^11.11.4", + "@sentry/react": "^8.25.0", + "@tanstack/react-query": "^5.51.23", + "haengdong-design": "^0.1.81", + "jest-canvas-mock": "^2.5.2", + "react": "^18.3.1", + "react-copy-to-clipboard": "^5.1.0", + "react-dom": "^18.3.1", + "react-error-boundary": "^4.0.13", + "react-router-dom": "^6.24.1", + "zustand": "^4.5.5" + }, + "engines": { + "npm": ">=10.7.0", + "node": ">=20.15.1" + } +} diff --git a/client/public/mockServiceWorker.js b/client/public/mockServiceWorker.js new file mode 100644 index 000000000..3abd19a06 --- /dev/null +++ b/client/public/mockServiceWorker.js @@ -0,0 +1,281 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker. + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const PACKAGE_VERSION = '2.3.5'; +const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'; +const IS_MOCKED_RESPONSE = Symbol('isMockedResponse'); +const activeClientIds = new Set(); + +self.addEventListener('install', function () { + self.skipWaiting(); +}); + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()); +}); + +self.addEventListener('message', async function (event) { + const clientId = event.source.id; + + if (!clientId || !self.clients) { + return; + } + + const client = await self.clients.get(clientId); + + if (!client) { + return; + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }); + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }); + break; + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, + }); + break; + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId); + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }); + break; + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId); + break; + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId); + + const remainingClients = allClients.filter(client => { + return client.id !== clientId; + }); + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister(); + } + + break; + } + } +}); + +self.addEventListener('fetch', function (event) { + const {request} = event; + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return; + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return; + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return; + } + + // Generate unique request ID. + const requestId = crypto.randomUUID(); + event.respondWith(handleRequest(event, requestId)); +}); + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event); + const response = await getResponse(event, client, requestId); + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + (async function () { + const responseClone = response.clone(); + + sendToClient( + client, + { + type: 'RESPONSE', + payload: { + requestId, + isMockedResponse: IS_MOCKED_RESPONSE in response, + type: responseClone.type, + status: responseClone.status, + statusText: responseClone.statusText, + body: responseClone.body, + headers: Object.fromEntries(responseClone.headers.entries()), + }, + }, + [responseClone.body], + ); + })(); + } + + return response; +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId); + + if (client?.frameType === 'top-level') { + return client; + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }); + + return allClients + .filter(client => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible'; + }) + .find(client => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id); + }); +} + +async function getResponse(event, client, requestId) { + const {request} = event; + + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const requestClone = request.clone(); + + function passthrough() { + const headers = Object.fromEntries(requestClone.headers.entries()); + + // Remove internal MSW request header so the passthrough request + // complies with any potential CORS preflight checks on the server. + // Some servers forbid unknown request headers. + delete headers['x-msw-intention']; + + return fetch(requestClone, {headers}); + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough(); + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough(); + } + + // Notify the client that a request has been intercepted. + const requestBuffer = await request.arrayBuffer(); + const clientMessage = await sendToClient( + client, + { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + mode: request.mode, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: requestBuffer, + keepalive: request.keepalive, + }, + }, + [requestBuffer], + ); + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.data); + } + + case 'PASSTHROUGH': { + return passthrough(); + } + } + + return passthrough(); +} + +function sendToClient(client, message, transferrables = []) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel(); + + channel.port1.onmessage = event => { + if (event.data && event.data.error) { + return reject(event.data.error); + } + + resolve(event.data); + }; + + client.postMessage(message, [channel.port2].concat(transferrables.filter(Boolean))); + }); +} + +async function respondWithMock(response) { + // Setting response status code to 0 is a no-op. + // However, when responding with a "Response.error()", the produced Response + // instance will have status code set to 0. Since it's not possible to create + // a Response instance with status code 0, handle that use-case separately. + if (response.status === 0) { + return Response.error(); + } + + const mockedResponse = new Response(response.body, response); + + Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { + value: true, + enumerable: true, + }); + + return mockedResponse; +} diff --git a/client/src/App.tsx b/client/src/App.tsx new file mode 100644 index 000000000..4e9ce39e1 --- /dev/null +++ b/client/src/App.tsx @@ -0,0 +1,31 @@ +import {Outlet} from 'react-router-dom'; +import {HDesignProvider} from 'haengdong-design'; +import {Global} from '@emotion/react'; +import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; + +import {ToastProvider} from '@hooks/useToast/ToastProvider'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import ErrorCatcher from '@components/AppErrorBoundary/ErrorCatcher'; + +import {GlobalStyle} from './GlobalStyle'; +import UnhandledErrorBoundary from './UnhandledErrorBoundary'; + +const App: React.FC = () => { + return ( + + + + + + + + + + + + + + ); +}; + +export default App; diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts new file mode 100644 index 000000000..ab16de8e1 --- /dev/null +++ b/client/src/GlobalStyle.ts @@ -0,0 +1,160 @@ +import {css} from '@emotion/react'; + +// reset css -> index css +export const GlobalStyle = css` + html, + body, + div, + span, + applet, + object, + iframe, + h1, + h2, + h3, + h4, + h5, + h6, + p, + blockquote, + pre, + a, + abbr, + acronym, + address, + big, + cite, + code, + del, + dfn, + em, + img, + ins, + kbd, + q, + s, + samp, + small, + strike, + strong, + sub, + sup, + tt, + b, + u, + i, + center, + dl, + dt, + dd, + ol, + ul, + li, + fieldset, + form, + label, + legend, + table, + caption, + tbody, + tfoot, + thead, + tr, + th, + td, + article, + aside, + canvas, + details, + embed, + figure, + figcaption, + footer, + header, + hgroup, + menu, + nav, + output, + ruby, + section, + summary, + time, + mark, + audio, + video { + vertical-align: baseline; + margin: 0; + border: 0; + padding: 0; + font-size: 100%; + font: inherit; + } + /* HTML5 display-role reset for older browsers */ + article, + aside, + details, + figcaption, + figure, + footer, + header, + hgroup, + menu, + nav, + section { + display: block; + } + body { + line-height: 1; + } + ol, + ul { + list-style: none; + } + blockquote, + q { + quotes: none; + } + blockquote:before, + blockquote:after, + q:before, + q:after { + content: ''; + content: none; + } + table { + border-collapse: collapse; + border-spacing: 0; + } + button { + cursor: pointer; + border: none; + background-color: transparent; + } + * { + box-sizing: border-box; + } + + html { + height: 100%; + } + + body { + max-width: 768px; + height: 100%; + margin: 0 auto; + + overflow-y: scroll; + &::-webkit-scrollbar { + display: none; + } + } + + section { + width: 100%; + } + + #root { + display: flex; + flex-direction: column; + } +`; diff --git a/client/src/UnhandledErrorBoundary.tsx b/client/src/UnhandledErrorBoundary.tsx new file mode 100644 index 000000000..78d017344 --- /dev/null +++ b/client/src/UnhandledErrorBoundary.tsx @@ -0,0 +1,10 @@ +import {StrictPropsWithChildren} from 'haengdong-design/dist/type/strictPropsWithChildren'; +import {ErrorBoundary} from 'react-error-boundary'; + +import ErrorPage from '@pages/ErrorPage/ErrorPage'; + +const UnhandledErrorBoundary = ({children}: StrictPropsWithChildren) => { + return }>{children}; +}; + +export default UnhandledErrorBoundary; diff --git a/client/src/apis/baseUrl.ts b/client/src/apis/baseUrl.ts new file mode 100644 index 000000000..37fc00a94 --- /dev/null +++ b/client/src/apis/baseUrl.ts @@ -0,0 +1,3 @@ +export const BASE_URL = { + HD: process.env.API_BASE_URL, +}; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts new file mode 100644 index 000000000..2e1c2d067 --- /dev/null +++ b/client/src/apis/fetcher.ts @@ -0,0 +1,120 @@ +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; + +import objectToQueryString from '@utils/objectToQueryString'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; + +import FetchError from '../errors/FetchError'; + +export type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; + +type Body = ReadableStream | XMLHttpRequestBodyInit; +type HeadersType = [string, string][] | Record | Headers; + +export type ObjectQueryParams = Record; + +type RequestProps = { + baseUrl?: string; + endpoint: string; + headers?: HeadersType; + body?: Body | object | null; + queryParams?: ObjectQueryParams; +}; + +type FetcherProps = RequestProps & { + method: Method; +}; + +type Options = { + method: Method; + headers: HeadersType; + body?: Body | null; +}; + +type ErrorHandlerProps = { + url: string; + options: Options; + body: string; +}; + +const API_BASE_URL = process.env.API_BASE_URL ?? ''; + +export const requestGet = async ({headers = {}, ...args}: RequestProps): Promise => { + const response = await fetcher({ + ...args, + method: 'GET', + headers, + }); + + const data: T = await response!.json(); + return data; +}; + +export const requestPatch = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'PATCH', headers, ...args}); +}; + +export const requestPut = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'PUT', headers, ...args}); +}; + +export const requestPostWithoutResponse = async ({headers = {}, ...args}: RequestProps) => { + await fetcher({method: 'POST', headers, ...args}); +}; + +export const requestPostWithResponse = async ({headers = {}, ...args}: RequestProps): Promise => { + const response = await fetcher({method: 'POST', headers, ...args}); + + const data: T = await response!.json(); + return data; +}; + +export const requestDelete = ({headers = {}, ...args}: RequestProps) => { + return fetcher({method: 'DELETE', headers, ...args}); +}; + +const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: FetcherProps) => { + const options = { + method, + credentials: 'include', + headers: { + 'Content-Type': 'application/json', + ...headers, + }, + body: body ? JSON.stringify(body) : null, + }; + + let url = `${baseUrl}${endpoint}`; + + if (queryParams) url += `?${objectToQueryString(queryParams)}`; + + return errorHandler({url, options, body: JSON.stringify(body)}); +}; + +const errorHandler = async ({url, options, body}: ErrorHandlerProps) => { + try { + const response: Response = await fetch(url, options); + + if (!response.ok) { + const serverErrorInfo: ErrorInfo = await response.json(); + + throw new FetchError({ + status: response.status, + requestBody: body, + endpoint: response.url, + errorInfo: serverErrorInfo, + name: serverErrorInfo.errorCode, + message: serverErrorInfo.message || '', + method: options.method, + }); + } + + return response; + } catch (error) { + if (error instanceof Error) { + throw error; // 그대로 FetchError || Error 인스턴스를 던집니다. + } + + throw new Error(UNKNOWN_ERROR); + } +}; diff --git a/client/src/apis/request/auth.ts b/client/src/apis/request/auth.ts new file mode 100644 index 000000000..9c56d1f6b --- /dev/null +++ b/client/src/apis/request/auth.ts @@ -0,0 +1,25 @@ +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestPostWithoutResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +export type RequestToken = { + password: string; +}; + +export const requestPostAuthentication = async ({eventId}: WithEventId) => { + await requestPostWithoutResponse({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/auth`, + }); +}; + +export const requestPostToken = async ({eventId, password}: WithEventId) => { + await requestPostWithoutResponse({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/login`, + body: { + password: password, + }, + }); +}; diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts new file mode 100644 index 000000000..c08168520 --- /dev/null +++ b/client/src/apis/request/bill.ts @@ -0,0 +1,69 @@ +import type {Bill, MemberReportInAction} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestDelete, requestGet, requestPostWithoutResponse, requestPut} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +type RequestPostBillList = { + billList: Bill[]; +}; + +export const requestPostBillList = async ({eventId, billList}: WithEventId) => { + await requestPostWithoutResponse({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions`, + body: { + actions: billList, + }, + }); +}; + +type RequestBillAction = { + actionId: number; +}; + +export const requestDeleteBillAction = async ({eventId, actionId}: WithEventId) => { + await requestDelete({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, + }); +}; + +type RequestPutBillAction = Bill & RequestBillAction; + +export const requestPutBillAction = async ({eventId, actionId, title, price}: WithEventId) => { + await requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, + body: { + title, + price, + }, + }); +}; + +export type MemberReportList = {members: MemberReportInAction[]}; + +export const requestGetMemberReportListInAction = async ({eventId, actionId}: WithEventId) => { + return requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, + }); +}; + +type RequestPutMemberReportList = RequestBillAction & MemberReportList; + +export const requestPutMemberReportListInAction = async ({ + eventId, + actionId, + members, +}: WithEventId) => { + return requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, + body: { + members, + }, + }); +}; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts new file mode 100644 index 000000000..c9299c813 --- /dev/null +++ b/client/src/apis/request/event.ts @@ -0,0 +1,32 @@ +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet, requestPostWithResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +export type RequestPostNewEvent = { + eventName: string; + password: number; +}; + +export type ResponsePostNewEvent = { + eventId: string; +}; + +export const requestPostNewEvent = async ({eventName, password}: RequestPostNewEvent) => { + return await requestPostWithResponse({ + endpoint: TEMP_PREFIX, + body: { + eventName: eventName, + password: password, + }, + }); +}; + +type ResponseGetEventName = { + eventName: string; +}; + +export const requestGetEventName = async ({eventId}: WithEventId) => { + return requestGet({ + endpoint: `${TEMP_PREFIX}/${eventId}`, + }); +}; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts new file mode 100644 index 000000000..dd7152575 --- /dev/null +++ b/client/src/apis/request/member.ts @@ -0,0 +1,84 @@ +import type {MemberType} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestDelete, requestGet, requestPut, requestPostWithoutResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +type RequestPostMemberList = { + memberNameList: string[]; + type: MemberType; +}; + +export const requestPostMemberList = async ({eventId, type, memberNameList}: WithEventId) => { + await requestPostWithoutResponse({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/member-actions`, + body: { + members: memberNameList, + status: type, + }, + }); +}; + +type RequestDeleteMemberAction = { + actionId: number; +}; + +export const requestDeleteMemberAction = async ({eventId, actionId}: WithEventId) => { + await requestDelete({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/member-actions/${actionId}`, + }); +}; + +type ResponseGetAllMemberList = { + memberNames: string[]; +}; + +export const requestGetAllMemberList = async ({eventId}: WithEventId) => { + return requestGet({ + endpoint: `${TEMP_PREFIX}/${eventId}/members`, + }); +}; + +export type MemberChange = { + before: string; + after: string; +}; + +type RequestPutAllMemberList = { + members: MemberChange[]; +}; + +export const requestPutAllMemberList = async ({eventId, members}: WithEventId) => { + await requestPut({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/nameChange`, + body: { + members, + }, + }); +}; + +type RequestDeleteAllMemberList = { + memberName: string; +}; + +export const requestDeleteAllMemberList = async ({eventId, memberName}: WithEventId) => { + await requestDelete({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/${memberName}`, + }); +}; + +export type ResponseGetCurrentInMemberList = { + memberNames: string[]; +}; + +export const requestGetCurrentInMemberList = async ({eventId}: WithEventId) => { + return await requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/members/current`, + }); +}; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts new file mode 100644 index 000000000..8992f9c30 --- /dev/null +++ b/client/src/apis/request/report.ts @@ -0,0 +1,19 @@ +import type {MemberReport} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +type ResponseGetMemberReportList = { + reports: MemberReport[]; +}; + +export const requestGetMemberReportList = async ({eventId}: WithEventId) => { + const {reports} = await requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/actions/reports`, + }); + + return reports; +}; diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts new file mode 100644 index 000000000..0d47ab90e --- /dev/null +++ b/client/src/apis/request/stepList.ts @@ -0,0 +1,17 @@ +import type {StepList} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {requestGet} from '@apis/fetcher'; +import {WithEventId} from '@apis/withEventId.type'; + +// TODO: (@weadie) 현재 토큰을 어떻게 관리할지.. 계속 사용되는데 +export const requestGetStepList = async ({eventId}: WithEventId) => { + // TODO: (@weadie) response가 어떻게 오는지 안나와서 data로만 써뒀어요. + const {steps} = await requestGet({ + baseUrl: BASE_URL.HD, + endpoint: `${TEMP_PREFIX}/${eventId}/actions`, + }); + + return steps; +}; diff --git a/client/src/apis/tempPrefix.ts b/client/src/apis/tempPrefix.ts new file mode 100644 index 000000000..949981b73 --- /dev/null +++ b/client/src/apis/tempPrefix.ts @@ -0,0 +1,2 @@ +// TODO: (@weadie) 반복되서 쓰이는 이 api/events가 추후 수정 가능성이 있어서 일단 편집하기 편하게 이 변수를 재사용하도록 했습니다. +export const TEMP_PREFIX = '/api/events'; diff --git a/client/src/apis/withEventId.type.ts b/client/src/apis/withEventId.type.ts new file mode 100644 index 000000000..b88160e3e --- /dev/null +++ b/client/src/apis/withEventId.type.ts @@ -0,0 +1,3 @@ +export type WithEventId

= P & { + eventId: string; +}; diff --git a/client/src/assets/image/addBillMockup.svg b/client/src/assets/image/addBillMockup.svg new file mode 100644 index 000000000..c7e4aa109 --- /dev/null +++ b/client/src/assets/image/addBillMockup.svg @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/image/addMemberMockup.svg b/client/src/assets/image/addMemberMockup.svg new file mode 100644 index 000000000..1bf5892d3 --- /dev/null +++ b/client/src/assets/image/addMemberMockup.svg @@ -0,0 +1,317 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/image/chevronDownLarge.svg b/client/src/assets/image/chevronDownLarge.svg new file mode 100644 index 000000000..11a631f88 --- /dev/null +++ b/client/src/assets/image/chevronDownLarge.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/assets/image/dog.svg b/client/src/assets/image/dog.svg new file mode 100644 index 000000000..f70558ed6 --- /dev/null +++ b/client/src/assets/image/dog.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/image/heundeut.svg b/client/src/assets/image/heundeut.svg new file mode 100644 index 000000000..c78ca8c9b --- /dev/null +++ b/client/src/assets/image/heundeut.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/assets/image/memberReportMockup.svg b/client/src/assets/image/memberReportMockup.svg new file mode 100644 index 000000000..efbaf3c1c --- /dev/null +++ b/client/src/assets/image/memberReportMockup.svg @@ -0,0 +1,311 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/image/runningDog.svg b/client/src/assets/image/runningDog.svg new file mode 100644 index 000000000..60951e642 --- /dev/null +++ b/client/src/assets/image/runningDog.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/assets/image/standingDog.svg b/client/src/assets/image/standingDog.svg new file mode 100644 index 000000000..2d34a8cf9 --- /dev/null +++ b/client/src/assets/image/standingDog.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx new file mode 100644 index 000000000..8d7946b8a --- /dev/null +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx @@ -0,0 +1,92 @@ +import {render, screen, waitFor} from '@testing-library/react'; +import {act, ReactNode} from 'react'; +import {MemoryRouter} from 'react-router-dom'; +import {HDesignProvider} from 'haengdong-design'; + +import FetchError from '@errors/FetchError'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; + +import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; + +import ErrorCatcher from './ErrorCatcher'; + +// 테스트용 헬퍼 컴포넌트 +const TestComponent = ({triggerError}: {triggerError: () => void}) => { + return ; +}; + +const setup = (ui: ReactNode) => + render( + + + + + {ui} + + + + , + ); + +describe('ErrorCatcher', () => { + jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: jest.fn(), + })); + + it('핸들링 가능한 에러인 경우 토스트가 표시된다.', async () => { + const errorCode = 'EVENT_NOT_FOUND'; + const error = new FetchError({ + errorInfo: {errorCode, message: '서버의 에러메세지'}, + name: errorCode, + message: '에러메세지', + status: 200, + endpoint: '', + method: 'GET', + requestBody: '', + }); + + const {updateAppError} = useAppErrorStore.getState(); + + setup( updateAppError(error)} />); + + act(() => { + screen.getByText('Trigger Error').click(); + }); + + const errorMessage = SERVER_ERROR_MESSAGES[errorCode]; + + await waitFor(() => { + expect(screen.getByText(errorMessage)).toBeInTheDocument(); + }); + }); + + it('핸들링 불가능한 에러인 경우 에러 바운더리가 표시된다.', async () => { + const errorCode = '모르겠는 에러'; + const error = new FetchError({ + errorInfo: {errorCode, message: '모르겠는 에러메세지'}, + name: errorCode, + message: '에러메세지', + status: 400, + endpoint: '', + method: 'GET', + requestBody: '', + }); + + const {updateAppError} = useAppErrorStore.getState(); + + setup( updateAppError(error)} />); + + act(() => { + screen.getByText('Trigger Error').click(); + }); + + await waitFor(() => { + expect(screen.getByText('알 수 없는 오류입니다.')).toBeInTheDocument(); + }); + }); +}); diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx new file mode 100644 index 000000000..dde5f3d64 --- /dev/null +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx @@ -0,0 +1,62 @@ +import {useEffect} from 'react'; + +import FetchError from '@errors/FetchError'; +import {useToast} from '@hooks/useToast/useToast'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +import {captureError} from '@utils/captureError'; + +import {SERVER_ERROR_MESSAGES, UNKNOWN_ERROR} from '@constants/errorMessage'; + +export type ErrorInfo = { + errorCode: string; + message: string; +}; + +const convertAppErrorToErrorInfo = (appError: Error) => { + if (appError instanceof Error) { + const errorInfo = + appError instanceof FetchError ? appError.errorInfo : {errorCode: appError.name, message: appError.message}; + + return errorInfo; + } else { + const errorInfo = {errorCode: UNKNOWN_ERROR, message: JSON.stringify(appError)}; + + return errorInfo; + } +}; + +const isUnhandledError = (errorInfo: ErrorInfo) => { + if (errorInfo.errorCode === 'INTERNAL_SERVER_ERROR') return true; + + return SERVER_ERROR_MESSAGES[errorInfo.errorCode] === undefined; +}; + +const ErrorCatcher = ({children}: React.PropsWithChildren) => { + const {appError} = useAppErrorStore(); + const {showToast} = useToast(); + + useEffect(() => { + if (appError) { + const errorInfo = convertAppErrorToErrorInfo(appError); + captureError(appError, errorInfo); + + if (!isUnhandledError(errorInfo)) { + showToast({ + showingTime: 3000, + message: SERVER_ERROR_MESSAGES[errorInfo.errorCode], + type: 'error', + position: 'bottom', + bottom: '8rem', + }); + } else { + throw appError; + } + } + }, [appError]); + + return children; +}; + +export default ErrorCatcher; diff --git a/client/src/components/Common/Logo/Logo.style.ts b/client/src/components/Common/Logo/Logo.style.ts new file mode 100644 index 000000000..89f97ede0 --- /dev/null +++ b/client/src/components/Common/Logo/Logo.style.ts @@ -0,0 +1,8 @@ +import {css} from '@emotion/react'; + +export const logoStyle = css({ + display: 'flex', + justifyContent: 'center', + + width: '100%', +}); diff --git a/client/src/components/Common/Logo/RunningDogLogo.tsx b/client/src/components/Common/Logo/RunningDogLogo.tsx new file mode 100644 index 000000000..a09a904c1 --- /dev/null +++ b/client/src/components/Common/Logo/RunningDogLogo.tsx @@ -0,0 +1,13 @@ +import RunningDog from '@assets/image/runningDog.svg'; + +import {logoStyle} from './Logo.style'; + +const RunningDogLogo = () => { + return ( +

+ +
+ ); +}; + +export default RunningDogLogo; diff --git a/client/src/components/Common/Logo/StandingDogLogo.tsx b/client/src/components/Common/Logo/StandingDogLogo.tsx new file mode 100644 index 000000000..5c2cf591e --- /dev/null +++ b/client/src/components/Common/Logo/StandingDogLogo.tsx @@ -0,0 +1,13 @@ +import StandingDog from '@assets/image/standingDog.svg'; + +import {logoStyle} from './Logo.style'; + +const StandingDogLogo = () => { + return ( +
+ +
+ ); +}; + +export default StandingDogLogo; diff --git a/client/src/components/Common/Logo/index.ts b/client/src/components/Common/Logo/index.ts new file mode 100644 index 000000000..43a08fd54 --- /dev/null +++ b/client/src/components/Common/Logo/index.ts @@ -0,0 +1,2 @@ +export {default as StandingDog} from './StandingDogLogo'; +export {default as RunningDog} from './RunningDogLogo'; diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx new file mode 100644 index 000000000..1004540fa --- /dev/null +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -0,0 +1,22 @@ +import {ExpenseList, Flex, Input} from 'haengdong-design'; +import React, {useState} from 'react'; + +import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; + +const MemberReportList = () => { + const [name, setName] = useState(''); + const {memberReportSearchList} = useSearchMemberReportList({name}); + + const changeName = ({target}: React.ChangeEvent) => { + setName(target.value); + }; + + return ( + + + + + ); +}; + +export default MemberReportList; diff --git a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx new file mode 100644 index 000000000..645acb468 --- /dev/null +++ b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx @@ -0,0 +1,142 @@ +import type {BillAction} from 'types/serviceType'; + +import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; + +import validatePurchase from '@utils/validate/validatePurchase'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; +import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; + +import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; + +import { + bottomSheetHeaderStyle, + bottomSheetStyle, + inputContainerStyle, +} from '../SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style'; + +type PutAndDeleteBillActionModalProps = { + billAction: BillAction; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch>; +}; + +const ExpenseDetailModal = ({ + billAction, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: PutAndDeleteBillActionModalProps) => { + const { + inputPair, + handleInputChange, + // handleOnBlur, + // errorMessage, + // errorInfo, + canSubmit, + onDelete, + onSubmit: putBillAction, + } = usePutAndDeleteBillAction( + {title: billAction.name, price: String(billAction.price), index: 0}, + validatePurchase, + () => setIsBottomSheetOpened(false), + ); + + const { + memberReportListInAction, + addAdjustedMember, + onSubmit: putMemberReportListInAction, + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + isExistAdjustedPrice, + } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); + const { + inputList, + onChange, + canEditList, + canSubmit: isChangedMemberReportInput, + } = useMemberReportInput({ + data: memberReportListInAction, + addAdjustedMember, + totalPrice: Number(inputPair.price), + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + }); + + const {data: stepListData = []} = useRequestGetStepList(); + + const actionMemberList = stepListData.filter(({actions}) => + actions.find(({actionId}) => actionId === billAction.actionId), + )[0].members; + + return ( + setIsBottomSheetOpened(false)}> + setIsBottomSheetOpened(false)}> +

+ 지출 내역 상세 +

+
+ + ) => handleInputChange('title', event)} + disabled + /> + + ) => handleInputChange('price', event)} + isFixed={isExistAdjustedPrice()} + disabled + /> + + + + + + + {inputList.map(({name, price, isFixed}, index) => ( + + + + onChange(event, index)} + isFixed={isFixed} + textSize="smallBody" + value={price} + placeholder="0" + type="number" + disabled + style={{textAlign: 'right'}} + > + + + + ))} + + +
+ + 닫기 + + +
+ ); +}; + +export default ExpenseDetailModal; diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts new file mode 100644 index 000000000..4bbefdba9 --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts @@ -0,0 +1,10 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1.5rem', +}); diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx new file mode 100644 index 000000000..e3579ab6b --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx @@ -0,0 +1,53 @@ +import type {MemberReport} from 'types/serviceType'; + +import {BottomSheet, FixedButton, Flex, Text} from 'haengdong-design'; + +import {bottomSheetStyle} from './MemberListInBillStep.style'; + +type MemberListInBillStepProps = { + stepName: string; + memberList: MemberReport[]; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; +}; + +const MemberListInBillStep = ({ + stepName, + memberList, + isOpenBottomSheet, + setIsOpenBottomSheet, +}: MemberListInBillStepProps) => { + const closeModal = () => setIsOpenBottomSheet(false); + + return ( + +
+ + {`${stepName} 참석자`} + {`총 ${memberList.length}명`} + + +
    + {memberList.map(member => ( +
  • + + + {member.name} + + + {`${member.price.toLocaleString('ko-kr')} 원`} + + +
  • + ))} +
+
+
+ + 닫기 + +
+ ); +}; + +export default MemberListInBillStep; diff --git a/client/src/components/Modal/MemberListInBillStep/index.ts b/client/src/components/Modal/MemberListInBillStep/index.ts new file mode 100644 index 000000000..137df8c87 --- /dev/null +++ b/client/src/components/Modal/MemberListInBillStep/index.ts @@ -0,0 +1 @@ +export {default as MemberListInBillStep} from './MemberListInBillStep'; diff --git a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx new file mode 100644 index 000000000..51e33589b --- /dev/null +++ b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx @@ -0,0 +1,39 @@ +import {SetAllMemberListModal, SetInitialMemberListModal, SetActionListModal} from '@components/Modal/index'; + +interface ModalBasedOnMemberCountProps { + allMemberList: string[]; + isOpenBottomSheet: boolean; + isOpenAllMemberListButton: boolean; + setIsOpenBottomSheet: React.Dispatch>; + setIsOpenAllMemberListButton: React.Dispatch>; +} + +const ModalBasedOnMemberCount = ({ + allMemberList, + isOpenBottomSheet, + isOpenAllMemberListButton, + setIsOpenBottomSheet, + setIsOpenAllMemberListButton, +}: ModalBasedOnMemberCountProps) => { + if (isOpenAllMemberListButton) { + return ( + + ); + } + switch (allMemberList.length) { + case 0: + return ( + + ); + + default: + return ; + } +}; + +export default ModalBasedOnMemberCount; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts new file mode 100644 index 000000000..7fad2e001 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts @@ -0,0 +1,23 @@ +import {css} from '@emotion/react'; + +const container = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + height: '100%', +}); + +const inputGroup = css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '14rem', +}); + +const addMemberActionListModalContentStyle = { + container, + inputGroup, +}; + +export default addMemberActionListModalContentStyle; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx new file mode 100644 index 000000000..ad6e63f28 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -0,0 +1,50 @@ +import type {MemberType} from 'types/serviceType'; + +import {FixedButton, LabelGroupInput} from 'haengdong-design'; + +import validateMemberName from '@utils/validate/validateMemberName'; +import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; + +import useDynamicInput from '@hooks/useDynamicInput'; + +import style from './AddMemberActionListModalContent.style'; +import InMember from './InMember'; +import OutMember from './OutMember'; + +interface AddMemberActionListModalContentProps { + inOutAction: MemberType; + setIsOpenBottomSheet: React.Dispatch>; +} + +const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: AddMemberActionListModalContentProps) => { + const dynamicProps = useDynamicInput(validateMemberName); + const {inputList, getFilledInputList, errorMessage, canSubmit, resetInputValue} = dynamicProps; + + const {mutate: postMemberList} = useRequestPostMemberList(); + + const handleUpdateMemberListSubmit = () => { + postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); + setIsOpenBottomSheet(false); + }; + + return ( +
+
+ + {inOutAction === 'IN' ? : } + +
+ { + handleUpdateMemberListSubmit(); + resetInputValue(); + }} + /> +
+ ); +}; + +export default AddMemberActionListModalContent; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx new file mode 100644 index 000000000..5f9f9a2e0 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx @@ -0,0 +1,35 @@ +import {LabelGroupInput} from 'haengdong-design'; + +import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; + +interface InMemberProps { + dynamicProps: ReturnUseDynamicInput; +} + +const InMember = ({dynamicProps}: InMemberProps) => { + const { + inputList, + inputRefList, + handleInputChange, + deleteEmptyInputElementOnBlur, + focusNextInputOnEnter, + errorIndexList, + } = dynamicProps; + return inputList.map(({value, index}) => ( + (inputRefList.current[index] = el)} + isError={errorIndexList.includes(index)} + onChange={e => handleInputChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + placeholder="이름" + autoFocus={inputList.length === 1 && index === 0} + /> + )); +}; + +export default InMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx new file mode 100644 index 000000000..9294b18ae --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -0,0 +1,52 @@ +import {LabelGroupInput, Search} from 'haengdong-design'; + +import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; +import useSearchInMemberList from '@hooks/useSearchInMemberList'; + +interface OutMemberProps { + dynamicProps: ReturnUseDynamicInput; +} + +const OutMember = ({dynamicProps}: OutMemberProps) => { + const { + inputList, + inputRefList, + errorIndexList, + deleteEmptyInputElementOnBlur, + focusNextInputOnEnter, + handleInputChange, + handleChange, + } = dynamicProps; + const {currentInputIndex, filteredInMemberList, handleCurrentInputIndex, searchCurrentInMember, chooseMember} = + useSearchInMemberList(handleChange); + + const validationAndSearchOnChange = (inputIndex: number, event: React.ChangeEvent) => { + handleCurrentInputIndex(inputIndex); + handleInputChange(inputIndex, event); + searchCurrentInMember(event); + }; + + return inputList.map(({value, index}) => ( + chooseMember(currentInputIndex, term)} + > + (inputRefList.current[index] = el)} + isError={errorIndexList.includes(index)} + onChange={e => validationAndSearchOnChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + placeholder="이름" + autoFocus={inputList.length === 1 && index === 0} + /> + + )); +}; + +export default OutMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts new file mode 100644 index 000000000..6519283f4 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts @@ -0,0 +1 @@ +export {default as AddMemberActionListModalContent} from './AddMemberActionListModalContent'; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts new file mode 100644 index 000000000..7be2f2141 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts @@ -0,0 +1,27 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1rem', +}); + +export const bottomSheetHeaderStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignContent: 'center', + + width: '100%', + padding: '0 0.5rem', +}); + +export const inputGroupStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '11rem', +}); diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx new file mode 100644 index 000000000..04242fad1 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -0,0 +1,88 @@ +import type {MemberAction, MemberType} from 'types/serviceType'; + +import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; + +import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; +import {useToast} from '@hooks/useToast/useToast'; + +import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; + +type DeleteMemberActionModalProps = { + memberActionType: MemberType; + memberActionList: MemberAction[]; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch>; +}; + +const DeleteMemberActionModal = ({ + memberActionType, + memberActionList, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: DeleteMemberActionModalProps) => { + const {showToast} = useToast(); + + const showToastAlreadyExistMemberAction = () => { + showToast({ + isClickToClose: true, + showingTime: 3000, + message: '이미 삭제된 인원입니다.', + type: 'error', + bottom: '160px', + }); + }; + + const showToastExistSameMemberFromAfterStep = (name: string) => { + showToast({ + isClickToClose: true, + showingTime: 3000, + message: `이후의 ${name}가 사라져요`, + type: 'error', + position: 'top', + top: '30px', + style: { + zIndex: 9000, + }, + }); + }; + + const {aliveActionList, deleteMemberActionList, addDeleteMemberAction} = useDeleteMemberAction({ + memberActionList, + setIsBottomSheetOpened, + showToastAlreadyExistMemberAction, + showToastExistSameMemberFromAfterStep, + }); + + return ( + setIsBottomSheetOpened(false)}> +
+
+ {memberActionType === 'IN' ? '들어온' : '나간'} 인원 수정하기 + {`${aliveActionList.length}명`} +
+
    + {aliveActionList.map(member => ( +
  • + +
    + +
    + addDeleteMemberAction(member)}> + + +
    +
  • + ))} +
+ +
+
+ ); +}; + +export default DeleteMemberActionModal; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts new file mode 100644 index 000000000..2a6b52b45 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts @@ -0,0 +1 @@ +export {default as DeleteMemberActionModal} from './DeleteMemberActionModal'; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx new file mode 100644 index 000000000..5f7d4501e --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -0,0 +1,149 @@ +import type {BillAction} from 'types/serviceType'; + +import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; + +import validatePurchase from '@utils/validate/validatePurchase'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; +import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; + +import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; + +import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './PutAndDeltetBillActionModal.style'; + +type PutAndDeleteBillActionModalProps = { + billAction: BillAction; + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch>; +}; + +const PutAndDeleteBillActionModal = ({ + billAction, + isBottomSheetOpened, + setIsBottomSheetOpened, +}: PutAndDeleteBillActionModalProps) => { + const { + inputPair, + handleInputChange, + // handleOnBlur, + // errorMessage, + // errorInfo, + canSubmit, + onDelete, + onSubmit: putBillAction, + } = usePutAndDeleteBillAction( + {title: billAction.name, price: String(billAction.price), index: 0}, + validatePurchase, + () => setIsBottomSheetOpened(false), + ); + + const { + memberReportListInAction, + addAdjustedMember, + onSubmit: putMemberReportListInAction, + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + isExistAdjustedPrice, + } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); + const { + inputList, + onChange, + canEditList, + canSubmit: isChangedMemberReportInput, + } = useMemberReportInput({ + data: memberReportListInAction, + addAdjustedMember, + totalPrice: Number(inputPair.price), + getIsSamePriceStateAndServerState, + getOnlyOneNotAdjustedRemainMemberIndex, + }); + + const {data: stepListData = []} = useRequestGetStepList(); + + const actionMemberList = stepListData.filter(({actions}) => + actions.find(({actionId}) => actionId === billAction.actionId), + )[0].members; + + return ( + setIsBottomSheetOpened(false)}> +
{ + event.preventDefault(); + + if (canSubmit) await putBillAction(event, inputPair, billAction.actionId); + if (isChangedMemberReportInput) putMemberReportListInAction(); + }} + > +

+ 지출 내역 수정하기 +

+
+ + ) => handleInputChange('title', event)} + /> + + ) => handleInputChange('price', event)} + isFixed={isExistAdjustedPrice()} + /> + + + + + + + {inputList.map(({name, price, isFixed}, index) => ( + + + + onChange(event, index)} + isFixed={isFixed} + textSize="smallBody" + value={price} + placeholder="0" + type="number" + readOnly={!canEditList[index]} + style={{textAlign: 'right'}} + > + + + + ))} + + +
+ onDelete(billAction.actionId)} + > + 수정 완료 + +
+
+ ); +}; + +export default PutAndDeleteBillActionModal; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts new file mode 100644 index 000000000..f58f43425 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts @@ -0,0 +1,28 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1rem', +}); + +export const bottomSheetHeaderStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignContent: 'center', + + width: '100%', + padding: '0 0.5rem', +}); + +export const inputContainerStyle = css({ + display: 'flex', + height: '100%', + flexDirection: 'column', + gap: '1.5rem', + overflow: 'auto', + paddingBottom: '14rem', +}); diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts new file mode 100644 index 000000000..c7cbcfcb6 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts @@ -0,0 +1 @@ +export {default as PutAndDeleteBillActionModal} from './PutAndDeleteBillActionModal'; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts b/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts new file mode 100644 index 000000000..ca6703309 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts @@ -0,0 +1,20 @@ +import {css} from '@emotion/react'; + +export const container = css({ + display: 'flex', + flexDirection: 'column', + width: '100%', + height: '100%', + padding: '0 1.5rem', + gap: '1.5rem', +}); + +export const switchContainer = css({ + display: 'flex', + width: '100%', + justifyContent: 'space-between', +}); + +const setActionListModalStyle = {container, switchContainer}; + +export default setActionListModalStyle; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx new file mode 100644 index 000000000..862bd91e3 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -0,0 +1,42 @@ +import type {InOutType} from 'types/serviceType'; + +import {useState} from 'react'; +import {BottomSheet, Switch, Text} from 'haengdong-design'; + +import {AddMemberActionListModalContent} from './AddMemberActionListModalContent'; +import style from './SetActionListModal.style'; + +export type ActionType = '지출' | '인원'; + +interface SetActionModalContentProps { + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; +} + +const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetActionModalContentProps) => { + const [inOutAction, setInOutAction] = useState('탈주'); + + const handleParticipantTypeChange = (value: string) => { + setInOutAction(value as InOutType); + }; + + return ( + setIsOpenBottomSheet(false)}> +
+
+ + 인원 변동 + + +
+ + +
+
+ ); +}; + +export default SetActionListModal; diff --git a/client/src/components/Modal/SetActionModal/index.ts b/client/src/components/Modal/SetActionModal/index.ts new file mode 100644 index 000000000..f689cb596 --- /dev/null +++ b/client/src/components/Modal/SetActionModal/index.ts @@ -0,0 +1 @@ +export {default as SetActionListModal} from './SetActionListModal'; diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts new file mode 100644 index 000000000..f54166c08 --- /dev/null +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts @@ -0,0 +1,36 @@ +import {css} from '@emotion/react'; + +export const allMemberListModalStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + width: '100%', + height: '100%', + }); + +export const allMemberListModalTitleStyle = () => + css({ + display: 'flex', + justifyContent: 'space-between', + width: '100%', + padding: '0 1.5rem', + }); + +export const allMemberListModalLabelGroupInputStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + padding: '0 1rem', + paddingBottom: '10rem', + + overflow: 'auto', + }); + +export const InputAndDeleteButtonContainer = () => + css({ + display: 'flex', + alignItems: 'center', + width: '100%', + gap: '1rem', + }); diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx new file mode 100644 index 000000000..58e86b917 --- /dev/null +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx @@ -0,0 +1,80 @@ +import {BottomSheet, Text, LabelGroupInput, FixedButton, IconButton, Icon} from 'haengdong-design'; + +import validateMemberName from '@utils/validate/validateMemberName'; + +import useSetAllMemberList from '@hooks/useSetAllMemberList'; + +import { + allMemberListModalLabelGroupInputStyle, + allMemberListModalStyle, + allMemberListModalTitleStyle, + InputAndDeleteButtonContainer, +} from './SetAllMemberListModal.style'; + +interface SetAllMemberListModalProps { + isOpenBottomSheet: boolean; + allMemberList: string[]; + setIsOpenBottomSheet: React.Dispatch>; + setIsOpenAllMemberListButton: React.Dispatch>; +} + +const SetAllMemberListModal = ({ + isOpenBottomSheet, + allMemberList, + setIsOpenBottomSheet, + setIsOpenAllMemberListButton, +}: SetAllMemberListModalProps) => { + const handleCloseAllMemberListModal = () => { + setIsOpenAllMemberListButton(prev => !prev); + setIsOpenBottomSheet(false); + }; + + const { + editedAllMemberList, + canSubmit, + errorMessage, + errorIndexList, + handleNameChange, + handleClickDeleteButton, + handlePutAllMemberList, + } = useSetAllMemberList({ + validateFunc: validateMemberName, + allMemberList, + handleCloseAllMemberListModal, + }); + + return ( + +
+
+ 전체 참여자 수정하기 + + 총 {allMemberList.length}명 + +
+
+ + {editedAllMemberList.map((member, index) => ( +
+
+ handleNameChange(index, e)} + /> +
+ handleClickDeleteButton(index)}> + + +
+ ))} +
+
+ +
+
+ ); +}; + +export default SetAllMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts new file mode 100644 index 000000000..ed835682c --- /dev/null +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts @@ -0,0 +1,20 @@ +import {css} from '@emotion/react'; + +export const setInitialMemberListModalStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1.5rem', + }); + +export const setInitialMemberListModalInputGroupStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + overflow: 'auto', + paddingBottom: '11rem', + }); diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx new file mode 100644 index 000000000..f73f2616d --- /dev/null +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -0,0 +1,66 @@ +import {Text, BottomSheet, FixedButton, LabelGroupInput} from 'haengdong-design'; + +import validateMemberName from '@utils/validate/validateMemberName'; +import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; + +import useDynamicInput from '@hooks/useDynamicInput'; + +import { + setInitialMemberListModalInputGroupStyle, + setInitialMemberListModalStyle, +} from './SetInitialMemberListModal.style'; + +interface SetInitialMemberListProps { + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; +} + +const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetInitialMemberListProps) => { + const { + inputList, + inputRefList, + handleInputChange, + deleteEmptyInputElementOnBlur, + getFilledInputList, + errorMessage, + canSubmit, + errorIndexList, + focusNextInputOnEnter, + } = useDynamicInput(validateMemberName); + const {mutate: postMemberList} = useRequestPostMemberList(); + + const handleSubmit = () => { + postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); + setIsOpenBottomSheet(false); + }; + + return ( + setIsOpenBottomSheet(false)}> +
+ 시작 인원 추가하기 +
+ + {inputList.map(({value, index}) => ( + (inputRefList.current[index] = el)} + onChange={e => handleInputChange(index, e)} + onBlur={() => deleteEmptyInputElementOnBlur()} + onKeyDown={e => focusNextInputOnEnter(e, index)} + autoFocus={inputList.length === 1 && index === 0} + /> + ))} + +
+
+ +
+ ); +}; + +export default SetInitialMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/index.ts b/client/src/components/Modal/SetInitialMemberListModal/index.ts new file mode 100644 index 000000000..18098e4f6 --- /dev/null +++ b/client/src/components/Modal/SetInitialMemberListModal/index.ts @@ -0,0 +1 @@ +export {default as SetInitialMemberListModal} from './SetInitialMemberListModal'; diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts new file mode 100644 index 000000000..180063b03 --- /dev/null +++ b/client/src/components/Modal/index.ts @@ -0,0 +1,4 @@ +export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; +export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; +export {default as SetAllMemberListModal} from './SetAllMemberListModal/SetAllMemberListModal'; +export {default as ModalBasedOnMemberCount} from './ModalBasedOnMemberCount/ModalBasedOnMemberCount'; diff --git a/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx new file mode 100644 index 000000000..aeec24c3a --- /dev/null +++ b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx @@ -0,0 +1,24 @@ +import {MutationCache, QueryCache, QueryClient, QueryClientProvider} from '@tanstack/react-query'; + +import {useAppErrorStore} from '@store/appErrorStore'; + +const QueryClientBoundary = ({children}: React.PropsWithChildren) => { + const {updateAppError} = useAppErrorStore(); + + const queryClient = new QueryClient({ + queryCache: new QueryCache({ + onError: (error: Error) => { + updateAppError(error); + }, + }), + mutationCache: new MutationCache({ + onError: (error: Error) => { + updateAppError(error); + }, + }), + }); + + return {children}; +}; + +export default QueryClientBoundary; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx new file mode 100644 index 000000000..7fed9ef5c --- /dev/null +++ b/client/src/components/StepList/BillStepItem.tsx @@ -0,0 +1,138 @@ +import {DragHandleItem, DragHandleItemContainer, EditableItem, Flex, Text} from 'haengdong-design'; +import {Fragment, useState} from 'react'; +import {useOutletContext} from 'react-router-dom'; + +import {BillStep, MemberReport} from 'types/serviceType'; +import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; +import {MemberListInBillStep} from '@components/Modal/MemberListInBillStep'; +import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; +import ExpenseDetailModal from '@components/Modal/ExpenseDetailModal/ExpenseDetailModal'; + +import useSetBillInput from '@hooks/useSetBillInput'; + +interface BillStepItemProps { + step: BillStep; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; + isAddEditableItem: boolean; + setIsAddEditableItem: React.Dispatch>; + isLastBillItem: boolean; + index: number; +} + +const BillStepItem: React.FC = ({ + step, + isOpenBottomSheet, + setIsOpenBottomSheet, + isAddEditableItem, + setIsAddEditableItem, + isLastBillItem, + index, +}) => { + const {isAdmin} = useOutletContext(); + const {handleBlurBillRequest, handleChangeBillInput, billInput} = useSetBillInput({setIsAddEditableItem}); + + const [clickedIndex, setClickedIndex] = useState(-1); + const [isOpenMemberListInBillStep, setIsOpenMemberListInBillStep] = useState(false); + + const totalPrice = step.actions && step.type === 'BILL' ? step.actions.reduce((acc, cur) => acc + cur.price, 0) : 0; + + const handleDragHandleItemClick = (index: number) => { + setClickedIndex(index); + setIsOpenBottomSheet(true); + }; + + const memberList: MemberReport[] = step.members.map(member => ({ + name: member, + price: totalPrice / step.members.length, + })); + + const handleTopRightTextClick = () => { + setIsOpenMemberListInBillStep(true); + }; + + return ( + <> + + {step.actions && + step.type === 'BILL' && + step.actions.map((action, index) => ( + + handleDragHandleItemClick(index)} + isFixed={action.isFixed} + /> + + {isOpenBottomSheet && clickedIndex === index && isAdmin && ( + + )} + {isOpenBottomSheet && clickedIndex === index && !isAdmin && ( + + )} + + ))} + + {isAddEditableItem && isLastBillItem && ( + { + if (e.key === 'Enter') { + handleBlurBillRequest(); + } + }} + > + handleChangeBillInput('title', e)} + autoFocus + > + + handleChangeBillInput('price', e)} + style={{textAlign: 'right'}} + > + + + + )} + + + + ); +}; + +export default BillStepItem; diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx new file mode 100644 index 000000000..ed3f5bfe7 --- /dev/null +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -0,0 +1,38 @@ +import type {MemberStep} from 'types/serviceType'; + +import {DragHandleItem} from 'haengdong-design'; +import {useOutletContext} from 'react-router-dom'; + +import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMemberActionModal'; +import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; + +interface MemberStepItemProps { + step: MemberStep; + isOpenBottomSheet: boolean; + setIsOpenBottomSheet: React.Dispatch>; +} + +const MemberStepItem: React.FC = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { + const {isAdmin} = useOutletContext(); + + return ( + <> + name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} + onClick={() => setIsOpenBottomSheet(prev => !prev)} + /> + {isOpenBottomSheet && isAdmin && ( + + )} + + ); +}; + +export default MemberStepItem; diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx new file mode 100644 index 000000000..f6c89475b --- /dev/null +++ b/client/src/components/StepList/Step.tsx @@ -0,0 +1,51 @@ +import type {BillStep, MemberStep} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import BillStepItem from './BillStepItem'; +import MemberStepItem from './MemberStepItem'; + +interface StepProps { + step: BillStep | MemberStep; + isAddEditableItem: boolean; + lastBillItemIndex: number; + lastItemIndex: number; + index: number; + setIsAddEditableItem: React.Dispatch>; +} + +const Step = ({step, isAddEditableItem, lastBillItemIndex, lastItemIndex, setIsAddEditableItem, index}: StepProps) => { + const [isOpenBottomSheet, setIsOpenBottomSheet] = useState(false); + const [isLastBillItem, setIsLastBillItem] = useState(false); + + useEffect(() => { + if (index === lastBillItemIndex && lastBillItemIndex === lastItemIndex) { + // index를 사용하여 마지막 BillStep인지 확인 + setIsLastBillItem(true); + } else { + setIsLastBillItem(false); + } + }, [index, lastBillItemIndex]); + + if (step.actions && step.type === 'BILL') { + return ( + + ); + } else if (step.actions && (step.type === 'IN' || step.type === 'OUT')) { + return ( + + ); + } else { + return <>; + } +}; + +export default Step; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx new file mode 100644 index 000000000..d6a507247 --- /dev/null +++ b/client/src/components/StepList/StepList.tsx @@ -0,0 +1,76 @@ +import {Flex} from 'haengdong-design'; +import {useEffect, useMemo, useState} from 'react'; + +import {BillStep, MemberStep} from 'types/serviceType'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; + +import Step from './Step'; + +interface StepListProps { + isAddEditableItem?: boolean; + setIsAddEditableItem?: React.Dispatch>; +} + +const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: StepListProps) => { + const {data: stepListData} = useRequestGetStepList(); + const [stepList, setStepList] = useState<(MemberStep | BillStep)[]>([]); + const existIndexInStepList = stepList.map((step, index) => ({...step, index})); + const [hasAddedItem, setHasAddedItem] = useState(false); + const nextStepName = stepList.length > 0 ? String(stepList[stepList.length - 1].stepName).match(/.*(?=차)/) : ''; + + useEffect(() => { + if (stepListData) { + setStepList(stepListData); + } + }, [stepListData]); + + const lastBillItemIndex = useMemo(() => { + const billSteps = existIndexInStepList.filter(step => step.type === 'BILL'); + + // billSteps 배열이 비어 있지 않으면 마지막 항목의 index를 반환, 그렇지 않으면 -1을 반환 + return billSteps.length > 0 ? billSteps.slice(-1)[0].index : -1; + }, [stepList]); + + const lastItemIndex = useMemo(() => { + return existIndexInStepList.length > 0 ? existIndexInStepList.slice(-1)[0].index : -1; + }, [existIndexInStepList]); + + useEffect(() => { + if (hasAddedItem) { + setHasAddedItem(false); + + setStepList(prev => [...prev.filter(({actions}) => actions.length !== 0)]); + } + + if (isAddEditableItem && lastBillItemIndex !== lastItemIndex && !hasAddedItem) { + setStepList(prev => [ + ...prev, + { + type: 'BILL', + stepName: `${Number(nextStepName) + 1}차`, + members: [], + actions: [], + }, + ]); + setHasAddedItem(prev => !prev); + } + }, [isAddEditableItem]); + + return ( + + {stepList.map((step, index) => ( + + ))} + + ); +}; + +export default StepList; diff --git a/client/src/components/Toast/Toast.style.ts b/client/src/components/Toast/Toast.style.ts new file mode 100644 index 000000000..a0b5c7cd4 --- /dev/null +++ b/client/src/components/Toast/Toast.style.ts @@ -0,0 +1,65 @@ +import {css, keyframes} from '@emotion/react'; + +import {ToastPosition} from './Toast.type'; + +type ToastMarginStyle = { + position?: ToastPosition; + bottom?: string; + top?: string; +}; + +// 애니메이션 키프레임 정의 +const fadeInWithTransformY = keyframes` + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +`; + +const fadeOutWithTransformY = keyframes` + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(20px); + } +`; + +export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => + css({ + position: 'absolute', + bottom: position === 'bottom' ? `${bottom}` : 'auto', + top: position === 'top' ? `${top}` : 'auto', + left: '50%', + transform: 'translate(-50%)', + + width: '100%', + maxWidth: '48rem', + paddingInline: '1rem', + }); + +export const toastStyle = (isVisible: boolean) => + css({ + width: '100%', + padding: '0.625rem 1rem', + + backgroundColor: 'gray', + boxShadow: '0 0.5rem 0.75rem rgba(0, 0, 0, 0.16);', + + borderRadius: '1.25rem', + + // 애니메이션 추가 + animation: `${isVisible ? fadeInWithTransformY : fadeOutWithTransformY} 0.5s forwards`, + }); + +export const textStyle = css({ + width: '100%', + color: 'white', + whiteSpace: 'pre-line', +}); diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx new file mode 100644 index 000000000..5bf44d6fb --- /dev/null +++ b/client/src/components/Toast/Toast.tsx @@ -0,0 +1,75 @@ +import {createPortal} from 'react-dom'; +import {useState, useEffect} from 'react'; +import {Button, Flex, Icon, Text} from 'haengdong-design'; + +import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; +import {ToastProps, ToastType} from './Toast.type'; + +const renderIcon = (type: ToastType) => { + if (type === 'none') return null; + + return ; +}; + +const ANIMATION_TIME = 500; + +const Toast = ({ + type = 'confirm', + top = '0px', + bottom = '0px', + isClickToClose = true, + position = 'bottom', + showingTime = 3000, + message, + onUndo, + onClose, + ...htmlProps +}: ToastProps) => { + const [isVisible, setIsVisible] = useState(true); + const styleProps = {position, top, bottom}; + + useEffect(() => { + const timer = setTimeout(() => { + setIsVisible(false); + setTimeout(() => { + if (onClose) onClose(); + }, ANIMATION_TIME); // fadeOut 애니메이션 시간과 동일하게 설정 + }, showingTime - ANIMATION_TIME); // 토스트가 내려가는 시간 확보 + + return () => { + clearTimeout(timer); + }; + }, [onClose]); + + const handleClickToClose = () => { + if (!isClickToClose || !onClose) return; + + setIsVisible(false); + setTimeout(() => { + onClose(); + }, ANIMATION_TIME); // fadeOut 애니메이션 시간과 동일하게 설정 + }; + + return createPortal( +
+
+ + + {renderIcon(type)} + + {message} + + + {onUndo && ( + + )} + +
+
, + document.body, + ); +}; + +export default Toast; diff --git a/client/src/components/Toast/Toast.type.ts b/client/src/components/Toast/Toast.type.ts new file mode 100644 index 000000000..20b92c0db --- /dev/null +++ b/client/src/components/Toast/Toast.type.ts @@ -0,0 +1,22 @@ +export type ToastPosition = 'bottom' | 'top'; +export type ToastType = 'error' | 'confirm' | 'none'; + +export interface ToastStyleProps { + bottom?: string; + top?: string; +} + +export interface ToastOptionProps { + position?: ToastPosition; + type?: ToastType; + onUndo?: () => void; + isClickToClose?: boolean; + onClose?: () => void; + showingTime?: number; +} + +export interface ToastRequiredProps { + message: string; +} + +export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts new file mode 100644 index 000000000..42703bdf0 --- /dev/null +++ b/client/src/constants/errorMessage.ts @@ -0,0 +1,49 @@ +type ErrorMessage = Record; + +export const SERVER_ERROR_MESSAGES: ErrorMessage = { + EVENT_NOT_FOUND: '존재하지 않는 행사입니다.', + EVENT_NAME_LENGTH_INVALID: '행사 이름은 2자 이상 30자 이하만 입력 가능합니다.', + EVENT_NAME_CONSECUTIVE_SPACES: '행사 이름에는 공백 문자가 연속될 수 없습니다.', + EVENT_PASSWORD_FORMAT_INVALID: '비밀번호는 4자리 숫자만 가능합니다.', + + ACTION_NOT_FOUND: '존재하지 않는 액션입니다.', + + MEMBER_NAME_LENGTH_INVALID: '멤버 이름은 1자 이상 4자 이하만 입력 가능합니다.', + MEMBER_NAME_DUPLICATE: '중복된 행사 참여 인원 이름이 존재합니다.', + MEMBER_NOT_EXIST: '현재 참여하고 있지 않은 인원이 존재합니다.', + MEMBER_ALREADY_EXIST: '현재 참여하고 있는 인원이 존재합니다.', + + MEMBER_ACTION_NOT_FOUND: '존재하지 않는 멤버 액션입니다.', + MEMBER_ACTION_STATUS_INVALID: '유효하지 않은 멤버 액션 상태입니다.', + + BILL_ACTION_NOT_FOUND: '존재하지 않는 지출 액션입니다.', + BILL_ACTION_TITLE_INVALID: '앞뒤 공백을 제거한 지출 내역 제목은 %d자 ~ %d자여야 합니다.', + BILL_ACTION_PRICE_INVALID: '지출 금액은 10,000,000 이하의 자연수여야 합니다.', + + REQUEST_EMPTY: '입력 값은 공백일 수 없습니다.', + MESSAGE_NOT_READABLE: '읽을 수 없는 요청입니다.', + NO_RESOURCE_REQUEST: '존재하지 않는 자원입니다.', + REQUEST_METHOD_NOT_SUPPORTED: '지원하지 않는 요청 메서드입니다.', + + INTERNAL_SERVER_ERROR: '서버 내부에 에러가 발생했습니다.', + + PASSWORD_INVALID: '비밀번호가 일치하지 않습니다.', + TOKEN_NOT_FOUND: '토큰이 존재하지 않습니다.', + TOKEN_EXPIRED: '만료된 토큰입니다.', + TOKEN_INVALID: '유효하지 않은 토큰입니다.', + FORBIDDEN: '접근할 수 없는 행사입니다.', + + UNHANDLED: '알 수 없는 에러입니다.', +}; + +export const ERROR_MESSAGE = { + eventName: '행사 이름은 30자 이하만 가능해요', + eventPasswordType: '비밀번호는 숫자만 입력이 가능해요', + memberName: '참여자 이름은 4자 이하의 한글, 영어만 가능해요', + purchasePrice: '10,000,000원 이하의 숫자만 입력이 가능해요', + purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', + preventEmpty: '값은 비어있을 수 없어요', + invalidInput: '올바르지 않은 입력이에요.', +}; + +export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; diff --git a/client/src/constants/password.ts b/client/src/constants/password.ts new file mode 100644 index 000000000..cfb26b39c --- /dev/null +++ b/client/src/constants/password.ts @@ -0,0 +1 @@ +export const PASSWORD_LENGTH = 4; diff --git a/client/src/constants/queryKeys.ts b/client/src/constants/queryKeys.ts new file mode 100644 index 000000000..17f3f4586 --- /dev/null +++ b/client/src/constants/queryKeys.ts @@ -0,0 +1,10 @@ +const QUERY_KEYS = { + stepList: 'stepList', + eventName: 'eventName', + allMemberList: 'allMemberList', + currentInMember: 'currentInMember', + memberReport: 'memberReport', + memberReportInAction: 'memberReportInAction', +}; + +export default QUERY_KEYS; diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts new file mode 100644 index 000000000..4d910ac99 --- /dev/null +++ b/client/src/constants/regExp.ts @@ -0,0 +1,8 @@ +const REGEXP = { + eventPassword: /^[0-9]*$/, + memberName: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s]*$/, + purchaseTitle: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s]*$/, + eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, +}; + +export default REGEXP; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts new file mode 100644 index 000000000..6a3634c3b --- /dev/null +++ b/client/src/constants/routerUrls.ts @@ -0,0 +1,10 @@ +export const ROUTER_URLS = { + main: '/', + eventCreateName: '/event/create/name', + eventCreatePassword: '/event/create/password', + eventCreateComplete: '/event/create/complete', + event: '/event', // TODO: (@weadie) baseurl을 어떻게 관리할 것인가? + eventLogin: '/event/:eventId/login', + eventManage: '/event/:eventId/admin', + home: '/event/:eventId/home', +}; diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts new file mode 100644 index 000000000..4b78031b9 --- /dev/null +++ b/client/src/constants/rule.ts @@ -0,0 +1,8 @@ +const RULE = { + maxEventNameLength: 30, + maxEventPasswordLength: 4, + maxMemberNameLength: 4, + maxPrice: 10000000, +}; + +export default RULE; diff --git a/client/src/errors/FetchError.ts b/client/src/errors/FetchError.ts new file mode 100644 index 000000000..9123a80b5 --- /dev/null +++ b/client/src/errors/FetchError.ts @@ -0,0 +1,23 @@ +import {FetchErrorType} from '../types/fetchErrorType'; + +class FetchError extends Error { + requestBody; + status; + endpoint; + errorInfo; + method; + + constructor({requestBody, status, endpoint, errorInfo, method, name, message}: FetchErrorType) { + super(errorInfo.errorCode); + + this.requestBody = requestBody; + this.status = status; + this.endpoint = endpoint; + this.errorInfo = errorInfo; + this.method = method; + this.name = name; + this.message = message; + } +} + +export default FetchError; diff --git a/client/src/global.d.ts b/client/src/global.d.ts new file mode 100644 index 000000000..dbf6320af --- /dev/null +++ b/client/src/global.d.ts @@ -0,0 +1,11 @@ +declare module '*.svg'; + +declare namespace NodeJS { + interface ProcessEnv { + readonly NODE_ENV: 'development' | 'production' | 'test'; + + // env keys + readonly API_BASE_URL: string; + readonly AMPLITUDE_KEY: string; + } +} diff --git a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts new file mode 100644 index 000000000..da6fc4223 --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts @@ -0,0 +1,28 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteAllMemberListMutationProps { + memberName: string; +} + +const useRequestDeleteAllMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({memberName}: DeleteAllMemberListMutationProps) => requestDeleteAllMemberList({eventId, memberName}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestDeleteAllMemberList; diff --git a/client/src/hooks/queries/useRequestDeleteBillAction.ts b/client/src/hooks/queries/useRequestDeleteBillAction.ts new file mode 100644 index 000000000..28be9dfd1 --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteBillAction.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteBillAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteBillActionMutationProps { + actionId: number; +} + +const useRequestDeleteBillAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId}: DeleteBillActionMutationProps) => requestDeleteBillAction({eventId, actionId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestDeleteBillAction; diff --git a/client/src/hooks/queries/useRequestDeleteMemberAction.ts b/client/src/hooks/queries/useRequestDeleteMemberAction.ts new file mode 100644 index 000000000..08e69ac1f --- /dev/null +++ b/client/src/hooks/queries/useRequestDeleteMemberAction.ts @@ -0,0 +1,28 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteMemberAction} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface DeleteMemberActionMutationProps { + actionId: number; +} + +const useRequestDeleteMemberAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId}: DeleteMemberActionMutationProps) => requestDeleteMemberAction({eventId, actionId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + }, + }); +}; + +export default useRequestDeleteMemberAction; diff --git a/client/src/hooks/queries/useRequestGetAllMemberList.ts b/client/src/hooks/queries/useRequestGetAllMemberList.ts new file mode 100644 index 000000000..531285fd6 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetAllMemberList.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetAllMemberList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.allMemberList], + queryFn: () => requestGetAllMemberList({eventId}), + }); +}; + +export default useRequestGetAllMemberList; diff --git a/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts b/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts new file mode 100644 index 000000000..31dc058c2 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetCurrentInMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetCurrentInMemberList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.currentInMember], + queryFn: () => requestGetCurrentInMemberList({eventId}), + }); +}; + +export default useRequestGetCurrentInMemberList; diff --git a/client/src/hooks/queries/useRequestGetEventName.ts b/client/src/hooks/queries/useRequestGetEventName.ts new file mode 100644 index 000000000..6ddb21858 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetEventName.ts @@ -0,0 +1,18 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetEventName} from '@apis/request/event'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetEventName = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.eventName], + queryFn: () => requestGetEventName({eventId}), + }); +}; + +export default useRequestGetEventName; diff --git a/client/src/hooks/queries/useRequestGetMemberReportList.ts b/client/src/hooks/queries/useRequestGetMemberReportList.ts new file mode 100644 index 000000000..fe3372d35 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetMemberReportList.ts @@ -0,0 +1,17 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetMemberReportList} from '@apis/request/report'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetMemberReportList = () => { + const eventId = getEventIdByUrl(); + + return useQuery({ + queryKey: [QUERY_KEYS.memberReport], + queryFn: () => requestGetMemberReportList({eventId}), + }); +}; +export default useRequestGetMemberReportList; diff --git a/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts b/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts new file mode 100644 index 000000000..85b458228 --- /dev/null +++ b/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts @@ -0,0 +1,24 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetMemberReportListInAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetMemberReportListInAction = (actionId: number) => { + const eventId = getEventIdByUrl(); + + const {data, ...queryResult} = useQuery({ + queryKey: [QUERY_KEYS.memberReportInAction, actionId], + queryFn: () => requestGetMemberReportListInAction({eventId, actionId}), + select: data => data.members, + }); + + return { + memberReportListInActionFromServer: data ?? [], + queryResult, + }; +}; + +export default useRequestGetMemberReportListInAction; diff --git a/client/src/hooks/queries/useRequestGetStepList.ts b/client/src/hooks/queries/useRequestGetStepList.ts new file mode 100644 index 000000000..7dfc1799c --- /dev/null +++ b/client/src/hooks/queries/useRequestGetStepList.ts @@ -0,0 +1,30 @@ +import {useQuery} from '@tanstack/react-query'; +import {useEffect} from 'react'; + +import {requestGetStepList} from '@apis/request/stepList'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetStepList = () => { + const eventId = getEventIdByUrl(); + const {updateTotalExpenseAmount} = useTotalExpenseAmountStore(); + + const queryResult = useQuery({ + queryKey: [QUERY_KEYS.stepList], + queryFn: () => requestGetStepList({eventId}), + }); + + useEffect(() => { + if (queryResult.isSuccess && queryResult.data) { + updateTotalExpenseAmount(queryResult.data); + } + }, [queryResult.data, queryResult.isSuccess, updateTotalExpenseAmount]); + + return queryResult; +}; + +export default useRequestGetStepList; diff --git a/client/src/hooks/queries/useRequestPostAuthentication.ts b/client/src/hooks/queries/useRequestPostAuthentication.ts new file mode 100644 index 000000000..e533a501b --- /dev/null +++ b/client/src/hooks/queries/useRequestPostAuthentication.ts @@ -0,0 +1,23 @@ +import {useMutation} from '@tanstack/react-query'; +import {useNavigate} from 'react-router-dom'; + +import {requestPostAuthentication} from '@apis/request/auth'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const useRequestPostAuthenticate = () => { + const eventId = getEventIdByUrl(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: () => requestPostAuthentication({eventId}), + onError: () => { + // 에러가 발생하면 로그인 페이지로 리다이렉트 + navigate(`${ROUTER_URLS.event}/${eventId}/login`); + }, + }); +}; + +export default useRequestPostAuthenticate; diff --git a/client/src/hooks/queries/useRequestPostBillList.ts b/client/src/hooks/queries/useRequestPostBillList.ts new file mode 100644 index 000000000..676da9d85 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostBillList.ts @@ -0,0 +1,27 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPostBillList} from '@apis/request/bill'; +import {Bill} from 'types/serviceType'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PostBillActionMutationProps { + billList: Bill[]; +} + +const useRequestPostBillList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({billList}: PostBillActionMutationProps) => requestPostBillList({eventId, billList}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPostBillList; diff --git a/client/src/hooks/queries/useRequestPostEvent.ts b/client/src/hooks/queries/useRequestPostEvent.ts new file mode 100644 index 000000000..5327710fc --- /dev/null +++ b/client/src/hooks/queries/useRequestPostEvent.ts @@ -0,0 +1,16 @@ +import {useMutation} from '@tanstack/react-query'; + +import {requestPostNewEvent} from '@apis/request/event'; + +interface PostEventMutationProps { + eventName: string; + password: number; +} + +const usePostEvent = () => { + return useMutation({ + mutationFn: ({eventName, password}: PostEventMutationProps) => requestPostNewEvent({eventName, password}), + }); +}; + +export default usePostEvent; diff --git a/client/src/hooks/queries/useRequestPostLogin.ts b/client/src/hooks/queries/useRequestPostLogin.ts new file mode 100644 index 000000000..21dce1791 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostLogin.ts @@ -0,0 +1,26 @@ +import {useMutation} from '@tanstack/react-query'; +import {useNavigate} from 'react-router-dom'; + +import {requestPostToken} from '@apis/request/auth'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +interface PostLoginMutationProps { + password: string; +} + +const useRequestPostLogin = () => { + const eventId = getEventIdByUrl(); + const navigate = useNavigate(); + + return useMutation({ + mutationFn: ({password}: PostLoginMutationProps) => requestPostToken({eventId, password}), + onSuccess: () => { + navigate(`${ROUTER_URLS.event}/${eventId}/admin`); + }, + }); +}; + +export default useRequestPostLogin; diff --git a/client/src/hooks/queries/useRequestPostMemberList.ts b/client/src/hooks/queries/useRequestPostMemberList.ts new file mode 100644 index 000000000..8ed69db08 --- /dev/null +++ b/client/src/hooks/queries/useRequestPostMemberList.ts @@ -0,0 +1,37 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {MemberType} from 'types/serviceType'; +import {requestPostMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PostMemberListMutationProps { + type: MemberType; + memberNameList: string[]; +} + +const useRequestPostMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({type, memberNameList}: PostMemberListMutationProps) => + requestPostMemberList({eventId, type, memberNameList}), + // TODO: (@todari) : 낙관적 업데이트 적고 있었어용 + // onMutate: async ({type, memberNameList}) => { + // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.stepList]}); + // const previousStepList = queryClient.getQueryData([QUERY_KEYS.stepList]); + // queryClient.setQueryData([QUERY_KEYS.stepList], (prev: (MemberStep | BillStep)[]) => prev && { + // }); + // }, + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPostMemberList; diff --git a/client/src/hooks/queries/useRequestPutAllMemberList.ts b/client/src/hooks/queries/useRequestPutAllMemberList.ts new file mode 100644 index 000000000..4bd746d0c --- /dev/null +++ b/client/src/hooks/queries/useRequestPutAllMemberList.ts @@ -0,0 +1,28 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {MemberChange, requestPutAllMemberList} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PutAllMemberListMutationProps { + members: MemberChange[]; +} + +const useRequestPutAllMemberList = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({members}: PutAllMemberListMutationProps) => requestPutAllMemberList({eventId, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPutAllMemberList; diff --git a/client/src/hooks/queries/useRequestPutBillAction.ts b/client/src/hooks/queries/useRequestPutBillAction.ts new file mode 100644 index 000000000..a58da8ea4 --- /dev/null +++ b/client/src/hooks/queries/useRequestPutBillAction.ts @@ -0,0 +1,29 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPutBillAction} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +interface PutBillActionMutationProps { + actionId: number; + title: string; + price: number; +} + +const useRequestPutBillAction = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({actionId, title, price}: PutBillActionMutationProps) => + requestPutBillAction({eventId, actionId, title, price}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + }, + }); +}; + +export default useRequestPutBillAction; diff --git a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts new file mode 100644 index 000000000..a87fa44f1 --- /dev/null +++ b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts @@ -0,0 +1,49 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {MemberReportList, requestPutMemberReportListInAction} from '@apis/request/bill'; +import {MemberReportInAction} from 'types/serviceType'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutMemberReportListInAction = (actionId: number) => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...mutationProps} = useMutation({ + mutationFn: (members: MemberReportInAction[]) => requestPutMemberReportListInAction({eventId, actionId, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + }, + onMutate: async (newMembers: MemberReportInAction[]) => { + await queryClient.cancelQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + + const previousMembers = queryClient.getQueryData([QUERY_KEYS.memberReportInAction, actionId]); + + queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], (oldData: MemberReportList) => ({ + ...oldData, + members: oldData.members.map((member: MemberReportInAction) => { + const updatedMember = newMembers.find(m => m.name === member.name); + return updatedMember ? {...member, ...updatedMember} : member; + }), + })); + + return {previousMembers}; + }, + onError: (err, newMembers, context) => { + if (context?.previousMembers) { + queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], context.previousMembers); + } + }, + }); + + return { + putMemberReportListInAction: mutate, + mutationProps, + }; +}; + +export default useRequestPutMemberReportListInAction; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx new file mode 100644 index 000000000..38836f677 --- /dev/null +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -0,0 +1,139 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {act} from 'react'; +import {HDesignProvider} from 'haengdong-design'; + +import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; + +import stepListJson from '@mocks/stepList.json'; +import invalidMemberStepListJson from '@mocks/invalidMemberStepList.json'; + +import useDeleteMemberAction from './useDeleteMemberAction'; + +const stepListMockData = stepListJson as (BillStep | MemberStep)[]; +let memberActionList: MemberAction[] = []; + +// filter로는 type narrowing이 안되어 부득이하게 for 문을 사용했습니다. +for (let i = 0; i < stepListMockData.length; i++) { + const curAction = stepListMockData[i]; + if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); +} + +describe('useDeleteMemberAction', () => { + const initializeProvider = (list: MemberAction[] = memberActionList) => + renderHook( + () => { + return { + stepListResult: useRequestGetStepList(), + deleteMemberActionList: useDeleteMemberAction({ + memberActionList: list, + setIsBottomSheetOpened: () => {}, + showToastAlreadyExistMemberAction: () => {}, + showToastExistSameMemberFromAfterStep: () => {}, + }), + }; + }, + { + wrapper: ({children}) => ( + + + + + {children} + + + + + ), + }, + ); + + it('멤버를 삭제할 멤버 목록에 추가한다.', async () => { + const {result} = initializeProvider(); + + // stepList 값이 채워지길 대기합니다. + await waitFor(() => { + expect(result.current.stepListResult.data).not.toStrictEqual([]); + }); + + act(() => { + const memberAction = { + actionId: 1, + name: '망쵸', + price: null, + sequence: 1, + isFixed: false, + }; + + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + + expect(result.current.deleteMemberActionList.aliveActionList).not.toContainEqual({ + actionId: 1, + name: '망쵸', + price: null, + sequence: 1, + }); + }); + + it('삭제할 멤버 목록에 있는 멤버들을 모두 삭제해 삭제할 멤버 목록을 비운다.', async () => { + const {result} = initializeProvider(); + + // stepList 값이 채워지길 대기합니다. + await waitFor(() => { + expect(result.current.stepListResult.data).not.toStrictEqual([]); + }); + + await act(async () => { + memberActionList.forEach(memberAction => { + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + }); + + await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); + + await waitFor(() => { + expect(result.current.deleteMemberActionList.aliveActionList).toHaveLength(0); + }); + }); + + it('삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 처음의 상태로 돌려놓는다.', async () => { + /** + * 이 테스트는 deleteMemberAction을 실행했을 때 오류가 나는 경우를 테스트하기 위해 작성되었습니다. + * 여기서 사용하는 stepList 목데이터는 999 actionId를 가진 MemberAction이 있는 데이터입니다. + * 999 actionId는 현재 모킹되어있는 msw에서 오류를 뱉도록 하는 id입니다. 이는 오류 상황을 시연하기 위한 임의 모킹입니다. + * (999가 아닌 경우는 모두 정상 응답 반환) + */ + + // 999 actionId를 가진 MemberAction이 있는 stepListJson 데이터를 사용해 MemberActions []으로 정제합니다. + const invalidMemberStepListMockData = invalidMemberStepListJson as (BillStep | MemberStep)[]; + let memberActionList: MemberAction[] = []; + + for (let i = 0; i < invalidMemberStepListMockData.length; i++) { + const curAction = invalidMemberStepListMockData[i]; + if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); + } + + // 오류 멤버가 포함된 memberAction[]을 useDeleteMemberAction의 초기값으로 주입합니다. + const {result} = initializeProvider(memberActionList); + + // stepList 값이 채워지길 대기합니다. + await waitFor(() => { + expect(result.current.stepListResult.data).not.toStrictEqual([]); + }); + + await act(async () => { + const memberAction = memberActionList[0]; // 현재 0번 참여자는 actionId가 999 이고, 999 actionId는 서버에서 에러를 뱉도록 조작된 상황입니다. + result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); + }); + + await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); + + // 삭제 요청에서 오류가 발생했기 때문에 aliveActionList를 초기에 주입했던 값으로 다시 돌려놓는지 확인합니다. + expect(result.current.deleteMemberActionList.aliveActionList).toStrictEqual(memberActionList); + }); +}); diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx new file mode 100644 index 000000000..913087a59 --- /dev/null +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx @@ -0,0 +1,86 @@ +import type {MemberAction} from 'types/serviceType'; + +import {useState} from 'react'; + +import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import useRequestDeleteMemberAction from '@hooks/queries/useRequestDeleteMemberAction'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +type UseDeleteMemberActionProps = { + memberActionList: MemberAction[]; + setIsBottomSheetOpened: React.Dispatch>; + showToastAlreadyExistMemberAction: () => void; + showToastExistSameMemberFromAfterStep: (name: string) => void; +}; + +const useDeleteMemberAction = ({ + memberActionList, + setIsBottomSheetOpened, + showToastAlreadyExistMemberAction, + showToastExistSameMemberFromAfterStep, +}: UseDeleteMemberActionProps) => { + const {data: stepListData} = useRequestGetStepList(); + const stepList = stepListData ?? []; + const {mutate: deleteMemberActionMutate} = useRequestDeleteMemberAction(); + + const [deleteActionList, setDeleteActionList] = useState([]); + + const eventId = getEventIdByUrl(); + + const deleteMemberAction = async (actionId: number) => { + deleteMemberActionMutate( + {actionId}, + { + onError: () => { + setDeleteActionList([]); + }, + }, + ); + setIsBottomSheetOpened(false); + }; + + // TODO: (@cookie: 추후에 반복문으로 delete하는 것이 아니라 한 번에 모아서 delete 처리하기 (backend에 문의)) + const deleteMemberActionList = async () => { + for (const {actionId} of deleteActionList) { + await deleteMemberAction(actionId); + } + }; + + const checkAlreadyExistMemberAction = (memberAction: MemberAction, showToast: () => void) => { + if (!memberActionList.includes(memberAction)) { + showToast(); + } + }; + + const checkExistSameMemberFromAfterStep = (memberAction: MemberAction, showToast: () => void) => { + if (isExistSameMemberFromAfterStep(memberAction)) { + showToast(); + } + }; + + const addDeleteMemberAction = (memberAction: MemberAction) => { + checkAlreadyExistMemberAction(memberAction, showToastAlreadyExistMemberAction); + checkExistSameMemberFromAfterStep(memberAction, () => showToastExistSameMemberFromAfterStep(memberAction.name)); + setDeleteActionList(prev => [...prev, memberAction]); + }; + + const isExistSameMemberFromAfterStep = (memberAction: MemberAction) => { + const memberActionList = stepList + .filter(step => step.type !== 'BILL') + .map(({actions}) => actions) + .flat(); + const currentActionIndex = memberActionList.findIndex(action => action.actionId === memberAction.actionId); + const memberActionListAfterCurrentAction = memberActionList.slice(Math.max(currentActionIndex - 1, 0)); + const memberNameList = memberActionListAfterCurrentAction.map(({name}) => name); + + return memberNameList.filter(member => member === memberAction.name).length >= 2; + }; + + const aliveActionList = memberActionList.filter( + memberAction => !deleteActionList.some(deleteAction => deleteAction.actionId === memberAction.actionId), + ); + return {aliveActionList, deleteMemberActionList, addDeleteMemberAction}; +}; + +export default useDeleteMemberAction; diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx new file mode 100644 index 000000000..452add193 --- /dev/null +++ b/client/src/hooks/useDynamicInput.tsx @@ -0,0 +1,142 @@ +import {useEffect, useRef} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; + +import useInput from './useInput'; + +type InputValue = { + value: string; + index: number; +}; + +export type ReturnUseDynamicInput = { + inputList: InputValue[]; + inputRefList: React.MutableRefObject<(HTMLInputElement | null)[]>; + errorMessage: string | null; + canSubmit: boolean; + errorIndexList: number[]; + handleChange: (index: number, value: string) => void; + handleInputChange: (index: number, event: React.ChangeEvent) => void; + deleteEmptyInputElementOnBlur: () => void; + getFilledInputList: (list?: InputValue[]) => InputValue[]; + focusNextInputOnEnter: (e: React.KeyboardEvent, index: number) => void; + setInputValueTargetIndex: (index: number, value: string) => void; + resetInputValue: () => void; +}; + +const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { + const initialInputList = [{index: 0, value: ''}]; + const inputRefList = useRef<(HTMLInputElement | null)[]>([]); + + const {inputList, errorMessage, errorIndexList, canSubmit, handleChange, setInputList} = useInput({ + validateFunc, + initialInputList, + }); + + useEffect(() => { + if (inputRefList.current.length <= 0) return; + + const lastInput = inputRefList.current[inputRefList.current.length - 1]; + + if (lastInput) { + lastInput.scrollIntoView({behavior: 'smooth', block: 'center'}); + } + }, [inputList]); + + const handleInputChange = (index: number, event: React.ChangeEvent) => { + const {value} = event.target; + + makeNewInputWhenFirstCharacterInput(index, value); + handleChange(index, value); + }; + + const makeNewInputWhenFirstCharacterInput = (index: number, value: string) => { + if (isLastInputFilled(index, value) && value.trim().length !== 0) { + // 마지막 인풋이 한 자라도 채워진다면 새로운 인풋을 생성해 간편한 다음 입력을 유도합니다. + setInputList(prevInputs => { + const updatedInputList = [...prevInputs]; + + // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 + const newIndex = updatedInputList[updatedInputList.length - 1].index + 1; + + return [...updatedInputList, {index: newIndex, value: ''}]; + }); + } + }; + + const deleteEmptyInputElementOnBlur = () => { + // 0, 1번 input이 값이 있는 상태에서 두 input의 값을 모두 x버튼으로 제거해도 input이 2개 남아있는 문제를 위해 조건문을 추가했습니다. + if (getFilledInputList().length === 0 && inputList.length > 1) { + setInputList([{index: 0, value: ''}]); + return; + } + + // *표시 조건문은 처음에 input을 클릭했다가 블러시켰을 때 filledInputList가 아예 없어 .index에 접근할 때 오류가 납니다. 이를 위한 얼리리턴을 두었습니다. + if (getFilledInputList().length === 0) return; + + if (getFilledInputList().length !== inputList.length) { + setInputList(inputList => { + const filledInputList = getFilledInputList(inputList); + + // 새 입력의 인덱스를 inputs 길이를 기준으로 설정 + const newIndex = filledInputList[filledInputList.length - 1].index + 1; + + return [...filledInputList, {index: newIndex, value: ''}]; + }); + } + }; + + const setInputValueTargetIndex = (index: number, value: string) => { + setInputList(prevInputs => { + const updatedInputList = [...prevInputs]; + const targetInput = findInputByIndex(index, updatedInputList); + + targetInput.value = value; + + return updatedInputList; + }); + }; + + const resetInputValue = () => { + setInputList(initialInputList); + }; + + const focusNextInputOnEnter = (e: React.KeyboardEvent, index: number) => { + if (e.nativeEvent.isComposing) return; + + if (e.key === 'Enter') { + inputRefList.current[index + 1]?.focus(); + } + }; + + const findInputByIndex = (index: number, list?: InputValue[]) => { + return (list ?? inputList).filter(input => input.index === index)[0]; + }; + + const getFilledInputList = (list?: InputValue[]) => { + return (list ?? inputList).filter(({value}) => value.trim().length !== 0); + }; + + const isLastInputFilled = (index: number, value: string) => { + const lastInputIndex = inputList[inputList.length - 1].index; + + return value !== '' && index === lastInputIndex; + }; + + return { + inputList, + inputRefList, + errorMessage, + canSubmit, + errorIndexList, + handleInputChange, + handleChange, + deleteEmptyInputElementOnBlur, + getFilledInputList, + focusNextInputOnEnter, + setInputValueTargetIndex, + resetInputValue, + }; +}; + +export default useDynamicInput; diff --git a/client/src/hooks/useEventLogin.ts b/client/src/hooks/useEventLogin.ts new file mode 100644 index 000000000..ccabe20c1 --- /dev/null +++ b/client/src/hooks/useEventLogin.ts @@ -0,0 +1,42 @@ +import {useState} from 'react'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import RULE from '@constants/rule'; + +import useRequestPostLogin from './queries/useRequestPostLogin'; + +const useEventLogin = () => { + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(null); + const [canSubmit, setCanSubmit] = useState(false); + const {mutate: postLogin} = useRequestPostLogin(); + + const submitPassword = async (event: React.FormEvent) => { + event.preventDefault(); + + postLogin({password}, {onError: () => setErrorMessage('비밀번호가 틀렸어요')}); + }; + + const handleChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + setErrorMessage(validation.errorMessage); + + if (validation.isValid) { + setPassword(newValue); + } + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + }; + + return { + password, + errorMessage, + handleChange, + canSubmit, + submitPassword, + }; +}; + +export default useEventLogin; diff --git a/client/src/hooks/useInput.tsx b/client/src/hooks/useInput.tsx new file mode 100644 index 000000000..a6901573b --- /dev/null +++ b/client/src/hooks/useInput.tsx @@ -0,0 +1,97 @@ +import {useEffect, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; + +export type InputValue = { + value: string; + index?: number; +}; + +export type UseInputReturn = { + inputList: T[]; + errorMessage: string; + errorIndexList: number[]; + canSubmit: boolean; + handleChange: (index: number, value: string) => void; + setInputList: React.Dispatch>; + addErrorIndex: (index: number) => void; + setCanSubmit: React.Dispatch>; +}; + +type UseInputProps = { + validateFunc: (value: string) => ValidateResult; + initialInputList: T[]; +}; + +const useInput = ({validateFunc, initialInputList}: UseInputProps): UseInputReturn => { + const [inputList, setInputList] = useState(initialInputList); + const [errorMessage, setErrorMessage] = useState(''); + const [errorIndexList, setErrorIndexList] = useState([]); + const [canSubmit, setCanSubmit] = useState(false); + + useEffect(() => { + changeCanSubmit(); + }, [errorMessage, errorIndexList]); + + useEffect(() => { + setInputList(prev => prev.map((value, index) => ({...value, index}))); + }, [inputList.length]); + + const handleChange = (index: number = 0, value: string) => { + const {isValid, errorMessage: validationResultMessage} = validateFunc(value); + + if (validationResultMessage === ERROR_MESSAGE.preventEmpty) { + setErrorMessage(validationResultMessage); + updateInputList(index, value); + addErrorIndex(index); + } else if (isValid && value.length !== 0) { + // TODO: (@soha) 쿠키가 작업한 errorMessage를 위로 올리기 변경 추후에 merge후에 반영하기 + setErrorMessage(''); + updateInputList(index, value); + removeErrorIndex(index); + } + }; + + const updateInputList = (index: number, value: string) => { + setInputList(prev => { + const newList = [...prev]; + const targetInput = newList.find(input => input.index === index); + if (targetInput) { + targetInput.value = value; + } + return newList; + }); + }; + + const removeErrorIndex = (index: number) => { + setErrorIndexList(prev => prev.filter(i => i !== index)); + }; + + const addErrorIndex = (index: number) => { + setErrorIndexList(prev => { + if (!prev.includes(index)) { + return [...prev, index]; + } + return prev; + }); + }; + + const changeCanSubmit = () => { + setCanSubmit(errorIndexList.length || errorMessage.length ? false : true); + }; + + return { + inputList, + errorMessage, + errorIndexList, + canSubmit, + handleChange, + setInputList, + addErrorIndex, + setCanSubmit, + }; +}; + +export default useInput; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx new file mode 100644 index 000000000..9c9cd80d9 --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx @@ -0,0 +1,89 @@ +import type {MemberReportInAction} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import validateMemberReportInAction from '@utils/validate/validateMemberReportInAction'; + +type MemberReportInput = MemberReportInAction & { + index: number; +}; + +type UseMemberReportProps = { + data: MemberReportInAction[]; + addAdjustedMember: (memberReport: MemberReportInAction) => void; + getOnlyOneNotAdjustedRemainMemberIndex: () => number | null; + getIsSamePriceStateAndServerState: () => boolean; + totalPrice: number; +}; + +const useMemberReportInput = ({ + data, + addAdjustedMember, + totalPrice, + getOnlyOneNotAdjustedRemainMemberIndex, + getIsSamePriceStateAndServerState, +}: UseMemberReportProps) => { + const [inputList, setInputList] = useState(data.map((item, index) => ({...item, index}))); + const [canSubmit, setCanSubmit] = useState(false); + + const [canEditList, setCanEditList] = useState([]); + + const onChange = (event: React.ChangeEvent, index: number) => { + const {value} = event.target; + + validateAndAddAdjustedMember(value, index); + }; + + const validateAndAddAdjustedMember = (price: string, index: number) => { + const {isValid} = validateMemberReportInAction(price, totalPrice); + + if (isValid) { + const newInputList = [...inputList]; + newInputList[index].price = Number(price); + setInputList(newInputList); + + const memberReportData: MemberReportInAction = { + name: newInputList[index].name, + price: newInputList[index].price, + isFixed: newInputList[index].isFixed, + }; + addAdjustedMember(memberReportData); + } + }; + + // 서버와 값이 같지 않고 input price의 상태가 모두 valid하다면 can submit true + useEffect(() => { + const isSamePriceState = getIsSamePriceStateAndServerState(); + const isAllValid = inputList.every(input => validateMemberReportInAction(String(input.price), totalPrice)); + + setCanSubmit(!isSamePriceState && isAllValid); + }, [inputList]); + + // addAdjustedMember로 인해 data가 변했을 때 input list의 값을 맞춰주기 위함 + useEffect(() => { + setCanSubmit(!getIsSamePriceStateAndServerState()); + setInputList(data.map((item, index) => ({...item, index}))); + + // 남은 인원이 1명일 때 수정을 불가능하도록 설정 + const onlyOneIndex = getOnlyOneNotAdjustedRemainMemberIndex(); + + if (data.length !== 0) { + setCanEditList(new Array(data.length).fill(true)); + } + + if (onlyOneIndex !== null) { + const newCanEditList = new Array(data.length).fill(true); + newCanEditList[onlyOneIndex] = false; + setCanEditList(newCanEditList); + } + }, [data]); + + return { + inputList, + onChange, + canEditList, + canSubmit, + }; +}; + +export default useMemberReportInput; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx new file mode 100644 index 000000000..78c29ee03 --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx @@ -0,0 +1,327 @@ +import type {MemberReportInAction} from 'types/serviceType'; + +import {renderHook, waitFor, act} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; +import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; + +import memberReportListInActionJson from '../../mocks/memberReportListInAction.json'; + +import useMemberReportListInAction from './useMemberReportListInAction'; + +describe('useMemberReportListInActionTest', () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: 0, + }, + }, + }); + + const initializeProvider = (actionId: number, totalPrice: number) => + renderHook(() => useMemberReportListInAction(actionId, totalPrice, () => {}), { + wrapper: ({children}) => ( + + {children} + + ), + }); + + const actionId = 123; + const totalPrice = 100000; + + describe('Flow: 유저가 정상적으로 값을 불러왔을 때의 test', () => { + it('초기값을 정상적으로 불러온다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + expect(result.current.memberReportListInAction).toStrictEqual(memberReportListInActionJson); + }); + + it('망쵸의 가격을 100원으로 바꾸면 망쵸의 가격은 100원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMember: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMember); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + + expect(targetMember?.price).toBe(100); + }); + + it('망쵸의 가격을 100원으로 바꾸면 망쵸의 가격은 100원으로 설정되고 나머지 인원의 가격이 33,300원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMember: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMember); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMember?.price).toBe(100); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(33300); + }); + }); + + it('망쵸의 가격을 100원 쿠키의 가격을 100원으로 바꾸면 나머지 인원의 가격이 49,900원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => !(member.name === '망쵸' || member.name === '쿠키'), + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(49900); + }); + }); + + it('망쵸의 가격을 100원 쿠키의 가격을 100원으로 바꾸면 나머지 인원의 가격이 49,900원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => !(member.name === '망쵸' || member.name === '쿠키'), + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(49900); + }); + }); + + it('망쵸의 가격을 100원으로 바꾸고 다시 망쵸의 가격을 10,000원으로 바꾸면 나머지 인원의 가격이 30,000원으로 설정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberMangchoAfter: MemberReportInAction = {name: '망쵸', price: 10000, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoAfter); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(30000); + }); + }); + }); + + describe('예외 & 엣지케이스', () => { + it('동일한 인원의 가격을 동일하게 바꾸면 변함없다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember({...adjustedMemberMangcho, isFixed: true}); + }); + + const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); + + expect(anotherMemberList[0].price).toBe(33300); + }); + + it('망쵸에게 300원을 주면 나머지 사람들은 33233원이고 마지막 사람은 33234원이 된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 300, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMember?.price).toBe(300); + + const anotherMemberList = result.current.memberReportListInAction.filter( + member => member.name === '이상' || member.name === '소하', + ); + + anotherMemberList.forEach(member => { + expect(member.price).toBe(33233); + }); + + const lastMember = result.current.memberReportListInAction.find(member => member.name === '쿠키'); + + expect(lastMember?.price).toBe(33234); + }); + + it('망쵸, 쿠키의 가격을 100원으로 바꾼 후 다시 쿠키의 가격을 33000원으로 바꾸면 쿠키의 isFixed는 false가 된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; + const adjustedMemberCookieReset: MemberReportInAction = {name: '쿠키', price: 33300, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookie); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '쿠키'); + + expect(targetMember?.isFixed).toBe(true); + + act(() => { + result.current.addAdjustedMember(adjustedMemberCookieReset); + }); + + const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '쿠키'); + + expect(targetMemberReset?.isFixed).toBe(false); + }); + + it('망쵸의 가격을 100원으로 바꾼 후 다시 망쵸의 가격을 25000원으로 바꾸면 망쵸의 isFixed는 false가 된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberMangchoAfter: MemberReportInAction = {name: '망쵸', price: 25000, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMember?.isFixed).toBe(true); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoAfter); + }); + + const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMemberReset?.isFixed).toBe(false); + }); + + it('아무도 조정된 값이 없다면 조정값이 있는지 확인 결과 false다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + expect(result.current.isExistAdjustedPrice()).toBe(false); + }); + + it('망쵸의 가격을 100원으로 바꾼 후 리스트 중 조정값이 있는지 확인 결과 true다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + expect(result.current.isExistAdjustedPrice()).toBe(true); + }); + }); + + describe('지출 인원이 2명인 상황', () => { + const actionId = 1; + const totalPrice = 50000; + + // 망쵸 이상 + it('망쵸의 가격을 100원으로 수정한 경우, 이상의 가격이 49900원으로 수정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); + + expect(targetMember?.price).toBe(49900); + }); + + it('망쵸의 가격을 100원으로 수정하고 다시 200원으로 수정한 경우, 이상의 가격이 49800원으로 수정된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + const adjustedMemberMangchoOther: MemberReportInAction = {name: '망쵸', price: 200, isFixed: true}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangchoOther); + }); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); + + expect(targetMember?.price).toBe(49800); + }); + }); + + // last + describe('onSubmit 실행 시 반영 테스트', () => { + it('망쵸의 가격을 100원으로 바꾸고 저장하면 망쵸 100원이 반영된다.', async () => { + const {result} = initializeProvider(actionId, totalPrice); + const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + act(() => { + result.current.addAdjustedMember(adjustedMemberMangcho); + }); + + await waitFor(() => { + result.current.onSubmit(); + }); + + await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); + + const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); + expect(targetMember?.price).toBe(100); + }); + }); +}); diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts new file mode 100644 index 000000000..0e32d740c --- /dev/null +++ b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts @@ -0,0 +1,156 @@ +import type {MemberReportInAction} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import useRequestGetMemberReportListInAction from '@hooks/queries/useRequestGetMemberReportListInAction'; +import useRequestPutMemberReportListInAction from '@hooks/queries/useRequestPutMemberReportListInAction'; + +const useMemberReportListInAction = (actionId: number, totalPrice: number, onClose: () => void) => { + const {memberReportListInActionFromServer, queryResult} = useRequestGetMemberReportListInAction(actionId); + const {putMemberReportListInAction} = useRequestPutMemberReportListInAction(actionId); + + const [memberReportListInAction, setMemberReportListInAction] = useState( + memberReportListInActionFromServer, + ); + + // isFixed를 모두 풀고 계산값으로 모두 처리하는 기능 + const reCalculatePriceByTotalPriceChange = () => { + const {divided, remainder} = calculateDividedPrice(memberReportListInAction.length, 0); + + const resetMemberReportList = [...memberReportListInAction]; + resetMemberReportList.forEach((member, index) => { + if (index !== resetMemberReportList.length - 1) { + member.price = divided; + } else { + member.price = divided + remainder; + } + member.isFixed = false; + }); + + setMemberReportListInAction(resetMemberReportList); + }; + + // 총 금액이 변동됐을 때 (서버에서 온 값과 다를 때) 재계산 실행 + useEffect(() => { + const totalPriceFromServer = memberReportListInActionFromServer.reduce((acc, cur) => acc + cur.price, 0); + + if (totalPriceFromServer !== totalPrice && totalPriceFromServer !== 0) { + reCalculatePriceByTotalPriceChange(); + } + }, [totalPrice, memberReportListInActionFromServer]); + + useEffect(() => { + if (queryResult.isSuccess) { + setMemberReportListInAction(memberReportListInActionFromServer); + } + }, [memberReportListInActionFromServer, queryResult.isSuccess]); + + const isExistAdjustedPrice = () => { + return memberReportListInAction.some(member => member.isFixed === true); + }; + + // 조정되지 않은 인원이 단 1명인 경우의 index + const getOnlyOneNotAdjustedRemainMemberIndex = (): number | null => { + const adjustedPriceCount = getAdjustedMemberCount(memberReportListInAction); + + if (adjustedPriceCount < memberReportListInAction.length - 1) return null; + + return memberReportListInAction.findIndex(member => member.isFixed === false); + }; + + // 조정값 멤버의 수를 구하는 함수 + const getAdjustedMemberCount = (memberReportListInAction: MemberReportInAction[]) => { + return memberReportListInAction.filter(member => member.isFixed === true).length; + }; + + const addAdjustedMember = (memberReport: MemberReportInAction) => { + const newMemberReportListInAction = memberReportListInAction.map(member => + member.name === memberReport.name ? {...member, price: memberReport.price, isFixed: true} : member, + ); + + calculateAnotherMemberPrice(newMemberReportListInAction); + }; + + const calculateDividedPrice = (remainMemberCount: number, totalAdjustedPrice: number) => { + return { + divided: Math.floor((totalPrice - totalAdjustedPrice) / remainMemberCount), + remainder: (totalPrice - totalAdjustedPrice) % remainMemberCount, + }; + }; + + // 계산값으로 값을 변경했을 때 isFixed를 푸는 함수 + // 100 true 33300 true 33300 false 33300 false + const setIsFixedFalseAtResetToDividedPrice = (memberReportListInAction: MemberReportInAction[], divided: number) => { + return memberReportListInAction.map(memberReport => { + if (memberReport.isFixed === true && memberReport.price === divided) { + return {...memberReport, isFixed: false}; + } + + return memberReport; + }); + }; + + const calculateAnotherMemberPrice = (memberReportListInAction: MemberReportInAction[]) => { + // 총 조정치 금액 + const totalAdjustedPrice = memberReportListInAction + .filter(memberReport => memberReport.isFixed === true) + .reduce((acc, cur) => acc + cur.price, 0); + + const remainMemberCount = memberReportListInAction.length - getAdjustedMemberCount(memberReportListInAction); + const {divided, remainder} = calculateDividedPrice(remainMemberCount, totalAdjustedPrice); + + const updatedList = memberReportListInAction.map(member => + member.isFixed === true ? member : {...member, price: divided}, + ); + + // 나머지를 조정되지 않은 멤버 중 마지막 멤버에게 추가 + if (remainder !== 0) { + const nonAdjustedMembers = updatedList.filter(member => member.isFixed === false); + const lastNonAdjustedMemberIndex = updatedList.findIndex( + member => member.name === nonAdjustedMembers[nonAdjustedMembers.length - 1].name, + ); + + if (lastNonAdjustedMemberIndex !== -1) { + updatedList[lastNonAdjustedMemberIndex].price += remainder; + } + } + + // 조정됐지만 계산값으로 가격이 변한 경우 fixed 상태를 풀어야한다. + const result = setIsFixedFalseAtResetToDividedPrice(updatedList, divided); + setMemberReportListInAction(result); + }; + + const onSubmit = () => { + putMemberReportListInAction(memberReportListInAction); + + onClose(); + }; + + const getIsSamePriceStateAndServerState = () => { + const serverStatePriceList = memberReportListInActionFromServer.map(({price}) => price); + const clientStatePriceList = memberReportListInAction.map(({price}) => price); + + let isSame = true; + + // isArrayEqual을 사용하지 않은 이유는 정렬이 영향을 받으면 안 되기 때문입니다 + for (let i = 0; i < serverStatePriceList.length; i++) { + if (serverStatePriceList[i] !== clientStatePriceList[i]) { + isSame = false; + } + } + + return isSame; + }; + + return { + memberReportListInAction, + addAdjustedMember, + isExistAdjustedPrice, + onSubmit, + getOnlyOneNotAdjustedRemainMemberIndex, + getIsSamePriceStateAndServerState, + queryResult, + }; +}; + +export default useMemberReportListInAction; diff --git a/client/src/hooks/useNavSwitch.tsx b/client/src/hooks/useNavSwitch.tsx new file mode 100644 index 000000000..a622a7a30 --- /dev/null +++ b/client/src/hooks/useNavSwitch.tsx @@ -0,0 +1,42 @@ +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; + +const PATH_TABLE: Record = { + 홈: 'home', + 관리: 'admin', +}; + +const PATH_DISPLAY_TABLE: Record = { + home: '홈', + admin: '관리', +}; + +const useNavSwitch = () => { + const paths = ['홈', '관리']; + const location = useLocation(); + const navigate = useNavigate(); + + const pathArray = location.pathname.split('/'); + const basePath = pathArray.slice(0, -1).join('/'); + const lastPath = pathArray[pathArray.length - 1]; + + const [nav, setNav] = useState(PATH_DISPLAY_TABLE[lastPath]); + + useEffect(() => { + const isLogin = lastPath === 'login'; + setNav(isLogin ? '관리' : PATH_DISPLAY_TABLE[lastPath]); + }, [location]); + + const onChange = (displayName: string) => { + setNav(displayName); + navigate(`${basePath}/${PATH_TABLE[displayName]}`); + }; + + return { + nav, + paths, + onChange, + }; +}; + +export default useNavSwitch; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts new file mode 100644 index 000000000..6f1e4feaf --- /dev/null +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -0,0 +1,113 @@ +import type {Bill, BillInputType, InputPair} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; + +import usePutBillAction from './queries/useRequestPutBillAction'; +import useDeleteBillAction from './queries/useRequestDeleteBillAction'; + +const usePutAndDeleteBillAction = ( + initialValue: InputPair, + validateFunc: (inputPair: Bill) => ValidateResult, + onClose: () => void, +) => { + const [inputPair, setInputPair] = useState(initialValue); + const [canSubmit, setCanSubmit] = useState(false); + const [errorInfo, setErrorInfo] = useState>({title: false, price: false}); + const [errorMessage, setErrorMessage] = useState(null); + + const {mutateAsync: putBillAction} = usePutBillAction(); + const {mutate: deleteBillAction} = useDeleteBillAction(); + + // 현재 타겟의 event.target.value를 넣어주기 위해서 + const getFieldValue = (field: BillInputType, value: string) => { + if (field === 'title') { + return {title: value, price: Number(inputPair.price)}; + } else { + return {title: inputPair.title, price: Number(value)}; + } + }; + + // TODO: (@weadie) getFieldValue 를 리펙토링해야한다. + + const handleInputChange = (field: BillInputType, event: React.ChangeEvent) => { + const {value} = event.target; + + const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue(field, value)); + + setErrorMessage(errorMessage); + + if (isValid) { + // valid일 경우 에러메시지 nope, setValue, submit은 value가 비지 않았을 때 true를 설정 + setInputPair(prevInputPair => { + return { + ...prevInputPair, + [field]: value, + }; + }); + setCanSubmit(value.length !== 0); + } else { + const {isValid: isValidName} = validateFunc(getFieldValue('title', inputPair.title)); + const {isValid: isValidPrice} = validateFunc(getFieldValue('price', inputPair.price)); + + setCanSubmit(isValidName && isValidPrice); + // valid하지 않으면 event.target.value 덮어쓰기 + event.target.value = inputPair[field]; + } + + if (field === 'title') { + // 현재 field가 title일 때는 title의 errorInfo만 반영해줌 (blur에서도 errorInfo를 조작하기 때문) + setErrorInfo(prev => ({title: errorInfo?.title ?? false, price: prev.price})); + } else { + setErrorInfo(prev => ({title: prev.title, price: errorInfo?.price ?? false})); + } + }; + + const handleOnBlur = () => { + const {isValid, errorMessage, errorInfo} = validateFunc({title: inputPair.title, price: Number(inputPair.price)}); + + // blur시 값이 비었을 때 error state 반영 + if (inputPair.price.length === 0 || inputPair.title.length === 0) { + setErrorMessage(ERROR_MESSAGE.preventEmpty); + setErrorInfo({title: inputPair.title.length === 0, price: inputPair.price.length === 0}); + setCanSubmit(false); + return; + } + + // 이외 blur시에 추가로 검증함 + setErrorMessage(errorMessage); + setCanSubmit(isValid); + setErrorInfo(errorInfo ?? {title: false, price: false}); + }; + + const onSubmit = async (event: React.FormEvent, inputPair: InputPair, actionId: number) => { + event.preventDefault(); + + const {title, price} = inputPair; + + await putBillAction({actionId, title, price: Number(price)}); + + onClose(); + }; + + const onDelete = async (actionId: number) => { + deleteBillAction({actionId}); + onClose(); + }; + + return { + inputPair, + handleInputChange, + handleOnBlur, + onSubmit, + onDelete, + canSubmit, + errorMessage, + errorInfo, + }; +}; + +export default usePutAndDeleteBillAction; diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts new file mode 100644 index 000000000..09f227b8e --- /dev/null +++ b/client/src/hooks/useSearchInMemberList.ts @@ -0,0 +1,54 @@ +import {useState} from 'react'; + +import useRequestGetCurrentInMemberList from './queries/useRequestGetCurrentInMemberList'; + +export type ReturnUseSearchInMemberList = { + currentInputIndex: number; + handleCurrentInputIndex: (inputIndex: number) => void; + filteredInMemberList: string[]; + searchCurrentInMember: (event: React.ChangeEvent) => void; + chooseMember: (inputIndex: number, name: string) => void; +}; + +const useSearchInMemberList = (handleChange: (index: number, value: string) => void): ReturnUseSearchInMemberList => { + const [currentInputIndex, setCurrentInputIndex] = useState(-1); + + // 서버에서 가져온 전체 리스트 + const {data} = useRequestGetCurrentInMemberList(); + const currentInMemberList = data?.memberNames ?? []; + + // 검색된 리스트 (따로 둔 이유는 검색 후 클릭했을 때 리스트를 비워주어야하기 때문) + const [filteredInMemberList, setFilteredInMemberList] = useState>([]); + + const filterMatchItems = (keyword: string) => { + if (keyword.trim() === '') return []; + + return currentInMemberList + .filter(member => member.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1) + .slice(0, 3); + }; + + const chooseMember = (inputIndex: number, name: string) => { + setFilteredInMemberList([]); + handleChange(inputIndex, name); + }; + + const searchCurrentInMember = (event: React.ChangeEvent) => { + const {value} = event.target; + setFilteredInMemberList(filterMatchItems(value)); + }; + + const handleCurrentInputIndex = (inputIndex: number) => { + setCurrentInputIndex(inputIndex); + }; + + return { + currentInputIndex, + handleCurrentInputIndex, + filteredInMemberList, + searchCurrentInMember, + chooseMember, + }; +}; + +export default useSearchInMemberList; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx new file mode 100644 index 000000000..90782cbdf --- /dev/null +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx @@ -0,0 +1,41 @@ +import {renderHook, waitFor} from '@testing-library/react'; +import {MemoryRouter} from 'react-router-dom'; + +import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; +import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; +import {ToastProvider} from '@hooks/useToast/ToastProvider'; + +import reportListJson from '../../mocks/reportList.json'; + +import useSearchMemberReportList from './useSearchMemberReportList'; + +describe('useSearchMemberReportList', () => { + const initializeProvider = (name: string) => + renderHook(() => useSearchMemberReportList({name}), { + wrapper: ({children}) => ( + + + + {children} + + + + ), + }); + + it('빈 값을 검색한다면 검색 목록은 비어있다.', async () => { + const {result} = initializeProvider(''); + + await waitFor(() => expect(result.current.memberReportSearchList).toStrictEqual(reportListJson)); + }); + + it('검색어의 일부와 일치하는 이름이 있다면 해당 이름을 목록에 반환한다.', async () => { + const keyword = '소'; + const {result} = initializeProvider(keyword); + const expectedMemberReportSearchList = reportListJson.filter(memberReport => memberReport.name.includes(keyword)); + + await waitFor(() => { + expect(result.current.memberReportSearchList).toStrictEqual(expectedMemberReportSearchList); + }); + }); +}); diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx new file mode 100644 index 000000000..4a967e45c --- /dev/null +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -0,0 +1,16 @@ +import useRequestGetMemberReportList from '@hooks/queries/useRequestGetMemberReportList'; + +type UseSearchMemberReportListParams = { + name: string; +}; + +const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { + const {data} = useRequestGetMemberReportList(); + const memberReportList = data ?? []; + + return { + memberReportSearchList: memberReportList.filter(memberReport => memberReport.name.includes(name)), + }; +}; + +export default useSearchMemberReportList; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx new file mode 100644 index 000000000..02241d3e3 --- /dev/null +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -0,0 +1,100 @@ +import {useEffect, useState} from 'react'; + +import {ValidateResult} from '@utils/validate/type'; +import {MemberChange} from '@apis/request/member'; + +import isArraysEqual from '@utils/isArraysEqual'; + +import useDeleteAllMemberList from './queries/useRequestDeleteAllMemberList'; +import usePutAllMemberList from './queries/useRequestPutAllMemberList'; +import useInput from './useInput'; + +interface UseSetAllMemberListProps { + validateFunc: (name: string) => ValidateResult; + allMemberList: string[]; + handleCloseAllMemberListModal: () => void; +} + +interface UseSetAllMemberListReturns { + editedAllMemberList: string[]; + canSubmit: boolean; + errorMessage: string; + errorIndexList: number[]; + handleNameChange: (index: number, event: React.ChangeEvent) => void; + handleClickDeleteButton: (index: number) => Promise; + handlePutAllMemberList: () => Promise; +} + +const useSetAllMemberList = ({ + validateFunc, + allMemberList, + handleCloseAllMemberListModal, +}: UseSetAllMemberListProps): UseSetAllMemberListReturns => { + const initialInputList = allMemberList.map((name, index) => ({index, value: name})); + const { + inputList, + errorMessage, + errorIndexList, + canSubmit, + handleChange, + setInputList: setEditedAllMemberList, + setCanSubmit, + } = useInput({validateFunc, initialInputList}); + + const [deleteInOriginal, setDeleteInOriginal] = useState(allMemberList); + const [deleteMemberList, setDeleteMemberList] = useState([]); + + const {mutateAsync: deleteAllMemberList} = useDeleteAllMemberList(); + const {mutate: putAllMemberList} = usePutAllMemberList(); + + const editedAllMemberList = inputList.map(input => input.value); + + useEffect(() => { + setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); + }, [editedAllMemberList]); + + const handleNameChange = (index: number, event: React.ChangeEvent) => { + const {value} = event.target; + + handleChange(index, value); + }; + + const handleClickDeleteButton = async (index: number) => { + const memberToDelete = editedAllMemberList[index]; + + setDeleteMemberList(prev => [...prev, memberToDelete]); + setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); + }; + + const handlePutAllMemberList = async () => { + // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) + if (deleteMemberList.length > 0) { + for (const deleteMember of deleteMemberList) { + await deleteAllMemberList({memberName: deleteMember}); + } + } + + const editedMemberName: MemberChange[] = deleteInOriginal + .map((originalName, index) => { + if (editedAllMemberList[index] !== originalName) { + return {before: originalName, after: editedAllMemberList[index]}; + } + return null; // 조건에 맞지 않으면 null을 반환 + }) + .filter(item => item !== null); // null인 항목을 필터링하여 제거 + if (!isArraysEqual(editedAllMemberList, deleteInOriginal)) putAllMemberList({members: editedMemberName}); + handleCloseAllMemberListModal(); + }; + + return { + editedAllMemberList, + canSubmit, + errorMessage, + errorIndexList, + handleNameChange, + handleClickDeleteButton, + handlePutAllMemberList, + }; +}; +export default useSetAllMemberList; diff --git a/client/src/hooks/useSetBillInput.ts b/client/src/hooks/useSetBillInput.ts new file mode 100644 index 000000000..a14b2a481 --- /dev/null +++ b/client/src/hooks/useSetBillInput.ts @@ -0,0 +1,67 @@ +import {useState} from 'react'; + +import validatePurchase from '@utils/validate/validatePurchase'; +import {Bill, BillInputType} from 'types/serviceType'; + +import useRequestPostBillList from './queries/useRequestPostBillList'; + +interface UseSetBillInputProps { + setIsAddEditableItem: React.Dispatch>; +} + +interface UseSetBillInputReturns { + billInput: Bill; + handleChangeBillInput: (field: BillInputType, event: React.ChangeEvent) => void; + handleBlurBillRequest: () => void; +} + +const useSetBillInput = ({setIsAddEditableItem}: UseSetBillInputProps): UseSetBillInputReturns => { + const initialInput = {title: '', price: 0}; + const [billInput, setBillInput] = useState(initialInput); + + const {mutate: postBillList} = useRequestPostBillList(); + + const handleChangeBillInput = (field: BillInputType, event: React.ChangeEvent) => { + const {value} = event.target; + const {isValid} = validatePurchase({ + ...billInput, + [field]: value, + }); + + if (isValid) { + setBillInput(prev => ({ + ...prev, + [field]: value, + })); + } + }; + + const handleBlurBillRequest = () => { + const isEmptyTitle = billInput.title.trim().length; + const isEmptyPrice = Number(billInput.price); + + // 두 input의 값이 모두 채워졌을 때 api 요청 + // api 요청을 하면 Input을 띄우지 않음 + if (isEmptyTitle && isEmptyPrice) { + postBillList( + {billList: [billInput]}, + { + onSuccess: () => { + setBillInput(initialInput); + setIsAddEditableItem(false); + }, + }, + ); + } else if (!isEmptyTitle && !isEmptyPrice) { + setIsAddEditableItem(false); + } + }; + + return { + billInput, + handleBlurBillRequest, + handleChangeBillInput, + }; +}; + +export default useSetBillInput; diff --git a/client/src/hooks/useSetEventNamePage.ts b/client/src/hooks/useSetEventNamePage.ts new file mode 100644 index 000000000..f5b5bce12 --- /dev/null +++ b/client/src/hooks/useSetEventNamePage.ts @@ -0,0 +1,32 @@ +import {useState} from 'react'; + +import validateEventName from '@utils/validate/validateEventName'; + +const useSetEventNamePage = () => { + const [eventName, setEventName] = useState(''); + const [errorMessage, setErrorMessage] = useState(null); + const [canSubmit, setCanSubmit] = useState(false); + + const handleEventNameChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + const validation = validateEventName(newValue); + + setCanSubmit(newValue.length !== 0); + setErrorMessage(validation.errorMessage); + + if (validation.isValid) { + setEventName(newValue); + } else { + event.target.value = eventName; + } + }; + + return { + eventName, + errorMessage, + canSubmit, + handleEventNameChange, + }; +}; + +export default useSetEventNamePage; diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts new file mode 100644 index 000000000..82ca72fb1 --- /dev/null +++ b/client/src/hooks/useSetEventPasswordPage.ts @@ -0,0 +1,60 @@ +import {useEffect, useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import {ROUTER_URLS} from '@constants/routerUrls'; +import RULE from '@constants/rule'; + +import usePostEvent from './queries/useRequestPostEvent'; + +const useSetEventPasswordPage = () => { + const [eventName, setEventName] = useState(''); + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const navigate = useNavigate(); + const location = useLocation(); + const {mutate: postEvent, isPending: isPostEventPending} = usePostEvent(); + + useEffect(() => { + if (!location.state) { + navigate(ROUTER_URLS.main); + } else { + setEventName(location.state.eventName); + } + }, []); + + const submitPassword = async (event: React.FormEvent) => { + event.preventDefault(); + + postEvent( + {eventName, password: parseInt(password)}, + { + onSuccess: data => { + navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId: data.eventId})}`, { + replace: true, + }); + }, + }, + ); + }; + + const handleChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (validation.isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + + return {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending}; +}; +export default useSetEventPasswordPage; diff --git a/client/src/hooks/useToast/ToastProvider.tsx b/client/src/hooks/useToast/ToastProvider.tsx new file mode 100644 index 000000000..be0d2ea15 --- /dev/null +++ b/client/src/hooks/useToast/ToastProvider.tsx @@ -0,0 +1,47 @@ +/** @jsxImportSource @emotion/react */ +import {createContext, useEffect, useState} from 'react'; + +import {ToastProps} from '../../components/Toast/Toast.type'; +import Toast from '../../components/Toast/Toast'; + +export const ToastContext = createContext(null); + +const DEFAULT_TIME = 3000; + +interface ToastContextProps { + showToast: (args: ShowToast) => void; +} + +type ShowToast = ToastProps & { + showingTime?: number; + isAlwaysOn?: boolean; +}; + +export const ToastProvider = ({children}: React.PropsWithChildren) => { + const [currentToast, setCurrentToast] = useState(null); + + const showToast = ({showingTime = DEFAULT_TIME, isAlwaysOn = false, ...toastProps}: ShowToast) => { + setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); + }; + + const closeToast = () => { + setCurrentToast(null); + }; + + useEffect(() => { + if (currentToast && !currentToast.isAlwaysOn) { + const timer = setTimeout(() => setCurrentToast(null), currentToast.showingTime); + + return () => clearTimeout(timer); + } + + return; + }, [currentToast]); + + return ( + + {currentToast && } + {children} + + ); +}; diff --git a/client/src/hooks/useToast/useToast.test.tsx b/client/src/hooks/useToast/useToast.test.tsx new file mode 100644 index 000000000..f790ba98e --- /dev/null +++ b/client/src/hooks/useToast/useToast.test.tsx @@ -0,0 +1,80 @@ +import {render, renderHook, screen, waitFor} from '@testing-library/react'; +import {act} from 'react'; +import {HDesignProvider} from 'haengdong-design'; + +import {ToastProvider} from './ToastProvider'; // 위 코드에 해당하는 ToastProvider 경로 +import {useToast} from './useToast'; + +const TOAST_CONFIG = { + message: 'Test Toast Message', +}; + +// 테스트용 헬퍼 컴포넌트 +const TestComponent = () => { + const {showToast} = useToast(); + + const handleClick = () => { + showToast(TOAST_CONFIG); + }; + + return ; +}; + +const setup = () => + render( + + + + + , + ); + +describe('ToastProvider', () => { + it('토스트를 띄우고 자동으로 사라지게 한다', async () => { + setup(); + + // 토스트를 띄우기 위해 버튼 클릭 + act(() => { + screen.getByText('Show Toast').click(); + }); + + // 토스트 메시지가 나타나는지 확인 + expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + + // 1초 후에 토스트 메시지가 사라지는지 확인 + await waitFor( + () => { + expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + }, + {timeout: 3100}, + ); // 타임아웃을 3100ms로 설정하여 정확히 3초 후 확인 + }); + + it('토스트 닫기 버튼을 눌렀을 때 사라진다', async () => { + setup(); + + // 토스트를 띄우기 위해 버튼 클릭 + act(() => { + screen.getByText('Show Toast').click(); + }); + + // 토스트 메시지가 나타나는지 확인 + expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + + // 토스트의 닫기 버튼을 클릭 + act(() => { + document.getElementById('toast')?.click(); + }); + + // 닫기 버튼을 클릭한 후 토스트가 사라지는지 확인 + await waitFor(() => { + expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + }); + }); + + it('Provider없이 useToast 사용할 경우 에러를 던진다.', () => { + expect(() => { + const _ = renderHook(() => useToast()); + }).toThrow('useToast는 ToastProvider 내에서 사용되어야 합니다.'); + }); +}); diff --git a/client/src/hooks/useToast/useToast.tsx b/client/src/hooks/useToast/useToast.tsx new file mode 100644 index 000000000..189847405 --- /dev/null +++ b/client/src/hooks/useToast/useToast.tsx @@ -0,0 +1,13 @@ +import {useContext} from 'react'; + +import {ToastContext} from './ToastProvider'; + +export const useToast = () => { + const context = useContext(ToastContext); + + if (!context) { + throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); + } + + return context; +}; diff --git a/client/src/index.tsx b/client/src/index.tsx new file mode 100644 index 000000000..17f98655f --- /dev/null +++ b/client/src/index.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import {RouterProvider} from 'react-router-dom'; +import * as Sentry from '@sentry/react'; + +import router from './router'; + +// async function enableMocking() { +// const {worker} = await import('./mocks/browser'); +// return worker.start(); +// } + +Sentry.init({ + dsn: 'https://81685591a3234c689be8c48959b04c88@o4507739935997952.ingest.us.sentry.io/4507739943272448', + integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], + // Performance Monitoring + tracesSampleRate: 1.0, // Capture 100% of the transactions + // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled + tracePropagationTargets: ['localhost', /^https:\/\/api\.haengdong\.pro/], + // Session Replay + replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production. + replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur. +}); + +// MSW 모킹을 사용하려면 아래 주석을 해제하고 save해주세요. +// enableMocking().then(() => { +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +); +// }); diff --git a/client/src/mocks/browser.ts b/client/src/mocks/browser.ts new file mode 100644 index 000000000..dd8d73b6c --- /dev/null +++ b/client/src/mocks/browser.ts @@ -0,0 +1,5 @@ +import {setupWorker} from 'msw/browser'; + +import {handlers} from './handlers'; + +export const worker = setupWorker(...handlers); diff --git a/client/src/mocks/handlers.ts b/client/src/mocks/handlers.ts new file mode 100644 index 000000000..4189b2d66 --- /dev/null +++ b/client/src/mocks/handlers.ts @@ -0,0 +1,15 @@ +import {authHandler} from './handlers/authHandlers'; +import {eventHandler} from './handlers/eventHandlers'; +import {reportHandlers} from './handlers/reportHandlers'; +import {stepListHandler} from './handlers/stepListHandler'; +import {testHandler} from './handlers/testHandlers'; +import {memberReportInActionHandler} from './handlers/memberReportInActionHandlers'; + +export const handlers = [ + ...authHandler, + ...eventHandler, + ...testHandler, + ...stepListHandler, + ...reportHandlers, + ...memberReportInActionHandler, +]; diff --git a/client/src/mocks/handlers/authHandlers.ts b/client/src/mocks/handlers/authHandlers.ts new file mode 100644 index 000000000..31532eea7 --- /dev/null +++ b/client/src/mocks/handlers/authHandlers.ts @@ -0,0 +1,104 @@ +import {HttpResponse, http} from 'msw'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import {PASSWORD_LENGTH} from '@constants/password'; + +import { + EXPIRED_TOKEN_FOR_TEST, + FORBIDDEN_TOKEN_FOR_TEST, + VALID_PASSWORD_FOR_TEST, + VALID_TOKEN_FOR_TEST, +} from '@mocks/validValueForTest'; + +type PostLoginParams = { + eventId: string; +}; + +type PostLoginRequestBody = { + password: string; +}; + +export const authHandler = [ + http.post(`${TEMP_PREFIX}/:eventId/auth`, ({cookies}) => { + const token = cookies['eventToken']; + + if (token === VALID_TOKEN_FOR_TEST) { + return new HttpResponse(null, { + status: 200, + }); + } else if (token === EXPIRED_TOKEN_FOR_TEST) { + return HttpResponse.json( + { + errorCode: 'TOKEN_EXPIRED', + message: '만료된 토큰입니다.', + }, + {status: 401}, + ); + } else if (token === FORBIDDEN_TOKEN_FOR_TEST) { + return HttpResponse.json( + { + errorCode: 'FORBIDDEN', + message: '접근할 수 없는 행사입니다.', + }, + {status: 401}, + ); + } else if (token === undefined) { + return HttpResponse.json( + { + errorCode: 'TOKEN_NOT_FOUND', + message: '토큰이 존재하지 않습니다.', + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + errorCode: 'TOKEN_INVALID', + message: '유효하지 않은 토큰입니다.', + }, + {status: 401}, + ); + } + }), + + // TODO: (@weadie) any를 사용한 이유는.. any가 있는 위치가 이 handler함수의 responseBody타입인데, 아래처럼 return하는 것에 대한 예시가 공문에 없습니다. 함수를 까면 되겠지만 시간이 아깝고 알아낸다고 해서 이 responseBody 타입은 사실 중요한게 아니기 때문에 any로 대체하였습니다. + http.post( + `${TEMP_PREFIX}/:eventId/login`, + async ({request}) => { + const {password} = await request.json(); + + if (password === String(VALID_PASSWORD_FOR_TEST)) { + return new HttpResponse(null, { + headers: { + 'Set-Cookie': 'eventToken=abc-123', + }, + }); + } else if (password.length < PASSWORD_LENGTH) { + return HttpResponse.json( + { + errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', + message: `비밀번호는 ${PASSWORD_LENGTH}자리 숫자만 가능합니다.`, + }, + {status: 401}, + ); + } else if (password === undefined) { + return HttpResponse.json( + { + errorCode: 'REQUEST_EMPTY', + message: '비밀번호는 공백일 수 없습니다.', + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + errorCode: 'PASSWORD_INVALID', + message: '비밀번호가 일치하지 않습니다.', + }, + {status: 401}, + ); + } + }, + ), +]; diff --git a/client/src/mocks/handlers/eventHandlers.ts b/client/src/mocks/handlers/eventHandlers.ts new file mode 100644 index 000000000..351993e16 --- /dev/null +++ b/client/src/mocks/handlers/eventHandlers.ts @@ -0,0 +1,55 @@ +import {HttpResponse, http} from 'msw'; + +import {RequestPostNewEvent, ResponsePostNewEvent} from '@apis/request/event'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import {PASSWORD_LENGTH} from '@constants/password'; + +import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; + +type ErrorResponseBody = { + errorCode: string; + message: string; +}; + +export const eventHandler = [ + http.post( + `${TEMP_PREFIX}`, + async ({request}) => { + const {eventName, password} = await request.json(); + + if (String(password).length < PASSWORD_LENGTH) { + return HttpResponse.json( + { + errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', + message: '비밀번호는 4자리 숫자만 가능합니다.', + }, + {status: 401}, + ); + } else if ( + eventName.length < VALID_EVENT_NAME_LENGTH_IN_SERVER.min || + eventName.length > VALID_EVENT_NAME_LENGTH_IN_SERVER.max + ) { + return HttpResponse.json( + { + errorCode: 'EVENT_NAME_LENGTH_INVALID', + message: `행사 이름은 2자 이상 30자 이하만 입력 가능합니다. 입력한 이름 길이 : ${eventName.length}`, + }, + {status: 401}, + ); + } else { + return HttpResponse.json( + { + eventId: 'eventId', + }, + { + headers: { + 'Set-Cookie': 'eventToken=abc-123', + }, + }, + ); + } + }, + ), +]; diff --git a/client/src/mocks/handlers/memberReportInActionHandlers.ts b/client/src/mocks/handlers/memberReportInActionHandlers.ts new file mode 100644 index 000000000..45de357f1 --- /dev/null +++ b/client/src/mocks/handlers/memberReportInActionHandlers.ts @@ -0,0 +1,49 @@ +import {http, HttpResponse} from 'msw'; + +import {MemberReport} from 'types/serviceType'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import memberReportInActionJson from '../memberReportListInAction.json'; + +let memberReportInActionMockData = memberReportInActionJson as MemberReport[]; + +type MemberReportListRequestParams = { + eventId: string; + actionId: string; +}; +type MemberReportListBody = {members: MemberReport[]}; + +export const memberReportInActionHandler = [ + http.get< + MemberReportListRequestParams, + MemberReportListBody, + any, + `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed` + >(`${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, ({params}) => { + const {actionId} = params; + + if (Number(actionId) === 123) { + return HttpResponse.json({ + members: memberReportInActionMockData, + }); + } + + return HttpResponse.json({ + members: memberReportInActionMockData.slice(0, 2), + }); + }), + + http.put( + `${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, + async ({request}) => { + const {members} = await request.json(); + + memberReportInActionMockData = members; + + return HttpResponse.json({ + status: 200, + }); + }, + ), +]; diff --git a/client/src/mocks/handlers/reportHandlers.ts b/client/src/mocks/handlers/reportHandlers.ts new file mode 100644 index 000000000..6b256d7d3 --- /dev/null +++ b/client/src/mocks/handlers/reportHandlers.ts @@ -0,0 +1,13 @@ +import {HttpResponse, http} from 'msw'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import reportListJson from '../reportList.json'; + +export const reportHandlers = [ + http.get(`${TEMP_PREFIX}/:eventId/actions/reports`, () => { + return HttpResponse.json({ + reports: reportListJson, + }); + }), +]; diff --git a/client/src/mocks/handlers/stepListHandler.ts b/client/src/mocks/handlers/stepListHandler.ts new file mode 100644 index 000000000..d79b7b0b4 --- /dev/null +++ b/client/src/mocks/handlers/stepListHandler.ts @@ -0,0 +1,113 @@ +import {HttpResponse, http} from 'msw'; + +import {Bill, MemberType, StepList} from 'types/serviceType'; + +import {TEMP_PREFIX} from '@apis/tempPrefix'; + +import stepListJson from '../stepList.json'; + +type StepListResponseBody = { + step: StepList; +}; + +type PostMemberListRequestBody = { + members: string[]; + status: MemberType; +}; + +type PostBillListRequestBody = { + actions: Bill[]; +}; + +let stepListMockData = stepListJson; + +export const stepListHandler = [ + http.get( + `${TEMP_PREFIX}/:eventId/actions`, + () => { + return HttpResponse.json({ + steps: stepListMockData, + }); + }, + ), + + http.get(`${TEMP_PREFIX}/:eventId/members`, () => { + return HttpResponse.json({ + memberNames: stepListMockData + .filter(({type}) => type !== 'BILL') + .map(({actions}) => actions.map(({name}) => name)) + .flat(), + }); + }), + + http.delete<{actionId: string}>(`${TEMP_PREFIX}/:eventId/member-actions/:actionId`, ({params}) => { + const {actionId} = params; + + if (parseInt(actionId) === 999) { + return HttpResponse.json( + { + errorCode: 'MEMBER_ACTION_STATUS_INVALID', + message: 'actionId는 999일 수 없습니다.(고의로 만든 에러임)', + }, + {status: 401}, + ); + } else { + return HttpResponse.json({ + status: 200, + }); + } + }), + + http.post( + `${TEMP_PREFIX}/:eventId/member-actions`, + async ({request}) => { + const {members, status} = await request.json(); + stepListMockData = [ + ...stepListJson, + { + type: status, + stepName: '영차영차', + members: status === 'IN' ? members : [], + actions: members.map(name => ({ + actionId: 999, + name, + price: 0, + sequence: 999, + isFixed: false, + })), + }, + ]; + + return HttpResponse.json({ + status: 200, + }); + }, + ), + + http.post( + `${TEMP_PREFIX}/:eventId/bill-actions`, + async ({request}) => { + const {actions} = await request.json(); + + stepListMockData = [ + ...stepListJson, + { + type: 'BILL', + stepName: '밥스카이', + members: [], + actions: actions.map(({title, price}) => ({ + actionId: 999, + name: title, + price, + sequence: 999, + isFixed: false, + })), + }, + ]; + + return HttpResponse.json({ + status: 200, + }); + }, + ), +]; diff --git a/client/src/mocks/handlers/testHandlers.ts b/client/src/mocks/handlers/testHandlers.ts new file mode 100644 index 000000000..fda96a1f0 --- /dev/null +++ b/client/src/mocks/handlers/testHandlers.ts @@ -0,0 +1,23 @@ +import {HttpResponse, http} from 'msw'; + +export const testHandler = [ + http.post(`/throw-handle-error`, () => { + return HttpResponse.json( + { + errorCode: 'TOKEN_NOT_FOUND', + message: '핸들링되는 테스트 에러입니다.', + }, + {status: 400}, + ); + }), + + http.post(`/throw-unhandle-error`, () => { + return HttpResponse.json( + { + errorCode: 'strange error', + message: '핸들링이 안되는 테스트 에러입니다.', + }, + {status: 500}, + ); + }), +]; diff --git a/client/src/mocks/invalidMemberStepList.json b/client/src/mocks/invalidMemberStepList.json new file mode 100644 index 000000000..33ca77e4c --- /dev/null +++ b/client/src/mocks/invalidMemberStepList.json @@ -0,0 +1,100 @@ +[ + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 999, + "name": "망쵸", + "price": null, + "sequence": 1, + "isFixed": false + }, + { + "actionId": 2, + "name": "백호", + "price": null, + "sequence": 2, + "isFixed": false + } + ] + }, + { + "type": "BILL", + "stepName": "1차", + "members": ["망쵸", "백호"], + "actions": [ + { + "actionId": 3, + "name": "감자탕", + "price": 10000, + "sequence": 3, + "isFixed": false + }, + { + "actionId": 4, + "name": "인생네컷", + "price": 10000, + "sequence": 4, + "isFixed": false + } + ] + }, + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 5, + "name": "소하", + "price": null, + "sequence": 5, + "isFixed": false + }, + { + "actionId": 6, + "name": "웨디", + "price": null, + "sequence": 6, + "isFixed": false + } + ] + }, + { + "type": "BILL", + "stepName": "2차", + "members": ["소하", "웨디"], + "actions": [ + { + "actionId": 9, + "name": "노래방", + "price": 20000, + "sequence": 10, + "isFixed": false + } + ] + }, + { + "type": "OUT", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 7, + "name": "망쵸", + "price": null, + "sequence": 7, + "isFixed": false + }, + { + "actionId": 8, + "name": "백호", + "price": null, + "sequence": 8, + "isFixed": false + } + ] + } +] diff --git a/client/src/mocks/memberActionStepList.json b/client/src/mocks/memberActionStepList.json new file mode 100644 index 000000000..734db4a75 --- /dev/null +++ b/client/src/mocks/memberActionStepList.json @@ -0,0 +1,23 @@ +[ + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 1, + "name": "망쵸", + "price": null, + "sequence": 1, + "isFixed": false + }, + { + "actionId": 2, + "name": "백호", + "price": null, + "sequence": 2, + "isFixed": false + } + ] + } +] diff --git a/client/src/mocks/memberReportListInAction.json b/client/src/mocks/memberReportListInAction.json new file mode 100644 index 000000000..2e24670cb --- /dev/null +++ b/client/src/mocks/memberReportListInAction.json @@ -0,0 +1,6 @@ +[ + {"name": "망쵸", "price": 25000, "isFixed": false}, + {"name": "이상", "price": 25000, "isFixed": false}, + {"name": "소하", "price": 25000, "isFixed": false}, + {"name": "쿠키", "price": 25000, "isFixed": false} +] diff --git a/client/src/mocks/memberReportSearchList.json b/client/src/mocks/memberReportSearchList.json new file mode 100644 index 000000000..dfcb684b1 --- /dev/null +++ b/client/src/mocks/memberReportSearchList.json @@ -0,0 +1,10 @@ +[ + {"name": "망쵸", "price": 1033200}, + {"name": "이상", "price": 10100}, + {"name": "소하", "price": 10000}, + {"name": "쿠키", "price": 100012}, + {"name": "토다리", "price": 1001230}, + {"name": "감자", "price": 1012300}, + {"name": "백호", "price": 10300}, + {"name": "웨디", "price": 1000} +] diff --git a/client/src/mocks/reportList.json b/client/src/mocks/reportList.json new file mode 100644 index 000000000..a663eb9fd --- /dev/null +++ b/client/src/mocks/reportList.json @@ -0,0 +1,18 @@ +[ + { + "name": "소하", + "price": 40000 + }, + { + "name": "감자", + "price": 20000 + }, + { + "name": "쿠키", + "price": 40000 + }, + { + "name": "토다리", + "price": 0 + } +] diff --git a/client/src/mocks/server.ts b/client/src/mocks/server.ts new file mode 100644 index 000000000..157a298e0 --- /dev/null +++ b/client/src/mocks/server.ts @@ -0,0 +1,5 @@ +import {setupServer} from 'msw/node'; + +import {handlers} from './handlers'; + +export const server = setupServer(...handlers); diff --git a/client/src/mocks/serverConstants.ts b/client/src/mocks/serverConstants.ts new file mode 100644 index 000000000..1063a2f75 --- /dev/null +++ b/client/src/mocks/serverConstants.ts @@ -0,0 +1,4 @@ +export const VALID_EVENT_NAME_LENGTH_IN_SERVER = { + min: 2, + max: 30, +}; diff --git a/client/src/mocks/stepList.json b/client/src/mocks/stepList.json new file mode 100644 index 000000000..355692d58 --- /dev/null +++ b/client/src/mocks/stepList.json @@ -0,0 +1,100 @@ +[ + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 1, + "name": "망쵸", + "price": null, + "sequence": 1, + "isFixed": false + }, + { + "actionId": 2, + "name": "백호", + "price": null, + "sequence": 2, + "isFixed": false + } + ] + }, + { + "type": "BILL", + "stepName": "1차", + "members": ["망쵸", "백호"], + "actions": [ + { + "actionId": 3, + "name": "감자탕", + "price": 10000, + "sequence": 3, + "isFixed": false + }, + { + "actionId": 4, + "name": "인생네컷", + "price": 10000, + "sequence": 4, + "isFixed": false + } + ] + }, + { + "type": "IN", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 5, + "name": "소하", + "price": null, + "sequence": 5, + "isFixed": false + }, + { + "actionId": 6, + "name": "웨디", + "price": null, + "sequence": 6, + "isFixed": false + } + ] + }, + { + "type": "BILL", + "stepName": "2차", + "members": ["소하", "웨디"], + "actions": [ + { + "actionId": 9, + "name": "노래방", + "price": 20000, + "sequence": 10, + "isFixed": false + } + ] + }, + { + "type": "OUT", + "stepName": null, + "members": [], + "actions": [ + { + "actionId": 7, + "name": "망쵸", + "price": null, + "sequence": 7, + "isFixed": false + }, + { + "actionId": 8, + "name": "백호", + "price": null, + "sequence": 8, + "isFixed": false + } + ] + } +] diff --git a/client/src/mocks/svg.ts b/client/src/mocks/svg.ts new file mode 100644 index 000000000..ffe2050a0 --- /dev/null +++ b/client/src/mocks/svg.ts @@ -0,0 +1,2 @@ +export default 'SvgrURL'; +export const ReactComponent = 'div'; diff --git a/client/src/mocks/validValueForTest.ts b/client/src/mocks/validValueForTest.ts new file mode 100644 index 000000000..31f587134 --- /dev/null +++ b/client/src/mocks/validValueForTest.ts @@ -0,0 +1,4 @@ +export const VALID_PASSWORD_FOR_TEST = 1111; +export const VALID_TOKEN_FOR_TEST = 'valid-token'; +export const FORBIDDEN_TOKEN_FOR_TEST = 'forbidden-token'; +export const EXPIRED_TOKEN_FOR_TEST = 'expired-token'; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx new file mode 100644 index 000000000..066165d6a --- /dev/null +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -0,0 +1,29 @@ +import {useLocation, useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; + +import {RunningDog} from '@components/Common/Logo'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const CompleteCreateEventPage = () => { + const navigate = useNavigate(); + const location = useLocation(); + + const params = new URLSearchParams(location.search); + const eventId = params.get('eventId'); + + return ( + + + + <RunningDog /> + <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>관리 페이지로 이동</FixedButton> + </MainLayout> + ); +}; + +export default CompleteCreateEventPage; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx new file mode 100644 index 000000000..ad68327d2 --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -0,0 +1,42 @@ +import {useNavigate} from 'react-router-dom'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; +import {css} from '@emotion/react'; + +import useSetEventNamePage from '@hooks/useSetEventNamePage'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const SetEventNamePage = () => { + const navigate = useNavigate(); + const {eventName, errorMessage, canSubmit, handleEventNameChange} = useSetEventNamePage(); + + const submitEventName = (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); + }; + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + <Title title="행사 이름 입력" description="시작할 행사 이름을 입력해 주세요." /> + <form onSubmit={submitEventName} css={css({padding: '0 1rem'})}> + <LabelInput + labelText="행사 이름" + errorText={errorMessage ?? ''} + value={eventName} + type="text" + placeholder="행사 이름" + onChange={handleEventNameChange} + isError={!!errorMessage} + autoFocus + ></LabelInput> + <FixedButton disabled={!canSubmit}>다음</FixedButton> + </form> + </MainLayout> + ); +}; + +export default SetEventNamePage; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx new file mode 100644 index 000000000..14fcdd75b --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -0,0 +1,41 @@ +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; + +import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; + +import RULE from '@constants/rule'; +import {PASSWORD_LENGTH} from '@constants/password'; + +const SetEventPasswordPage = () => { + const {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending} = + useSetEventPasswordPage(); + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + <Title + title="행사 비밀번호 설정" + description={`행사 관리에 필요한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} + /> + <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <LabelInput + labelText="비밀번호" + errorText={errorMessage} + value={password} + type="text" + maxLength={RULE.maxEventPasswordLength} + placeholder="비밀번호" + onChange={handleChange} + isError={!!errorMessage} + autoFocus + /> + <FixedButton variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> + 행동 개시! + </FixedButton> + </form> + </MainLayout> + ); +}; + +export default SetEventPasswordPage; diff --git a/client/src/pages/CreateEventPage/index.ts b/client/src/pages/CreateEventPage/index.ts new file mode 100644 index 000000000..6d3d6c808 --- /dev/null +++ b/client/src/pages/CreateEventPage/index.ts @@ -0,0 +1,3 @@ +export {default as SetEventNamePage} from './SetEventNamePage'; +export {default as SetEventPasswordPage} from './SetEventPasswordPage'; +export {default as CompleteCreateEventPage} from './CompleteCreateEventPage'; diff --git a/client/src/pages/ErrorPage/ErrorPage.tsx b/client/src/pages/ErrorPage/ErrorPage.tsx new file mode 100644 index 000000000..31ef8c81f --- /dev/null +++ b/client/src/pages/ErrorPage/ErrorPage.tsx @@ -0,0 +1,14 @@ +import {MainLayout, Title} from 'haengdong-design'; + +const ErrorPage = () => { + return ( + <MainLayout> + <Title + title="알 수 없는 오류입니다." + description="오류가 난 상황에 대해 haengdongdj@gmail.com 로 연락주시면 소정의 상품을 드립니다." + /> + </MainLayout> + ); +}; + +export default ErrorPage; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts new file mode 100644 index 000000000..cf6bb0042 --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts @@ -0,0 +1,23 @@ +import {css} from '@emotion/react'; + +export const receiptStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '1rem', + paddingBottom: '2rem', + }); + +export const titleAndListButtonContainerStyle = () => + css({ + display: 'flex', + flexDirection: 'column', + }); + +export const buttonGroupStyle = () => + css({ + display: 'flex', + width: '100%', + padding: '0 0.5rem', + gap: '0.5rem', + }); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx new file mode 100644 index 000000000..79deeac7a --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -0,0 +1,90 @@ +import {useEffect, useState} from 'react'; +import {Title, FixedButton, ListButton, Button} from 'haengdong-design'; +import {useOutletContext} from 'react-router-dom'; + +import StepList from '@components/StepList/StepList'; +import {ModalBasedOnMemberCount, SetAllMemberListModal} from '@components/Modal/index'; +import useRequestGetAllMemberList from '@hooks/queries/useRequestGetAllMemberList'; +import useRequestPostAuthenticate from '@hooks/queries/useRequestPostAuthentication'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; + +import {EventPageContextProps} from '../EventPageLayout'; + +import {receiptStyle, titleAndListButtonContainerStyle, buttonGroupStyle} from './AdminPage.style'; + +const AdminPage = () => { + const [isOpenFixedButtonBottomSheet, setIsOpenFixedButtonBottomSheet] = useState(false); + const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); + const [isAddEditableItem, setIsAddEditableItem] = useState(false); + + const {eventName} = useOutletContext<EventPageContextProps>(); + const {data: allMemberListData} = useRequestGetAllMemberList(); + const allMemberList = allMemberListData?.memberNames ?? []; + + const {totalExpenseAmount} = useTotalExpenseAmountStore(); + + const {mutate: postAuthentication} = useRequestPostAuthenticate(); + + useEffect(() => { + postAuthentication(); + }, [postAuthentication]); + + const handleOpenAllMemberListButton = () => { + setIsOpenFixedButtonBottomSheet(prev => !prev); + setIsOpenAllMemberListButton(prev => !prev); + }; + + const getTitleDescriptionByInitialMemberSetting = () => { + return allMemberList.length > 0 + ? `지출 내역 및 인원 변동을 추가해 주세요. + 인원 변동을 기준으로 몇 차인지 나뉘어져요.` + : '“시작 인원 추가” 버튼을 눌러 행사의 시작부터 참여하는 사람들의 이름을 입력해 주세요.'; + }; + + return ( + <> + <div css={titleAndListButtonContainerStyle}> + <Title title={eventName} description={getTitleDescriptionByInitialMemberSetting()} price={totalExpenseAmount} /> + {allMemberList.length !== 0 && ( + <ListButton + prefix="전체 참여자" + suffix={`${allMemberList.length}명`} + onClick={handleOpenAllMemberListButton} + /> + )} + </div> + <section css={receiptStyle}> + <StepList isAddEditableItem={isAddEditableItem} setIsAddEditableItem={setIsAddEditableItem} /> + {allMemberList.length === 0 ? ( + <FixedButton children={'시작인원 추가하기'} onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} /> + ) : ( + <div css={buttonGroupStyle}> + <Button + size="medium" + variants="tertiary" + style={{width: '100%'}} + onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} + > + 인원 변동 추가 + </Button> + <Button size="medium" onClick={() => setIsAddEditableItem(true)} style={{width: '100%'}}> + 지출 내역 추가 + </Button> + </div> + )} + {isOpenFixedButtonBottomSheet && ( + <ModalBasedOnMemberCount + allMemberList={allMemberList} + setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} + isOpenBottomSheet={isOpenFixedButtonBottomSheet} + isOpenAllMemberListButton={isOpenAllMemberListButton} + setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} + /> + )} + </section> + </> + ); +}; + +export default AdminPage; diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx new file mode 100644 index 000000000..741dca3eb --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -0,0 +1,35 @@ +import {FixedButton, LabelInput, Title} from 'haengdong-design'; + +import useEventLogin from '@hooks/useEventLogin'; + +import RULE from '@constants/rule'; +import {PASSWORD_LENGTH} from '@constants/password'; + +const EventLoginPage = () => { + const {password, errorMessage, handleChange, canSubmit, submitPassword} = useEventLogin(); + + return ( + <> + <Title + title="행사 비밀번호 입력" + description={`관리를 위해선 비밀번호가 필요해요. 행사 생성 시 설정한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} + /> + <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <LabelInput + labelText="비밀번호" + errorText={errorMessage} + value={password} + type="secret" + maxLength={RULE.maxEventPasswordLength} + placeholder="비밀번호" + onChange={e => handleChange(e)} + isError={!!errorMessage} + autoFocus + ></LabelInput> + <FixedButton disabled={!canSubmit}>관리 페이지로</FixedButton> + </form> + </> + ); +}; + +export default EventLoginPage; diff --git a/client/src/pages/EventPage/AdminPage/index.ts b/client/src/pages/EventPage/AdminPage/index.ts new file mode 100644 index 000000000..b80c0bb2f --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/index.ts @@ -0,0 +1 @@ +export {default as AdminPage} from './AdminPage'; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx new file mode 100644 index 000000000..6f00c23f1 --- /dev/null +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -0,0 +1,65 @@ +import {MainLayout, TopNav, Switch, Button} from 'haengdong-design'; +import {Outlet, useMatch} from 'react-router-dom'; +import CopyToClipboard from 'react-copy-to-clipboard'; + +import {useToast} from '@hooks/useToast/useToast'; +import useRequestGetEventName from '@hooks/queries/useRequestGetEventName'; + +import useNavSwitch from '@hooks/useNavSwitch'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; +import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +export type EventPageContextProps = { + isAdmin: boolean; + eventName: string; +}; + +const EventPageLayout = () => { + const {nav, paths, onChange} = useNavSwitch(); + const {data} = useRequestGetEventName(); + const eventName = data?.eventName ?? ''; + const eventId = getEventIdByUrl(); + + const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; + const isLoginPage = useMatch(ROUTER_URLS.eventLogin) !== null; + + const outletContext: EventPageContextProps = { + isAdmin, + eventName, + }; + + const {showToast} = useToast(); + const url = getEventPageUrlByEnvironment(eventId, 'home'); + + return ( + <MainLayout backgroundColor="gray"> + <TopNav> + <Switch value={nav} values={paths} onChange={onChange} /> + {!isLoginPage && ( + <CopyToClipboard + text={`[행동대장]\n"${eventName}"에 대한 정산을 시작할게요:)\n아래 링크에 접속해서 정산 내역을 확인해 주세요!\n${url}`} + onCopy={() => + showToast({ + showingTime: 3000, + message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', + type: 'confirm', + position: 'bottom', + bottom: '8rem', + }) + } + > + <Button size="small" variants="secondary"> + 정산 초대하기 + </Button> + </CopyToClipboard> + )} + </TopNav> + <Outlet context={outletContext} /> + </MainLayout> + ); +}; + +export default EventPageLayout; diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx new file mode 100644 index 000000000..72fc77cb9 --- /dev/null +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -0,0 +1,26 @@ +import {Tab, Tabs, Title} from 'haengdong-design'; +import {useOutletContext} from 'react-router-dom'; + +import MemberReportList from '@components/MemberReportList/MemberReportList'; +import StepList from '@components/StepList/StepList'; + +import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; + +import {EventPageContextProps} from '../EventPageLayout'; + +const HomePage = () => { + const {eventName} = useOutletContext<EventPageContextProps>(); + const {totalExpenseAmount} = useTotalExpenseAmountStore(); + + return ( + <div style={{paddingBottom: '2rem'}}> + <Title title={eventName} price={totalExpenseAmount} /> + <Tabs tabsContainerStyle={{gap: '1rem'}}> + <Tab label="전체 지출 내역" content={<StepList />} /> + <Tab label="참여자 별 내역" content={<MemberReportList />} /> + </Tabs> + </div> + ); +}; + +export default HomePage; diff --git a/client/src/pages/EventPage/HomePage/index.ts b/client/src/pages/EventPage/HomePage/index.ts new file mode 100644 index 000000000..aa0bf2b3f --- /dev/null +++ b/client/src/pages/EventPage/HomePage/index.ts @@ -0,0 +1 @@ +export {default as HomePage} from './HomePage'; diff --git a/client/src/pages/EventPage/index.ts b/client/src/pages/EventPage/index.ts new file mode 100644 index 000000000..5b5c314c7 --- /dev/null +++ b/client/src/pages/EventPage/index.ts @@ -0,0 +1 @@ +export {default as EventPage} from './EventPageLayout'; diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx new file mode 100644 index 000000000..d3a1cd079 --- /dev/null +++ b/client/src/pages/MainPage/MainPage.tsx @@ -0,0 +1,23 @@ +import {MainLayout} from 'haengdong-design'; + +import Nav from './Nav/Nav'; +import MainSection from './Section/MainSection'; +import DescriptionSection from './Section/DescriptionSection'; +import AddBillSection from './Section/AddBillSection'; +import AddMemberSection from './Section/AddMemberSection'; +import MemberReportSection from './Section/MemberReportSection'; + +const MainPage = () => { + return ( + <MainLayout> + <Nav /> + <MainSection /> + <DescriptionSection /> + <AddBillSection /> + <AddMemberSection /> + <MemberReportSection /> + </MainLayout> + ); +}; + +export default MainPage; diff --git a/client/src/pages/MainPage/Nav/Nav.style.ts b/client/src/pages/MainPage/Nav/Nav.style.ts new file mode 100644 index 000000000..58cf1cb86 --- /dev/null +++ b/client/src/pages/MainPage/Nav/Nav.style.ts @@ -0,0 +1,22 @@ +import {css} from '@emotion/react'; + +export const navStyle = css({ + position: 'fixed', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '1rem', + + top: '0', + width: '100%', + maxWidth: '768px', + zIndex: '20', + height: '4rem', + backgroundColor: 'white', +}); + +export const logoStyle = css({ + display: 'flex', + gap: '0.5rem', + alignItems: 'center', +}); diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx new file mode 100644 index 000000000..ec4d745c9 --- /dev/null +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -0,0 +1,27 @@ +import {Button, Flex, Text} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; + +import Heundeut from '@assets/image/heundeut.svg'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +import {logoStyle, navStyle} from './Nav.style'; + +const Nav = () => { + const navigate = useNavigate(); + return ( + <header css={navStyle}> + <Flex gap="0.5rem"> + <Heundeut /> + <div css={logoStyle}> + <Text size="subTitle">행동대장</Text> + </div> + </Flex> + <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + 정산 시작하기 + </Button> + </header> + ); +}; + +export default Nav; diff --git a/client/src/pages/MainPage/Section/AddBillSection.tsx b/client/src/pages/MainPage/Section/AddBillSection.tsx new file mode 100644 index 000000000..ecf7dd90d --- /dev/null +++ b/client/src/pages/MainPage/Section/AddBillSection.tsx @@ -0,0 +1,31 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; + +import AddBillMockup from '@assets/image/addBillMockup.svg'; + +const AddBillSection = () => { + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: 'white', + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">지출내역을 쉽게 추가하세요</Text> + <Text size="body" textColor="gray"> + {`나중에 한번에 기록할 수도 있지만, + 실시간으로 기록해 놓을 수 있어요`} + </Text> + </div> + <AddBillMockup /> + </div> + ); +}; + +export default AddBillSection; diff --git a/client/src/pages/MainPage/Section/AddMemberSection.tsx b/client/src/pages/MainPage/Section/AddMemberSection.tsx new file mode 100644 index 000000000..ae6e7d1fc --- /dev/null +++ b/client/src/pages/MainPage/Section/AddMemberSection.tsx @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; +import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +import AddMemberMockup from '@assets/image/addMemberMockup.svg'; + +const AddMemberSection = () => { + const {theme} = useTheme(); + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: theme.colors.lightGrayContainer, + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">인원 변동은 신경쓰지 마세요</Text> + <Text size="body" textColor="gray"> + {`누가 나가고 들어왔는지만 기록하세요 + 행동대장이 알아서 차수를 나눠줘요`} + </Text> + </div> + <AddMemberMockup /> + </div> + ); +}; + +export default AddMemberSection; diff --git a/client/src/pages/MainPage/Section/DescriptionSection.tsx b/client/src/pages/MainPage/Section/DescriptionSection.tsx new file mode 100644 index 000000000..193cfe465 --- /dev/null +++ b/client/src/pages/MainPage/Section/DescriptionSection.tsx @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; +import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +const DescriptionSection = () => { + const {theme} = useTheme(); + + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '100%', + gap: '1.5rem', + padding: '3rem 1.5rem', + backgroundColor: theme.colors.lightGrayContainer, + })} + > + <Text style={{textAlign: 'center'}} size="subTitle">{`행동대장들을 위해 + 행동대장을 준비했어요 + `}</Text> + <Text style={{textAlign: 'center'}} size="subTitle" textColor="gray">{`주환이가 먼저 집에 가도 + 소연이가 늦게 도착해도 + 건상이가 술을 마시지 않아도 + `}</Text> + <Text style={{textAlign: 'center'}} size="subTitle">{`간편하게 정산할 수 있어요`}</Text> + </div> + ); +}; + +export default DescriptionSection; diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx new file mode 100644 index 000000000..4bbeb7340 --- /dev/null +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -0,0 +1,93 @@ +import {css, keyframes} from '@emotion/react'; +import {Button, Text} from 'haengdong-design'; +import {useNavigate} from 'react-router-dom'; + +import {StandingDog} from '@components/Common/Logo'; +import ChevronDown from '@assets/image/chevronDownLarge.svg'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +const MainSection = () => { + const navigate = useNavigate(); + return ( + <div + css={css({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100vh', + width: '100%', + backgroundColor: 'white', + })} + > + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + gap: '2rem', + padding: '1.5rem', + height: '100vh', + width: '100%', + })} + > + <div css={animateWithDelay(0)}> + <StandingDog /> + </div> + <Text css={animateWithDelay(1)} style={{textAlign: 'center'}} size="title">{`행동대장을 통해 + 간편하게 정산하세요 + `}</Text> + <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + 정산 시작하기 + </Button> + </div> + <div + css={css({ + position: 'absolute', + bottom: '2rem', + left: '50%', + animation: `${bounce} 2s infinite ease-in-out`, + })} + > + <ChevronDown /> + </div> + </div> + ); +}; + +const fadeIn = keyframes` + from { + opacity: 0; + } + to { + opacity: 1; + } +`; + +const slideIn = keyframes` + from { + transform: translateY(1rem); + } + to { + transform: translateY(0); + } +`; + +const bounce = keyframes` + 0%, 100% { + transform: translate(-50%, 0); + } + 50% { + transform: translate(-50%, -1rem); + } +`; + +const animateWithDelay = (delay: number) => css` + opacity: 0; + animation: + ${fadeIn} 1s ease-in-out ${delay}s forwards, + ${slideIn} 1s ease-in-out ${delay}s forwards; +`; + +export default MainSection; diff --git a/client/src/pages/MainPage/Section/MemberReportSection.tsx b/client/src/pages/MainPage/Section/MemberReportSection.tsx new file mode 100644 index 000000000..69871e1c9 --- /dev/null +++ b/client/src/pages/MainPage/Section/MemberReportSection.tsx @@ -0,0 +1,31 @@ +import {css} from '@emotion/react'; +import {Text} from 'haengdong-design'; + +import MemberReportMockup from '@assets/image/memberReportMockup.svg'; + +const MemberReportSection = () => { + return ( + <div + css={css({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + padding: '3rem', + gap: '2rem', + width: '100%', + backgroundColor: 'white', + })} + > + <div css={css({display: 'flex', flexDirection: 'column', gap: '1rem'})}> + <Text size="subTitle">친구에게 링크를 공유하세요</Text> + <Text size="body" textColor="gray"> + {`지출내역과 인원변동을 통해 + 금액은 자동으로 계산돼요`} + </Text> + </div> + <MemberReportMockup /> + </div> + ); +}; + +export default MemberReportSection; diff --git a/client/src/pages/MainPage/index.ts b/client/src/pages/MainPage/index.ts new file mode 100644 index 000000000..017fff307 --- /dev/null +++ b/client/src/pages/MainPage/index.ts @@ -0,0 +1 @@ +export {default as MainPage} from './MainPage'; diff --git a/client/src/router.tsx b/client/src/router.tsx new file mode 100644 index 000000000..51162c775 --- /dev/null +++ b/client/src/router.tsx @@ -0,0 +1,58 @@ +import {createBrowserRouter} from 'react-router-dom'; + +import {AdminPage} from '@pages/EventPage/AdminPage'; +import {HomePage} from '@pages/EventPage/HomePage'; +import ErrorPage from '@pages/ErrorPage/ErrorPage'; +import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; + +import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; +import {MainPage} from '@pages/MainPage'; +import {EventPage} from '@pages/EventPage'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +import App from './App'; + +const router = createBrowserRouter([ + { + path: '', + element: <App />, + children: [ + { + index: true, + path: ROUTER_URLS.main, + element: <MainPage />, + }, + { + path: ROUTER_URLS.eventCreateName, + element: <SetEventNamePage />, + }, + { + path: ROUTER_URLS.eventCreatePassword, + element: <SetEventPasswordPage />, + }, + { + path: ROUTER_URLS.eventCreateComplete, + element: <CompleteCreateEventPage />, + }, + { + path: ROUTER_URLS.event, + element: <EventPage />, + children: [ + {path: ROUTER_URLS.eventManage, element: <AdminPage />}, + {path: ROUTER_URLS.home, element: <HomePage />}, + { + path: ROUTER_URLS.eventLogin, + element: <EventLoginPage />, + }, + ], + }, + { + path: '*', + element: <ErrorPage />, + }, + ], + }, +]); + +export default router; diff --git a/client/src/store/appErrorStore.ts b/client/src/store/appErrorStore.ts new file mode 100644 index 000000000..ca350d4cb --- /dev/null +++ b/client/src/store/appErrorStore.ts @@ -0,0 +1,14 @@ +import {create} from 'zustand'; + +type State = { + appError: Error | null; +}; + +type Action = { + updateAppError: (appError: State['appError']) => void; +}; + +export const useAppErrorStore = create<State & Action>(set => ({ + appError: null, + updateAppError: appError => set(() => ({appError})), +})); diff --git a/client/src/store/stepListStore.ts b/client/src/store/stepListStore.ts new file mode 100644 index 000000000..07f3b107f --- /dev/null +++ b/client/src/store/stepListStore.ts @@ -0,0 +1,16 @@ +import {create} from 'zustand'; + +import {ConvertedAction} from 'types/serviceType'; + +type State = { + stepList: ConvertedAction[]; +}; + +type Action = { + updateStepList: (stepList: State['stepList']) => void; +}; + +export const useStepListStore = create<State & Action>(set => ({ + stepList: [], + updateStepList: stepList => set(() => ({stepList})), +})); diff --git a/client/src/store/totalExpenseAmountStore.ts b/client/src/store/totalExpenseAmountStore.ts new file mode 100644 index 000000000..e9ebcf52a --- /dev/null +++ b/client/src/store/totalExpenseAmountStore.ts @@ -0,0 +1,18 @@ +import {create} from 'zustand'; + +import {BillStep, MemberStep} from 'types/serviceType'; + +import {getTotalExpenseAmount} from '@utils/caculateExpense'; + +type State = { + totalExpenseAmount: number; +}; + +type Action = { + updateTotalExpenseAmount: (stepList: (MemberStep | BillStep)[]) => void; +}; + +export const useTotalExpenseAmountStore = create<State & Action>(set => ({ + totalExpenseAmount: 0, + updateTotalExpenseAmount: stepList => set({totalExpenseAmount: getTotalExpenseAmount(stepList)}), +})); diff --git a/client/src/types/fetchErrorType.ts b/client/src/types/fetchErrorType.ts new file mode 100644 index 000000000..19fe8ee6f --- /dev/null +++ b/client/src/types/fetchErrorType.ts @@ -0,0 +1,11 @@ +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; + +import {Method} from '@apis/fetcher'; + +export type FetchErrorType = Error & { + requestBody: string; + status: number; + endpoint: string; + errorInfo: ErrorInfo; + method: Method; +}; diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts new file mode 100644 index 000000000..0467995f1 --- /dev/null +++ b/client/src/types/serviceType.ts @@ -0,0 +1,80 @@ +export type MemberType = 'IN' | 'OUT'; + +export type InOutType = '늦참' | '탈주'; + +export type MemberReport = { + name: string; + price: number; +}; + +export type MemberReportInAction = MemberReport & { + isFixed: boolean; +}; + +export type Bill = { + title: string; + price: number; +}; + +type StepBase = { + members: string[]; +}; + +export type MemberStep = StepBase & { + type: MemberType; + stepName: null; + actions: MemberAction[]; +}; + +export type BillStep = StepBase & { + type: 'BILL'; + stepName: string; + actions: BillAction[]; +}; + +// (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. +export type StepList = { + steps: (MemberStep | BillStep)[]; +}; + +export type Action = { + actionId: number; + name: string; + price: number | null; + sequence: number; + isFixed: boolean; +}; + +export type BillAction = Omit<Action, 'price'> & { + price: number; +}; + +export type MemberAction = Omit<Action, 'price'> & { + price: null; +}; + +export type Member = { + name: string; + status: MemberType; +}; + +export type ActionType = 'IN' | 'OUT' | 'BILL'; + +// export type StepList = { +// actions: Action[]; +// }; + +export type ConvertedAction = { + actionId: number; + name: string; + price: string | null; + sequence: number; + type: ActionType; +}; + +export type InputPair = Omit<Bill, 'price'> & { + price: string; + index: number; +}; + +export type BillInputType = 'title' | 'price'; diff --git a/client/src/utils/caculateExpense.ts b/client/src/utils/caculateExpense.ts new file mode 100644 index 000000000..8b41af8c3 --- /dev/null +++ b/client/src/utils/caculateExpense.ts @@ -0,0 +1,14 @@ +import {BillAction, BillStep, MemberStep} from 'types/serviceType'; + +export const calculateStepExpense = (actions: BillAction[]) => { + return actions.reduce((sum, {price}) => sum + price, 0); +}; + +export const getTotalExpenseAmount = (stepList: (MemberStep | BillStep)[]) => { + return stepList.reduce((sum, {type, actions}) => { + if (type === 'BILL') { + return sum + calculateStepExpense(actions); + } + return sum; + }, 0); +}; diff --git a/client/src/utils/captureError.ts b/client/src/utils/captureError.ts new file mode 100644 index 000000000..67a30ac99 --- /dev/null +++ b/client/src/utils/captureError.ts @@ -0,0 +1,49 @@ +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; + +import sendLogToSentry from './sendLogToSentry'; + +export const captureError = async (error: Error, errorInfo: ErrorInfo) => { + // prod 환경에서만 Sentry capture 실행 + if (process.env.NODE_ENV !== 'production') return; + + switch (errorInfo?.errorCode) { + case 'INTERNAL_SERVER_ERROR': + sendLogToSentry({error, errorInfo, level: 'fatal'}); + break; + + case 'FORBIDDEN': + sendLogToSentry({error, errorInfo}); + + break; + + case 'TOKEN_INVALID': + sendLogToSentry({error, errorInfo}); + + break; + + case 'TOKEN_EXPIRED': + sendLogToSentry({error, errorInfo}); + + break; + + case 'TOKEN_NOT_FOUND': + sendLogToSentry({error, errorInfo}); + + break; + + // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 + case 'PASSWORD_INVALID': + sendLogToSentry({error, errorInfo, level: 'debug'}); + + break; + + // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 + case 'BILL_ACTION_PRICE_INVALID': + sendLogToSentry({error, errorInfo, level: 'debug'}); + break; + + default: + sendLogToSentry({error, errorInfo, level: 'fatal'}); + break; + } +}; diff --git a/client/src/utils/getEventIdByUrl.ts b/client/src/utils/getEventIdByUrl.ts new file mode 100644 index 000000000..1cdb16c8f --- /dev/null +++ b/client/src/utils/getEventIdByUrl.ts @@ -0,0 +1,13 @@ +import REGEXP from '@constants/regExp'; + +const extractEventIdFromUrl = (url: string) => { + const regex = REGEXP.eventUrl; + const match = url.match(regex); + return match ? match[1] : null; +}; + +const getEventIdByUrl = () => { + return extractEventIdFromUrl(window.location.pathname) ?? ''; +}; + +export default getEventIdByUrl; diff --git a/client/src/utils/getEventPageUrlByEnvironment.ts b/client/src/utils/getEventPageUrlByEnvironment.ts new file mode 100644 index 000000000..bcfce54e9 --- /dev/null +++ b/client/src/utils/getEventPageUrlByEnvironment.ts @@ -0,0 +1,11 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; + +type EventPageTab = 'home' | 'admin'; + +const getEventPageUrlByEnvironment = (eventId: string, tab: EventPageTab) => { + const isDevelopment = process.env.NODE_ENV === 'development'; + + return `https://${isDevelopment ? 'dev.' : ''}haengdong.pro${ROUTER_URLS.event}/${eventId}/${tab}`; +}; + +export default getEventPageUrlByEnvironment; diff --git a/client/src/utils/groupActions.ts b/client/src/utils/groupActions.ts new file mode 100644 index 000000000..a6347167d --- /dev/null +++ b/client/src/utils/groupActions.ts @@ -0,0 +1,27 @@ +import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; + +import stepListToAction from './stepListToActions'; + +const groupActions = (stepList: (BillStep | MemberStep)[]) => { + const actions = stepListToAction(stepList); + const groupedActions: ConvertedAction[][] = []; + + let group: ConvertedAction[] = []; + + actions.forEach((action, index) => { + if (group.length === 0 || group[group.length - 1].type === action.type) { + group.push(action); + } else { + groupedActions.push(group); + group = []; + } + + if (index === actions.length - 1) { + groupedActions.push(group); + } + }); + + return groupedActions; +}; + +export default groupActions; diff --git a/client/src/utils/isArraysEqual.ts b/client/src/utils/isArraysEqual.ts new file mode 100644 index 000000000..df73a8552 --- /dev/null +++ b/client/src/utils/isArraysEqual.ts @@ -0,0 +1,16 @@ +const isArraysEqual = <T>(arr1: T[], arr2: T[]) => { + if (arr1.length !== arr2.length) return false; + + // 배열을 정렬한 후 비교 + const sortedArr1 = [...arr1].sort(); + const sortedArr2 = [...arr2].sort(); + + // 값은 모두 같으나 순서를 변경했을 시, false를 반환한다. + for (let i = 0; i < sortedArr1.length; i++) { + if (sortedArr1[i] !== sortedArr2[i]) return false; + } + + return true; +}; + +export default isArraysEqual; diff --git a/client/src/utils/objectToQueryString.ts b/client/src/utils/objectToQueryString.ts new file mode 100644 index 000000000..cc40fb076 --- /dev/null +++ b/client/src/utils/objectToQueryString.ts @@ -0,0 +1,9 @@ +import {ObjectQueryParams} from '@apis/fetcher'; + +const objectToQueryString = (params: ObjectQueryParams): string => { + return Object.entries(params) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) + .join('&'); +}; + +export default objectToQueryString; diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts new file mode 100644 index 000000000..22d736b6c --- /dev/null +++ b/client/src/utils/sendLogToSentry.ts @@ -0,0 +1,66 @@ +import * as Sentry from '@sentry/react'; + +import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; + +import {UNKNOWN_ERROR} from '@constants/errorMessage'; + +import FetchError from '../errors/FetchError'; + +/** + * level은 아래와 같은 용도에 맞게 지정해줍니다. + * + * fatal: 앱이 종료될 수 있는 치명적인 오류 + * error: 특정 기능 실패로 앱 종료까지는 아닌 오류 + * warning: 잠재적으로 문제가 될 수 있는 오류. 현재는 심각하지 않은 오류 + * info: 시스템의 정상적인 동작을 나타냄. 중요한 이벤트나 상태 변화 기록용 + * debug: 디버깅 목적으로 사용됨 + * log: 일반적인 로그 메세지 + */ + +type SentryLevel = 'fatal' | 'error' | 'warning' | 'info' | 'debug' | 'log'; +type SendLogToSentry = { + level?: SentryLevel; + error: Error; + errorInfo: ErrorInfo; +}; + +const sendLogToSentry = ({level = 'error', error, errorInfo}: SendLogToSentry) => { + Sentry.withScope(scope => { + const {errorCode, message} = errorInfo; + scope.setLevel(level); + + scope.setTag('environment', process.env.NODE_ENV); + + if (error instanceof FetchError) { + scope.setTags({ + endpoint: error.endpoint, + url: window.location.href, + errorCode, + errorMessage: message, + status: error.status, + // requestBody: JSON.stringify(error.requestBody), + method: error.method, + }); + + Sentry.captureMessage(`${errorCode}`); + } else if (error instanceof Error) { + scope.setTags({ + url: window.location.href, + errorCode, + errorMessage: message, + }); + + Sentry.captureMessage(`${errorCode}`); + } else { + scope.setTags({ + url: window.location.href, + errorCode, + message: UNKNOWN_ERROR, + name: UNKNOWN_ERROR, + }); + Sentry.captureMessage(`${errorCode}`); + } + }); +}; + +export default sendLogToSentry; diff --git a/client/src/utils/stepListToActions.ts b/client/src/utils/stepListToActions.ts new file mode 100644 index 000000000..5fe1bb3a7 --- /dev/null +++ b/client/src/utils/stepListToActions.ts @@ -0,0 +1,23 @@ +import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; + +const stepListToAction = (stepList: (BillStep | MemberStep)[]) => { + // (@todari) test용이라 임시로 any 사용할게용... + // Action을 사용하려고 하는데 serviceType의 기존 Action이랑 겹쳐서요~~~ + const actions: ConvertedAction[] = []; + + stepList.forEach(step => { + step.actions.forEach(action => { + actions.push({ + actionId: action.actionId, + name: action.name, + price: action.price ? action.price.toLocaleString() : null, + sequence: action.sequence, + type: step.type, + }); + }); + }); + + return actions; +}; + +export default stepListToAction; diff --git a/client/src/utils/validate/type.ts b/client/src/utils/validate/type.ts new file mode 100644 index 000000000..df81f1644 --- /dev/null +++ b/client/src/utils/validate/type.ts @@ -0,0 +1,5 @@ +export interface ValidateResult { + isValid: boolean; + errorMessage: string | null; + errorInfo?: Record<string, boolean>; +} diff --git a/client/src/utils/validate/validateEventName.ts b/client/src/utils/validate/validateEventName.ts new file mode 100644 index 000000000..93f4ecef1 --- /dev/null +++ b/client/src/utils/validate/validateEventName.ts @@ -0,0 +1,13 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateEventName = (name: string): ValidateResult => { + if (name.length > RULE.maxEventNameLength) { + return {isValid: false, errorMessage: ERROR_MESSAGE.eventName}; + } + return {isValid: true, errorMessage: null}; +}; + +export default validateEventName; diff --git a/client/src/utils/validate/validateEventPassword.ts b/client/src/utils/validate/validateEventPassword.ts new file mode 100644 index 000000000..7075e2f3e --- /dev/null +++ b/client/src/utils/validate/validateEventPassword.ts @@ -0,0 +1,13 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import REGEXP from '@constants/regExp'; + +import {ValidateResult} from './type'; + +const validateEventPassword = (password: string): ValidateResult => { + if (!REGEXP.eventPassword.test(password)) { + return {isValid: false, errorMessage: ERROR_MESSAGE.eventPasswordType}; + } + return {isValid: true, errorMessage: null}; +}; + +export default validateEventPassword; diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts new file mode 100644 index 000000000..bb87122a2 --- /dev/null +++ b/client/src/utils/validate/validateMemberName.ts @@ -0,0 +1,34 @@ +import REGEXP from '@constants/regExp'; +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateMemberName = (name: string): ValidateResult => { + let errorMessage = null; + const validateOnlyString = () => { + if (!REGEXP.memberName.test(name)) return false; + return true; + }; + + const validateLength = () => { + if (name.length > RULE.maxMemberNameLength) return false; + return true; + }; + + const validateEmpty = () => { + if (!name.trim().length) { + errorMessage = ERROR_MESSAGE.preventEmpty; + return false; + } + return true; + }; + + if (validateOnlyString() && validateLength() && validateEmpty()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage: errorMessage || ERROR_MESSAGE.memberName}; +}; + +export default validateMemberName; diff --git a/client/src/utils/validate/validateMemberReportInAction.ts b/client/src/utils/validate/validateMemberReportInAction.ts new file mode 100644 index 000000000..b4e6c2a9a --- /dev/null +++ b/client/src/utils/validate/validateMemberReportInAction.ts @@ -0,0 +1,33 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateMemberReportInAction = (price: string, totalPrice: number): ValidateResult => { + let errorMessage = null; + const numberTypePrice = Number(price); + + const validateOnlyNaturalNumber = () => { + if (!(Number.isInteger(numberTypePrice) && numberTypePrice >= 0)) return false; + return true; + }; + + const validatePrice = () => { + if (numberTypePrice > RULE.maxPrice) return false; + return true; + }; + + const validateUnderTotalPrice = () => { + if (numberTypePrice > totalPrice) return false; + + return true; + }; + + if (validateOnlyNaturalNumber() && validatePrice() && validateUnderTotalPrice()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage: errorMessage || ERROR_MESSAGE.invalidInput}; +}; + +export default validateMemberReportInAction; diff --git a/client/src/utils/validate/validatePurchase.ts b/client/src/utils/validate/validatePurchase.ts new file mode 100644 index 000000000..9915ce8b7 --- /dev/null +++ b/client/src/utils/validate/validatePurchase.ts @@ -0,0 +1,47 @@ +import type {Bill} from 'types/serviceType'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import RULE from '@constants/rule'; +import REGEXP from '@constants/regExp'; + +import {ValidateResult} from './type'; + +const validatePurchase = (inputPair: Bill): ValidateResult => { + const {title, price} = inputPair; + let errorMessage: string | null = null; + + const errorInfo = { + price: false, + title: false, + }; + + const validatePrice = () => { + if (price > RULE.maxPrice) { + errorMessage = ERROR_MESSAGE.purchasePrice; + errorInfo.price = true; + return false; + } + + errorInfo.price = false; + return true; + }; + + const validateTitle = () => { + if (!REGEXP.purchaseTitle.test(title)) { + errorMessage = ERROR_MESSAGE.purchaseTitle; + errorInfo.title = true; + return false; + } + + errorInfo.title = false; + return true; + }; + + if (validatePrice() && validateTitle()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage, errorInfo}; +}; + +export default validatePurchase; diff --git a/client/tsconfig.json b/client/tsconfig.json new file mode 100644 index 000000000..84c7c054a --- /dev/null +++ b/client/tsconfig.json @@ -0,0 +1,53 @@ +{ + "compilerOptions": { + "sourceMap": true, + "module": "ES2020", + "target": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "useDefineForClassFields": true, + "removeComments": true, + "skipLibCheck": true, + + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + + "jsx": "react-jsx", + "strict": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + + "types": ["jest", "@testing-library/jest-dom", "node", "cypress"], + "esModuleInterop": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitAny": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + "jsxImportSource": "@emotion/react", + + "baseUrl": "./src", + "paths": { + "@apis/*": ["apis/*"], + "@assets/*": ["assets/*"], + "@components/*": ["components/*"], + "@constants/*": ["constants/*"], + "@store/*": ["store/*"], + "@hooks/*": ["hooks/*"], + "@mocks/*": ["mocks/*"], + "@pages/*": ["pages/*"], + "@utils/*": ["utils/*"], + "@errors/*": ["errors/*"] + }, + "outDir": "./dist" + }, + "node": true, + "include": ["src", "jest.config.ts", "jest.setup.ts", "cypress/**/*.ts"] +} diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs new file mode 100644 index 000000000..160baf0ca --- /dev/null +++ b/client/webpack.common.mjs @@ -0,0 +1,60 @@ +import path from 'path'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import {ModifySourcePlugin, ConcatOperation} from 'modify-source-webpack-plugin'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default { + entry: './src/index.tsx', + resolve: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + alias: { + '@apis': path.resolve(__dirname, 'src/apis/'), + '@assets': path.resolve(__dirname, 'src/assets/'), + '@components': path.resolve(__dirname, 'src/components/'), + '@constants': path.resolve(__dirname, 'src/constants/'), + '@hooks': path.resolve(__dirname, 'src/hooks/'), + '@store': path.resolve(__dirname, 'src/store/'), + '@mocks': path.resolve(__dirname, 'src/mocks/'), + '@pages': path.resolve(__dirname, 'src/pages/'), + '@utils': path.resolve(__dirname, 'src/utils/'), + '@errors': path.resolve(__dirname, 'src/errors/'), + }, + }, + module: { + rules: [ + { + test: /\.tsx?$/, + loader: 'ts-loader', + exclude: /node_modules/, + }, + { + test: /\.svg$/, + use: [ + { + loader: '@svgr/webpack', + }, + ], + }, + ], + }, + plugins: [ + new HtmlWebpackPlugin({ + template: './index.html', + hash: true, + favicon: './favicon.ico', + }), + new ForkTsCheckerWebpackPlugin(), + new ModifySourcePlugin({ + rules: [ + { + test: /\.tsx$/i, + operations: [new ConcatOperation('start', '/** @jsxImportSource @emotion/react */\n\n')], + }, + ], + }), + ], +}; diff --git a/client/webpack.dev.mjs b/client/webpack.dev.mjs new file mode 100644 index 000000000..5ad42ed45 --- /dev/null +++ b/client/webpack.dev.mjs @@ -0,0 +1,33 @@ +import path from 'path'; +import {merge} from 'webpack-merge'; +import Dotenv from 'dotenv-webpack'; +import common from './webpack.common.mjs'; +import {fileURLToPath} from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default merge(common, { + mode: 'development', + output: { + filename: '[name].js', + chunkFilename: '[id].chunk.js', + path: path.resolve(__dirname, 'dist'), + clean: true, + publicPath: '/', + }, + devtool: 'eval-source-map', + devServer: { + port: 3000, + historyApiFallback: true, + hot: true, + client: { + overlay: false, + }, + }, + plugins: [ + new Dotenv({ + path: '.env.dev', + }), + ], +}); diff --git a/client/webpack.prod.mjs b/client/webpack.prod.mjs new file mode 100644 index 000000000..1cf3bc7d1 --- /dev/null +++ b/client/webpack.prod.mjs @@ -0,0 +1,31 @@ +import path from 'path'; +import {merge} from 'webpack-merge'; +import Dotenv from 'dotenv-webpack'; +import common from './webpack.common.mjs'; +import {fileURLToPath} from 'url'; +import {sentryWebpackPlugin} from '@sentry/webpack-plugin'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default merge(common, { + mode: 'production', + output: { + filename: '[name].[hash].js', + chunkFilename: '[id].[hash].chunk.js', + path: path.resolve(__dirname, 'dist'), + clean: true, + publicPath: '/', + }, + devtool: 'source-map', + plugins: [ + new Dotenv({ + path: '.env.prod', + }), + sentryWebpackPlugin({ + authToken: process.env.SENTRY_AUTH_TOKEN, + org: 'wtc-o6', + project: 'javascript-react', + }), + ], +}); From 038fd4a2704f1c951b5d8f49ebac57bb0b646037 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 23 Aug 2024 11:49:45 +0900 Subject: [PATCH 222/273] =?UTF-8?q?feat:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=EC=9D=B4=20=EC=97=86=EC=9D=84=20=EB=95=8C=20=ED=99=88?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EC=97=86?= =?UTF-8?q?=EB=8B=A4=EA=B3=A0=20=EB=9D=84=EC=9A=B0=EA=B8=B0=20(#520)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 데이터가 없는 경우 없다고 띄우는 기능 추가 * feat: 지출 상세 데이터를 return하도록 함 --- .../MemberReportList/MemberReportList.tsx | 20 +++++++++--- client/src/components/StepList/StepList.tsx | 32 ++++++++++++------- .../useSearchMemberReportList.tsx | 1 + 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx index 1004540fa..21da76bed 100644 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -1,11 +1,11 @@ -import {ExpenseList, Flex, Input} from 'haengdong-design'; -import React, {useState} from 'react'; +import {ExpenseList, Flex, Input, Text} from 'haengdong-design'; +import React, {useEffect, useState} from 'react'; import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; const MemberReportList = () => { const [name, setName] = useState(''); - const {memberReportSearchList} = useSearchMemberReportList({name}); + const {memberReportSearchList, memberReportList} = useSearchMemberReportList({name}); const changeName = ({target}: React.ChangeEvent<HTMLInputElement>) => { setName(target.value); @@ -13,8 +13,18 @@ const MemberReportList = () => { return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - <Input inputType="search" value={name} onChange={changeName} placeholder="참여자 이름" /> - <ExpenseList expenseList={memberReportSearchList} /> + {memberReportList.length > 0 ? ( + <> + <Input inputType="search" value={name} onChange={changeName} placeholder="참여자 이름" /> + {memberReportSearchList.length !== 0 && <ExpenseList expenseList={memberReportSearchList} />} + </> + ) : ( + <Flex width="100%" justifyContent="center"> + <Text size="body" textColor="gray" style={{paddingTop: '1rem'}}> + 지금은 참여자가 한 명도 없어요. :( + </Text> + </Flex> + )} </Flex> ); }; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index d6a507247..c08f1b7a3 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,4 +1,4 @@ -import {Flex} from 'haengdong-design'; +import {Flex, Text} from 'haengdong-design'; import {useEffect, useMemo, useState} from 'react'; import {BillStep, MemberStep} from 'types/serviceType'; @@ -58,17 +58,25 @@ const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - {stepList.map((step, index) => ( - <Step - index={index} - step={step} - lastBillItemIndex={lastBillItemIndex} - lastItemIndex={lastItemIndex} - key={`${step.stepName}${index}`} - isAddEditableItem={isAddEditableItem} - setIsAddEditableItem={setIsAddEditableItem} - /> - ))} + {stepList.length > 0 ? ( + stepList.map((step, index) => ( + <Step + index={index} + step={step} + lastBillItemIndex={lastBillItemIndex} + lastItemIndex={lastItemIndex} + key={`${step.stepName}${index}`} + isAddEditableItem={isAddEditableItem} + setIsAddEditableItem={setIsAddEditableItem} + /> + )) + ) : ( + <Flex width="100%" justifyContent="center"> + <Text size="body" textColor="gray" style={{paddingTop: '1rem'}}> + 지금은 지출 내역이 없어요. :( + </Text> + </Flex> + )} </Flex> ); }; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx index 4a967e45c..58608062b 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -10,6 +10,7 @@ const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { return { memberReportSearchList: memberReportList.filter(memberReport => memberReport.name.includes(name)), + memberReportList, }; }; From 1c559679be734c0df784f1c7ca720a85e2c94460 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 23 Aug 2024 12:01:03 +0900 Subject: [PATCH 223/273] =?UTF-8?q?chore:=20=EB=9D=BC=EC=9D=B4=EB=B8=8C?= =?UTF-8?q?=EB=9F=AC=EB=A6=AC=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20(#5?= =?UTF-8?q?25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/package-lock.json | 8 ++++---- client/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 61a529538..6625b0479 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.81", + "haengdong-design": "^0.1.82", "jest-canvas-mock": "^2.5.2", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", @@ -10171,9 +10171,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.81", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.81.tgz", - "integrity": "sha512-IiXkt0zXSEmn7vstTLOeNZLFS35JO8lXbXavM55wdyAJd+w0e5kfRxyDk/K2oSiAnX2c2YPiGep/A0x2/gZPDg==", + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.82.tgz", + "integrity": "sha512-AjVvLle+7N71d8cDkSTHyyYTCuANhlppcBaS3qwv4wTnJJrn68mpWUKQ1Lt2lUt8WMRmZuoF2Bql7t0LHMyodQ==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index 6d673dd06..bd117af40 100644 --- a/client/package.json +++ b/client/package.json @@ -69,7 +69,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.81", + "haengdong-design": "^0.1.82", "jest-canvas-mock": "^2.5.2", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", From ac26e958d675d1b392048a8df0cd84ece57e8946 Mon Sep 17 00:00:00 2001 From: pakxe <pigkill40@naver.com> Date: Fri, 23 Aug 2024 12:52:48 +0900 Subject: [PATCH 224/273] =?UTF-8?q?chore:=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/EditableItem/EditableItem.Input.tsx | 6 ++++-- .../src/components/EditableItem/EditableItem.stories.tsx | 8 +++++++- .../PutAndDeleteBillActionModal.tsx | 5 +++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/HDesign/src/components/EditableItem/EditableItem.Input.tsx index c0a08bc0e..7c7ebe0ea 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.tsx +++ b/HDesign/src/components/EditableItem/EditableItem.Input.tsx @@ -29,10 +29,12 @@ export const EditableItemInput = forwardRef<HTMLInputElement, InputProps>(functi return ( <div css={inputWrapperStyle}> + <input type="number" /> + <Flex flexDirection="row"> - <div ref={shadowRef} css={editingContainerStyle}> + {/* <div ref={shadowRef} css={editingContainerStyle}> <Text size={textSize}>{htmlProps.value || htmlProps.placeholder}</Text> - </div> + </div> */} {isFixed && <IsFixedIcon />} <div css={underlineStyle({theme, hasError, hasFocus})}> <input diff --git a/HDesign/src/components/EditableItem/EditableItem.stories.tsx b/HDesign/src/components/EditableItem/EditableItem.stories.tsx index 38406727e..dcd785171 100644 --- a/HDesign/src/components/EditableItem/EditableItem.stories.tsx +++ b/HDesign/src/components/EditableItem/EditableItem.stories.tsx @@ -47,7 +47,13 @@ export const Playground: Story = { <Flex gap="0.25rem" alignItems="center"> <EditableItem.Input value={value2} - onChange={e => setValue2(e.target.value)} + onChange={e => { + // 숫자인 경우 막아야됨 + if (isNaN(parseInt(e.target.value))) alert('안녕'); + else { + setValue2(e.target.value); + } + }} placeholder="0" type="number" style={{textAlign: 'right'}} diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index 5f7d4501e..de88a7128 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -1,6 +1,7 @@ import type {BillAction} from 'types/serviceType'; import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; +import {useEffect} from 'react'; import validatePurchase from '@utils/validate/validatePurchase'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; @@ -64,6 +65,10 @@ const PutAndDeleteBillActionModal = ({ actions.find(({actionId}) => actionId === billAction.actionId), )[0].members; + useEffect(() => { + console.log(inputList); + }, [inputList]); + return ( <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> <form From 65b12285db12a458d7c75e0fe3f27bc4fcb00c43 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:21:16 +0900 Subject: [PATCH 225/273] =?UTF-8?q?feat:=20=ED=96=89=EB=8F=99=EB=8C=80?= =?UTF-8?q?=EC=9E=A5=20v1.0.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe <pigkill40@naver.com> * design: 기본 css style 초기화 작업 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * design: 전역 스타일링 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우터 셋팅 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 앱의 진입점 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우트 경로 설정 Co-authored-by: pakxe <pigkill40@naver.com> * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 인원 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Input component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Title component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: BottomSheet component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 메서드 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 코드 컨벤션 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: 메서드 순서 변경 Co-authored-by: Arachne <jhg2819@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> authored-by: khabh <khabh@naver.com> * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 <rhymint@gmail.com> * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * refactor: global style app과 index에 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> --------- Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * style: lint 적용 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers<HTMLElement>' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * feat: BottomSheet 지출 부분 삭제 & input autoFocus (#433) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe <pigkill40@naver.com> * design: 기본 css style 초기화 작업 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * design: 전역 스타일링 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우터 셋팅 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 앱의 진입점 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우트 경로 설정 Co-authored-by: pakxe <pigkill40@naver.com> * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 인원 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Input component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Title component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: BottomSheet component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 메서드 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 코드 컨벤션 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: 메서드 순서 변경 Co-authored-by: Arachne <jhg2819@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> authored-by: khabh <khabh@naver.com> * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 <rhymint@gmail.com> * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * refactor: global style app과 index에 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> --------- Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * style: lint 적용 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers<HTMLElement>' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * fix: 사용하지 않는 지출 Modal Input 삭제 * remove: 지출 추가 로직 변경으로 인해 사용하지 않는 파일 제거 * feat: 첫번째 Input에 focus 적용 * feat: 첫번째 DynamicInput에 autoFocus 적용 * fix: StepListProps 속성이 없어서 발생하는 에러 해결 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: juha <khabh@naver.com> Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * fix: height가 짤리는 버그 해결 (#434) * fix: 차등 적용 인원이 2명일 때 계산되지 않는 버그 (#435) * fix: 나머지 1명만 조정치가 아닐 때 계산이 되지 않았던 버그 수정 * test: 2명일 때의 테스트 진행 * fix: 마지막 사람이 값이 변경될 수 없으므로 (input = disabled 처리) 관련 로직 훅에서 제거 * test: 발생할 수 없는 테스트 제거 * feat: 랜딩페이지 구현 (#418) * feat: 랜딩페이지 구현 * style: lint 적용 * fix: 문구 수정 * style: lint 적용 * fix: 랜딩페이지 화면의 변화에 따른 e2e 테스트 코드 변경 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> * fix: 랜딩페이지 Nav 버그 수정 (#438) * chore: 사용하지 않는 import 제거 * fix: maxWidth를 추가하여 데스크탑에서 Nav가 정상적으로 렌더링되도록 수정 * fix: totalPrice를 새로운 입력값으로 넘겨주지 않았던 문제 해결 (#442) * fix: 배경색상 height 버그 (#443) * chore: 사용하지 않는 코드 제거 * fix: 배경 heigth가 잘리는 문제를 background color를 넣어 해결 * fix: 백그라운드 수정 (#447) * fix: 멤버가 변동됐을 때 지출 상세 정보 데이터가 날라가지 않는 버그 수정 (#448) * fix: 차등 정산 모달에서 수정 완료 버튼을 누를 때 보내는 2개의 api의 순서를 보장하고 변동이 없으면 요청을 보내지 않도록 함 (#455) * feat: callback을 넘겨받아 api 요청 순서를 보장할 수 있도록 함 * fix: 지출 내역을 수정하고 나서 정상 응답이 와야 차등 정산 요청을 보내도록 함 * feat: 변경이 발생한 것에 대해서만 요청이 가도록 수정 * feat: 모달 자동 닫히도록 onClose전달 * feat: onClose를 전달해 모달을 닫는 함수를 스스로 호출하도록 함 * test: 훅에서 받는 인자가 수정되었으므로 이를 반영 * feat: onSuccessCallBack 을 없앰 * feat: Step에 stepName 반영하기 (#452) * feat: 서버로 부터 받은 stepName 출력 * feat: 마지막 action의 stepName에서 1을 더한 값을 새로 생성한 stepName에 넣기 * chore: 백엔드의 요청으로 인해 인원수 click시 BottomSheet가 띄워지지 않도록 주석처리 * fix: async, await 이 없어서 api 순서 보장이 안되기 때문에 추가 (#462) * [FE] 지출 Input 금액 default 변경 및 autoFocus (#470) * feat: 지출 내역 금액 default가 0이 아닌 ‘’로 변경 * feat: 지출 내역을 추가하면 title에 autoFocus * feat: enter 키를 눌렀을 때 handleBlurBillRequest가 실행되는 기능 추가 * feat: StepList에 isFixed 디자인시스템 반영 (#465) * chore: v0.1.77 배포 * chore: 디자인 시스템 적용 * fix: 변동된 금액인지를 나타내는 isFixed prop 추가 * feat: 차등 정산 적용시 신선한 데이터가 바로 반영되지 않고 시간차를 두고 반영되는 부분 수정 (#458) * feat: 차등 정산 내용이 수정되었을 경우 낙관적 업데이트 적용 * feat: any제거하고 타입 적용 * fix: 차등정산 수정 후 다시 로드 시 깜빡이는 현상 해결 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> * feat: 관리자 로그인 페이지에서 스위치가 관리로 활성화되지 않는 버그 (#469) * fix: 관리페이지 로그인에서도 top nav 관리 탭으로 활성화 되도록 수정 * refactor: useEventLogin으로 훅 분리 * refactor: DB 데이터를 drop 할 수 없도록 DB user 권한 수정합니다. (#485) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe <pigkill40@naver.com> * design: 기본 css style 초기화 작업 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * design: 전역 스타일링 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우터 셋팅 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 앱의 진입점 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우트 경로 설정 Co-authored-by: pakxe <pigkill40@naver.com> * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 인원 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Input component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Title component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: BottomSheet component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 메서드 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 코드 컨벤션 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: 메서드 순서 변경 Co-authored-by: Arachne <jhg2819@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> authored-by: khabh <khabh@naver.com> * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 클라이언트 코드 삭제 * refactor: CD workflow main, develop 분리 (#163) * refactor: CD workflow main, develop 분리 및 dockerfile 수정 * refactor: trigger test 브랜치 추가 * refactor: feature/#147 에 push test * refactor: github actions self-hosted runner tag 추가 * refactor: feature/#147 runner 구분 테스트 * refactor: feature/#147 prod runner 구분 테스트 * refactor: feature/#147 prod runner 구분 테스트2 * refactor: feature/#147 prod runner 구분 테스트3 * refactor: feature/#147 prod runner 구분 테스트3 * refactor: prod, dev yml 분리 완료 및 서버 테스트 완료 * feat: 로그 모니터링 환경 구축 (#169) * feat: 예외메시지 구체화 (#161) * feat: 예외 핸들링 추가 * refactor: 예외 메시지 구체화 및 검증 역할 변경 * feat: 에러 코드 추가 * style: 개행 제거 * refactor: 멤버 액션 예외 ErrorCode 분리 * feat: 로깅 추가 * refactor: 액션 이력 조회 리펙토링 (#141) * feat: 멤버 액션 삭제 기능 구현 (#181) * feat: 액션 삭제 기능 구현 중 지출 삭제 가능, 인원 삭제는 아직입니다. * feat: 멤버 액션 삭제 구현 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * feat: 맴버 액션 삭제 기능 구현 * refactor: api 매개변수에 값 넣도록 수정 * fix: 테스트 코드에 action 올바르게 사용하도록 수정 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: pakxe <pigkill40@naver.com> * feat: ERD svg 생성하여 스키마 변경에 대한 이력 관리 (#190) * feat: 지출 액션 수정 기능 구현 (#180) * feat: 지출 액션 삭제 기능 구현 (#179) * feat: 행사의 전체 참여자 중 특정 참여자의 멤버 액션을 모두 삭제하는 기능 구현 (#185) * feat: 행사의 전체 참여자 중 특정 참여자의 멤버 액션을 모두 삭제하는 기능 구현 * test: eventId String으로 변경 * fix: 다른 행사에 있는 멤버 액션도 지워지는 버그 수정 * refactor: 전체 참여자 중에서 특정 참여자를 전부 삭제하는 메서드명 변경 * refactor: 전체 참여자 중에서 특정 참여자를 전부 삭제하는 메서드명 변경 * refactor: MemberActionController 메서드 파라미터 컨벤션 반영 * refactor: conflict resolve * refactor: conflict resolve * feat: 행사에 참여한 전체 인원 조회 기능 구현 (#195) * feat: 행사에 참여한 전체 인원 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * refactor: EventServiceTest, MemberActionRepository 코드 리팩터링 * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: workflows runs-on self-hosted로 변경 Co-authored-by: 3juhwan <13selfesteem91@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * feat: 행사 참여 인원 이름 변경 기능 구현 (#197) * feat: 행사 참여 인원 이름 변경 기능 구현 * refactor: 지출 액션 수정 기능 리펙토링 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * refactor: API 엔드포인트 수정 (#200) * refactor: 멤버 액션, 지출 액션 관련 API 엔드포인트 수정 * refactor: 요청 url에 token을 eventId로 수정 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * feat: 테스트 데이터 클리너 구현 (#199) * feat: 테스트 데이터 클리너 구현 * feat: 테스트 클리너 상수, 메서드 분리 * refactor: 데이터베이스 클리너 적용 * feat: 행사 관리자 비밀번호 추가 (#213) * feat: 이벤트 비밀번호 추 * test: 테스트 공통 설정 클래스 분리 * feat: 어드민 인터셉터 추가 및 jwt 설정 추가 * feat: 이벤트 로그인 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * feat: 쿠키 설정 분리 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * submodule 업데이트 * style: 주석 제거 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * refactor: 로컬 환경 쿠키 secure 옵션 제거 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * test: 접근제어자 수정 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * test: 개행 추가 Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: khabh <khabh@naver.com> * fix: 쿠키 인증 버그 수정 (#222) Co-authored-by: khabh <khabh@naver.com> * fix: 쿠키 인증 버그 수정 (#235) * refactor: 에러 코드 재정의 (#227) * refactor: 에러 코드 재정의 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: 변수를 받는 예외 메세지 수정 Co-authored-by: 3juhwan <13selfesteem91@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * fix: 쿠키 저장 오류 2차 수정 (#237) * fix: 쿠키 인증 버그 수정 Co-authored-by: khabh <khabh@naver.com> * fix: 쿠키 인증 버그 수정 --------- Co-authored-by: khabh <khabh@naver.com> * feat: REST docs를 통한 문서화 (#238) * feat: REST Docs 적용 * feat: REST Docs prettyPrint 및 snippets 적용 * feat: REST Docs에 예외 항목 추가 * test: 행사 액션 이력 조회 테스트 추가 * refactor: 중복된 http-request snippet 제거 * refactor: 사용되지 않는 snippet 제거 * refactor: 빌드 시 자동으로 문서 최신화하도록 gradle 설정 추가 * fix: CookieProperties에 sameSite 옵션 추가 --------- Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * fix: JWT 유효기간 만료 버그 수정 (#248) * fix: JWT 기간 오류 수정 * fix: JWT 기간 오류 수정 * feat: 관리자 권한 확인 API 구현 (#259) * feat: 관리자 권한 확인 API 구현 * backend-pull-request workflow 파일 수정 * feat: HTTP Method를 POST에서 GET으로 변경 * fix: 참여자 삭제 서비스 메서드에 Transactional 추가 (#265) Co-authored-by: 3juhwan <13selfesteem91@naver.com> * refactor: application.yml metrics 추가 (#269) * feat: CI/CD 숙제 (#290) * feat: CI/CD 숙제 (#291) * refactor: 행사 참여 인원 이름 변경 api 수정 (#268) * refactor: 회원 이름 변경 api 여러명으로 추가 * style: 메소드 순서 변경 * fix: rest docs 저장 파일 위치 변경 (#273) * fix: 어드민 권한 확인 불가 버그 수정 (#275) * fix: 행사 로그인 불가 버그 수정 (#283) * fix: CI/CD 트리거 조건에서 server 폴더 조건 제거 (#308) * fix: CI 트리거 조건을 수정 * feat: be-dev CD 트리거 조건에서 server 폴더 제거 * feat: pr 머지시 issue close 기능 추가 (#309) * refactor: yml, Dockerfile TZ Asia/Seoul 적용 (#305) Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> * refactor: actuator health 엔드포인트 설정 변경 (#303) * feat: actuator health 엔드포인트 설정 변경 * refactor: AdminInterceptor log level 변경 --------- Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * feat: 서버 로그 볼륨 마운트 설정 (#300) * feat: 로그 파일 볼륨 설정 * feat: 볼륨 이름 지정 * feat: LogBack 롤링 정책 수정, 로그 레벨에 따른 분리 (#332) * feat: Logback 로그 레벨 분리 * feat: Lockback 로그 레벨 분리 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * fix: 서브 모듈 프로파일 오타 수정 (#334) * refactor: 현재 참여 인원 목록 조회 API 반환 형식 수정 (#361) * feat: BillActionDetail 베이스 코드 생성 (#363) * feat: 액션 이력 조회 v2 기능 구현 (#375) * [BE] 행사 참여 인원 또는 지출 총액 변동시 차등 정산 초기화 기능 구현 (#370) * feat: 지출 액션 수정시 지출 디테일 초기화 기능 구현 * feat: 맴버 액션 삭제시 지출 디테일 초기화 기능 구현 * feat: 맴버 삭제시 지출 디테일 초기화 기능 구현 * fix: 버그 수정 * fix: 버그 수정 * feat: 요구사항 변경에 따른 지출 내역 추가, 지출 액션 삭제 API 수정 (#373) * feat: 지출 내역 추가 시, 상세 내역 생성 로직 추가 * feat: 지출 내역 삭제 시, 상세 내역 삭제 로직 추가 * fix: 멤버가 없는 상황에 대해 0으로 나누는 상황 방지 * refactor: 참여자별 정산 현황 조회 및 액션 이력 조회 수정 (#377) * refactor: BillActionDetail 변경 사항을 반영하여 참여자별 정산 현황 조회하도록 수정 * refactor: 액션 이력 조회 시 지출 액션 고정 금액 설정 여부 필드 추가 * refactor: isFixed 필드 삭제 * refactor: 메서드 이름 변경 * fix: BillAction 변경 로직 수정 * feat: 참여자 개별 지출 금액 수정 및 조회 기능 구현 (#378) * feat: 참여자 개별 지출 금액 수정 기능 구현 * refactor: BillActionDetailService 코드 리팩터링 * docs: restdocs 작성 * feat: 참여자별 지출 금액 조회 기능 구현 * docs: index.adoc에 billActionDetail.adoc 추가 * refactor: 충돌 해결 * feat: 에러를 재현할 수 있는 로그로 수정 (#392) * feat: 로깅에 요청 정보 포함 * feat: 개발 환경 ddl update로 변경 * feat: 예외 처리 및 로깅 형식 수정 (#394) * fix: 리스트 형태의 요청 바디에 null을 넣으면 500이 뜨는 에러 수정 * feat: 로그를 json 형태로 수정 * feat: 예외 처리 및 로깅 형식 수정 (#395) * fix: 리스트 형태의 요청 바디에 null을 넣으면 500이 뜨는 에러 수정 * feat: 로그를 json 형태로 수정 * feat: 로그를 json 인덴트 추가 * refactor: BillActionDetail isFixed 추가 (#405) * fix: 로깅 적용 후 예외 응답 불가 버그 수정 (#413) * feat: 액션 이력 조회 stepName 추가 (#420) * feat: 이슈, PR 템플릿 추가 (#160) (#426) * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * fix: BillAction 수정시 BillDetail 초기화 안되는 버그 수정 * docs: pr issue close 삭제 * feat: 행사 비밀번호 암호화 추가 (#429) * feat: 행사 비밀번호 암호화 추가 * refactor: 비밀번호 암호화 로직 수정 * fix: MessageDigest를 싱글톤으로 관리하지 않도록 수정 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * fix: BillActionDetail 초기화시 totalPrice와 정합성 안맞는 버그 수정 (#460) * fix: BillActionDetail 초기화시 totalPrice와 정합성 안맞는 버그 수정 * refactor: BillActionDetail 초기화 로직 BillAction으로 위임 * style: 메소드 이름 수정 * refactor: BillActionDetail 계산 공통 로직 메소드 분리 * fix: price 분배 로직 버그 수정 * style: 미사용 필드 제거 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * refactor: DB 데이터를 drop 할 수 없도록 DB user 권한 수정 (#484) --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: juha <khabh@naver.com> Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * fix: 배경 색이 잘리는 문제 해결 (#466) * design: 생성 페이지 background 설정 * design: 메인 레이아웃 light gray 색 추가 * design: 홈페이지 padding bottom 2rem 추가 * design: root의 height auto로 설정 및 배경색 제거 * design: 효과없는 height 100% 제거 * design: 바텀시트 삭제로 어드민 페이지 패딩 바텀 조정 * feat: Flex prop min height 속성 추가, 알고보니 min-height 속성이 있어야 화면이 꽉 채워짐 * feat: title과 price에 값이 존재하지 않을 경우 지출 input 닫기 (#472) * feat: 디자인시스템 일부 수정 (#475) * design: 통일성 위해 디자인 수정 * chore: v0.1.78 배포 * chore: hdesign 0.1.78 적용 * chore: v0.1.79 배포 및 적용 * feat: 버튼 로딩 구현 및 이벤트 생성 페이지에 적용 (#476) * design: 통일성 위해 디자인 수정 * chore: v0.1.78 배포 * chore: hdesign 0.1.78 적용 * chore: v0.1.79 배포 및 적용 * chore: lottie-react dependency 추가 * chore: json file 읽을 수 있도록 설정 * feat: button의 loading variants 추가 * chore: v0.1.80 배포 * chore: hdesign 신규 버전 적용 * feat: 행사 생성이 pending 상태이면 button isLoading으로 변경 * style: lint 적용 * chore: lottie-react import ignore 하도록 변경 * fix: lottie-react를 mocking하여 lottie가 렌더링 시 테스트가 실패하지 않도록 변경 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * fix: 행사 생성 완료 페이지 변경 (#478) * fix: placeholder 추가 (#480) * fix: 지출 내역 금액 부분에 문자가 입력되던 오류 수정 (#491) * fix: dropdown animation 버그 수정 (#493) * chore: React-Query devtools 환경 설정 (#463) * chore: devtools 설치 * chore: stale time, gctime 셋팅 임시로 1분 설정 * chore: amplitude 적용 (#335) * feat: react-query에 맞는 error handling 적용 (#415) * chore: 디자인시스템 버전 적용 * rename: 파일 이름 변경 * fix: 사용하지 않는 Error 처리 로직 삭제 * feat: 전역 에러 상태 생성 * fix: 바뀐 파일 이름 적용 * fix: ToastProvider 내에서 에러 처리 로직 제거 * refactor: AppErrorBoundary 및 QueryClientBoundary를 통한 에러 처리 * fix: 사용하지 않는 코드 임시적으로 주석 처리 TODO: 테스트 코드 역할 위임 * mover: AppErrorBoundary, QueryClientBoundary 코드 위치 변경 * fix: test 코드 변경 * chore: jest path alias 적용 * test: AppErrorBoundary 테스트코드 작성 * remove: 사용하지 않는 코드 삭제 * fix: 사용하지 않는 코드 주석처리 * fix: AppErrorBoundary, QueryClientBoundary 로직 수정 * test: AppErrorBoundary test코드 작성 * style: lint 적용 * feat: App에 ErrorBoundary 추가 * feat: UnhandledErrorBoundary 컴포넌트 구현 * feat: 에러를 구독하며 핸들링되는 에러면 토스트, 핸들링 불가능한 에러면 에러 바운더리를 띄우도록 하는 캐처 구현 * feat: 에러 페이지에 메일 추가 * feat: errorInfo를 안에서 구현하는 것이 아닌 구현된 것을 인자로 받도록 수정 * chore: 파일 위치 수정에 따라 import 경로 수정 * chore: 불필요해진 파일 제거 * chore: 개행 추가 * feat: ErrorCatcher에 대한 테스트 코드 작성 * feat: Toast의 showingTime 을 옵셔널로 수정 * chore: 없어진 컴포넌트를 renderHook에서 제거 * refactor: return문이 반복되는 부분을 리펙터링 * feat: useToast에 대한 테스트코드 작성 * chore: 사용하지 않는 파일 제거 * chore: 불필요한 파일이 커버리지에 뜨지 않도록 ignore에 추가 * rename: 파일명 오타 수정 * chore: import 경로 수정 * chore: 병힙 * chore: 라이브러리 오류로 인해 테스트 통과가 안되므로 디자인 시스템 라이브러리 다운그레이드 --------- Co-authored-by: pakxe <pigkill40@naver.com> * fix 행사 인원 이름 변경시 지출 상세의 이름이 변경되지 않는 버그 수정 (#500) * fix: 로딩 라이브러리 도입으로 인해 테스트가 터지는 문제를 해결 (#501) * fix: canvas를 로딩하기 위한 라이브러리 설치후 jest.setup에 적용 * chore: 불필요한 import 제거 * fix: 참여자 이름 변경시 지출 상세 이름 변경 안되는 버그 수정 (#508) * feat: 비밀번호 4자리 넘게 적용되는 오류 수정 (#503) * chore: v0.1.81 배포 * fix: 비밀번호 4자리 넘게 입력 가능한 오류 수정 * fix: BottomSheet가 조건부 렌더링 되도록 변경 (#506) * feat: 홈페이지에서 지출 내역 눌렀을 때 차등 정산 모달 뜨기 (#507) * feat: 홈화면에서 지출 내역 상세 모달이 뜨도록 함 * chore: 사용하지 않는 코드 제거 * feat: 행동대장 흔듯콘(파비콘), 로고 적용 (#496) * feat: 새로운 행동 강아지 삽입 * feat: favicon 적용 * fix: 흔듯콘 logo에 사용 * style: lint 적용 --------- Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: meta tag 링크 복사 이미지와 설명 추가 (#510) * feat: og tag 설정 (링크 붙여넣기 할 때 이미지와 소개글 나오도록 설정) * feat: 행댕이 이미지 삽입 * feat: description 수정 * fix: 지출 내역 및 전체 참여자 버그 (#511) * fix: 전체 참여자 삭제 후 수정 요청 순서 보장 * fix: 이름 변경 수정이 존재하지 않는 상황에서도 nameChange api 요청이 전송되지 않도록 수정 * fix: 현재 필요하지 않는 hasDragHandler를 false로 변경 * fix: 인원 변동 요청을 한 후 input에 value 값이 초기화 되지 않는 버그 해결 * fix: bill 액션이 없는 상태에서 BillInput을 닫을 때 BillContainer가 사리지지 않는 버그 해결 * chore: console.log 삭제 * fix: build를 위한 없는 파일 import 제거 (#513) * fix: default 값이 빈문자열로 변경 * chore: build를 방해하는 import 제거 * fix: og tag 이미지 해상도 변경 (#515) * feat: 행동대장 v1.0.0 (#516) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-authored-by: pakxe <pigkill40@naver.com> * design: 기본 css style 초기화 작업 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 메인 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 이벤트 생성 완료 페이지 퍼블리싱 Co-authored-by: pakxe <pigkill40@naver.com> * design: 전역 스타일링 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우터 셋팅 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 앱의 진입점 설정 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 라우트 경로 설정 Co-authored-by: pakxe <pigkill40@naver.com> * fix: 라우트 이동 시 페이지가 제대로 보이지 않던 문제 해결 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 모달 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 스위치 컴포넌트 생성 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 초기인원 세팅 기능 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행동 추가를 위한 모달 컨텐츠 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 지출 내역 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 인원 관리 기능구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 행사관리 페이지 퍼블리싱 및 구현 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 해커톤 로그 출력을 위한 임시처리 Co-authored-by: pakxe <pigkill40@naver.com> * feat: 프로젝트 초기 설정 * feat: 엔티티 추가 * refactor: gitignore 수정 * refactor: 엔티티 컬럼명 변경 * chore: path alias 설정 및 lint 마이그레이션 * [FE] 해커톤 범위 디자인시스템 구현 (#36) * feat: FixedButton Component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Input component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: Title component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * feat: BottomSheet component 구현 Co-authored-by: soi-ha <soy2302ten@gmail.com> * fix: BottomSheet component 빌드 오류 해결 * move: 전체적인 파일 경로 수정정 * move: 전체적인 파일 경로 수정 * fix: npm build를 위한 설정 변경 * feat: IconButton Component 추가 * design: IconButton height가 제대로 적용되지 않는 오류 수정 * feat: npm 배포를 위한 환경설정 및 파일 경로 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: eslint 적용 * design: globalStyle root BG 변경 * design: globalStyle background 변경 * fix: Title type 변경 * chore: storybook svg 사용을 위한 main.ts 설정 * feat: BillItem component 구현 * feat: InOutItem Component 구현 * feat: StepItemComponent 구현 * chore: storybook preview background color 수정 * chore: tsconfig.json sourcemap 속성 변경 * chore: npm v0.1.0 배포 --------- Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: CI/CD 파이프라인 구축 (#42) * feat: ci/cd 구축 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * fix: ci/cd 디폴트 경로 변경 * feat: cicd 테스트 객체 제거 * feat: cicd 테스트 객체 제거 * feat: 행사 생성 기능 구현 * feat: 지출 내역 추가 기능 구현 * refactor: event의 마지막 action 순서 조회 로직 수정 * refactor: BillAction fetch type 수정 * test: 불필요한 mocking 제거 * refactor: 중요도에 따라 필드 순서 변경 * fix: BillAction 저장 Dto 검증 추가 * [FE] 디자인 시스템 수정 (#46) * chore: storybook 관련 dependency 설치 * fix: Text component 수정 * feat: TextButton Component 구현 * fix: Title Component 수정 * feat: input component background color InputType 추가 및 입력제거 아이콘 변경 * feat: Switch component 구현 * feat: TopNav component 구현 * feat: Tab 컴포넌트 구현 * refactor: Tab type type.ts로 분리 * feature: ExpenseList component 구현 * design: 폰트 size, weight, color 수정 * feat: BillItem에 드래그핸들러 포함 여부를 props로 받을 수 있도록 구현 * design: 드래그핸들러 여부에 따라 패딩을 다르게 하도록 수정 * feat: Flex 컴포넌트 구현 * feat: 잡고 이동할 수 있는 DragHandleItem 컴포넌트 모습 구현 아직 잡고 이동하는 기능은 없습니다. * chore: DragHandleItem 컴포넌트의 스토리북 작성 * feat: BillItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * feat: InOutItem 컴포넌트가 DragHandleItem, Flex 컴포넌트를 사용하도록 수정 * fix: 스토리북에서 배열 형태로 모습 테스트를 할 수 있도록 type 수정 * feat: InOutItem에서 드래그 여부를 할 수 있도록 type 추가 * feat: StepItem 컴포넌트가 Flex 컴포넌트를 사용하도록 대체 * feat: children을 포함하는 타입을 빠르게 선언하기 위한 타입 구현 * feat: 카멜 케이스를 케밥 케이스의 문자열로 반환하는 함수 구현 * design: 사용하지 않게된 css 객체 제거 * feat: COLORS 자동완성을 위한 타입 추가 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: BillAction 검증 로직 수정 * refactor: 지출 내역 추가 로직 수정 * feat: BillAction과 Action cascade 옵션과 orphanRemoval 옵션 변경 * test: event save 로직 분리 * test: DisplayName 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 경계값 테스트로 변경 Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> * test: 지출 내역 생성 테스트 수정 * feat: PR 후 테스트 리포트 발행 기능 추가 (#56) * test: 미사용 test class 제거 * [BE] 인원 변동 기능 구현 (#47) * feat: 인원 변동 기능 구현 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 메서드 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 코드 컨벤션 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: 멤버 액션 생성 클래스 분리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: MemberActionFactory 코드 리팩터링 * refactor: DTO 클래스명 리팩터링 * refactor: MemberActionRepository Lazy Loading 적용 * test: MemberActionFactory createMemberActions 결과 검증 테스트 추가 * refactor: 컨벤션에 맞게 수정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: memberActions를 복사해서 내림차순 정렬하도록 수정, 검증 로직 내부로 이동 * refactor: 컨벤션에 맞게 수정 * feat: 사용자 이름이 중복 입력되는 예외 상황 검증 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> * refactor: 메서드 순서 변경 Co-authored-by: Arachne <jhg2819@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> authored-by: khabh <khabh@naver.com> * [BE] 패키지 구조 변경 (#62) * chore: 패키지 구조 변경 * test: 패키지 구조 변경 --------- Co-authored-by: Arachneee <jhg2819@naver.com> * feat: api wrapping 객체 생성 (#68) Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * [FE] @svgr/webpack 플러그인 설치 * feat: 행사 정보 조회 기능 구현 (#75) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> * [BE] 설정 파일 서브 모듈 생성 (#82) * feat: 설정 파일을 서브모듈로 관리 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 테스트 설정 파일 추가 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 도커 파일 내 profile 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: gitflow에 서브 모듈 설정 Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> --------- Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachne <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * [BE] 요청 데이터가 맵핑되지 않는 문제 해결 (#86) Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: khabh <khabh@naver.com> * feat: 현재 참여 인원 조회 기능 구현 (#70) * design: 탭 컴포넌트 height 소수점 문제 (#51) * design: tab height 소수점 문제 해결 * fix: tab component after 가상태그를 활용해서 div 태그 제거 * chore: 배포, CI 및 테스트 전략 수립 #32 * chore: frontend-push yaml 파일 추가 * chore: eslint-import-resolver-typescript 추가 * chore: eslint explicit-module-boundary-types 옵션 해제 * chore: noUnused tsconfig.json 설정 제거 * chore: eslint no-use-before-define 옵션 제거 * style: eslint 적용 * fix: workflow yml 파일 수정 * feat: 행사 생성 페이지 구현 (#87) * feat: 행사 생성 페이지 디자인시스템 적용 * design : index.css 수정 * feat: 행사 생성 api 연결 * style: lint 적용 * feat: 행사 홈 페이지 구현 (#88) * chore: env와 디자인 시스템 라이브러리 설치 * chore: 현재 불필요한 옵션 비활성화 * chore: env를 사용하기 위한 환경 세팅 * feat: 디자인 시스템 provider 사용 * design: index.css 정한대로 수정 * feat: apiBaseUrl 선언 * feat: router에 Home 페이지 연결 * feat: api호출 시 매번 들어가는 prefix 상수화 * feat: eventId를 타입에 포함시키기 위한 WithEventId 타입 선언 * feat: 지출 내역 추가 api 구현 * feat: 행사 생성 api 구현 * feat: 참여자 목록 갱신 api 구현 * feat: 정산 현황 요청 api 구현 * feat: 행사 이력 조회 api 구현 * feat: 참여자 별 정산 목록 컴포넌트 구현 * feat: 전체 지출 내역 컴포넌트 구현 * feat: router url 논의된 대로 선언 * feat: 정산 현황 검색을 위한 훅 구현 * feat: 스텝 목록을 관리하기 위한 훅 구현 * chore: 정산 현황 목 데이터 작성 * chore: 전체 지출 내역 목 데이터 작성 * feat: 홈 페이지 레이아웃 구현 * feat: 홈 페이지 안에 들어갈 컨텐츠 구현 * feat: Home -> HomePage로 import 할 수 있도록 export 작성 * feat: 스텝 목록에 필요한 타입 선언 * chore: url 경로 포멧 변경에 따른 수정 * chore: package-lock 업로드 * chore: import 개행 추가 * chore: 디자인 시스템 업데이트 * fix: inOutType 대문자로 넘기도록 수정 * feat: TopNav 추가 * chore: 사용하지 않는 util라이브러리 삭제 * chore: dotenv 세팅 수정 * feat: 현재 참여자 검색 component 생성 (#78) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: search 컴포넌트 구현 * design: input 컴포넌트 마진 추가로 searchTerms 마진 추가 * refactor: 사용하지 않는 onChange 제거 * refactor: setKeyword -> setState로 setter라는 의미 명시 * style: early return 뒤 개행 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: CORS 설정 (#90) * feat: CORS 설정 * refactor: CORS 설정 분리 * test: yml에 CORS 설정 추가 * feat: Origin 추가 * feat: Cors 설정에 HTTP OPTIONS 메서드 추가 --------- Co-authored-by: juha <khabh@naver.com> * feat: 행사 커스텀 예외 처리 (#92) * feat: 행사 커스텀 예외 처리 * feat: 커스텀 예외 적용 * feat: 참여자별 정산 현황 조회 기능 구현 (#77) * feat: api 명세에서 행사 url을 표현하는 용어와 전달 방식 수정 (#98) * feat: 행사 url 명세를 token에서 eventId로 변경 * feat: 행사 url을 헤더가 아닌 바디로 전달 * test: 행사 생성 컨트롤러 테스트 수정 * feat: 행사 생성 응답 dto에 필드명 수정 * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 (#102) * feat: 기본 프로파일에서 DB를 MySQL을 H2로 변경 * feat: jpa dll-auto none에서 create로 변경 * refactor: 지출 내역 생성 및 현재 참여 인원 조회 예외 메시지 변경 (#100) * refactor: 지출 내역 생성 예외 메시지 변경 * refactor: 현재 인원 조회 예외 메시지 변경 * refactor: 예외 메시지 전달 방법 수정 * refactor: 참여자별 정산 현황 조회 예외 메시지 변경 (#106) * refactor: 행사 생성 API 예외 메세지 및 DTO 검증 애너테이션 추가 (#103) * refactor: 행사 생성 API 예외 메세지 추가 및 DTO 검증 애너테이션 추가 * refactor: 행사 생성 API EventSaveRequest name을 eventName으로 변경 * refactor: 행사 생성 요청 객체 검증 애너테이션 @Size 제거 * refactor: 연속된 공백 검증 및 예외 메세지 상수 사용하도록 리팩터링 * feat: 행사 관리 페이지 구현 (#107) * style: eslint 적용 * chore: typescript with invalid interface loaded as resolver 해결을 위한 eslint-import-resolver-typescript 설치 * chore: SetInitialParticipatns & SetActionModalContent를 Modal의 index.ts에서 export 추가 * design: HDesignProvider 적용 * design: 행사 관리 페이지 퍼블리싱 * design: 초기 인원 설정 Modal 퍼블리싱 * design: 지출내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 Modal 내부 퍼블리싱 * feat: TopNav 추가 및 props 추가 * design: BottomSheet 내부 퍼블리싱 (Input overflow시 scroll) * design: 행사 지출/인원 변동 내역 생성 퍼블리싱 * design: switch와 container의 gap 추가 * design: scroll시 모든 자식 요소가 안 보이는 에러 해결 * design: MainLayout 적용 및 root 태그에 height 적용 * design: 지출 내역 생성 Modal 내부 퍼블리싱 * design: 인원 변동 내역 생성 Modal 내부 퍼블리싱 * chore: develop 브랜치 merge로 인한 수정 * chore: 불필요한 import 삭제 * chore: haengdong-design 버전 업데이트 설치 * remove: 사용하지 않는 파일 제거 * chore: TopNav 수정된 디자인 시스템 설치 및 StepList 수정 주석 추가 * style: lint 적용 * feat: Input 값 입력시 다음 Input이 생성되는 hook 기능 구현 * feat: useDynamicInput에 auto focus 및 scrollIntoView 기능 추가 * feat: 초기 인원 설정 및 인원 변동 내역 Modal에 useDynamicInput 적용 * feat: 지출 내역에 대한 기능 구현 (useDynamicInputPairs 훅 생성) * chore: 불필요한 props 제거 및 backlog 주석 추가 * fix: BottomSheet의 onClick을 통해 submit되는 오류 수정 * fix: setParticipants를 분리하여 참여 인원 관리 * fix: setOrder를 분리하여 지출 내역 차수 관리 * chore: 사용하지 않는 상태 제거 * chore: haengdong-design 버전 업데이트 반영 * fix: 작성된 값을 수정할 수 없는 에러 해결 * chore: 에러 발생 수정에 대한 주석 추가 * chore: 디자인시스템 버전 업데이트 반영 * fix: 예외에서 정의한 메세지를 꺼내지 못하는 오류 해결 (#111) * feat: 퍼블리싱된 페이지 매끄럽게 연결 (#114) * chore: 디자인시스템 업데이트 반영 * feat: fixed button 클릭시 router 반영 * feat: 총 지출 금액 추가 및 StepList 연결 * refactor: 인원 변동 요청 형태 변경 (#117) * feat: 액션 이력 조회 기능 구현 (#76) * feat: 액션 이력 조회 기능 구현 Co-authored-by: 3juhwan <13selfesteem91@naver.com> * feat: 액션 이력 조회 반환 형식 변경 * test: 액션 이력 조회 테스트 삭제 --------- Co-authored-by: 3juhwan <13selfesteem91@naver.com> * chore: frontend yml lint 과정 수정 (#120) * fix: 액션 이력이 없는 경우 빈 리스트 반환 (#122) * fix: 액션 이력 조회 오류 수정 (#124) * fix: HaengdongException 적용 안된 부분 적용 * fix: Transactional 추가 및 StepResponse 로직 수정 * fix: StepResponse 로직 수정 (#126) * test: Gradle, Docker 캐싱을 위한 Feature/#121 test (#128) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * test * after cache * after cache2 * test: Gardle, Docker 캐싱을 위한 Feature/#121 test2 (#130) * refactor: Github Actions Gradle, Docker Build 캐싱 * refactor: Docker 사용하는 포트 번호 수정 * refactor: Docker 사용하는 포트 번호 수정 * after cache * revert: gradle cache, docker cache (#133) * refactor: 애플리케이션 도커 포트 번호 수정 (#134) * refactor: Docker 빌드 성능 개선 (#138) * refactor: 참여자 정산 현황 로직 리펙토링 (#110) * refactor: 참여자 정산 현황 로직 수정 * refactor: forEach -> stream 변경 * chore: storybook chromatic 배포 (#81) * chore: storybook chromatic workfloe * style: EOL 제거 * chore: storybook 배포를 위한 workflow 설정 * chore: storybook 배포를 위한 workflow 설정 * chore: workflow node 설정 추가 * chore: lint flow path 변경 * chore: run lint 수정 * chore: eslint-config-prettier 추가 * chore: lint 적용 * chore: airbnb 제거 * chore: eslint 설정 수정 * chore: chromatic working directory 변경 * feat: 2차 스프린트 API 연결 (#137) * chore: storybook 관련 dependency 설치 * feat: post api에도 response를 받을 수 있도록 수정 * refactor: parameter가 파스칼케이스인 부분을 카멜 케이스로 수정 * feat: 행사명을 가져오는 api 함수 구현 * feat: interface 수정에 따라 body 변경 * feat: 지출 내역을 추가하는 api 연결 * feat: 최초 참여자를 추가하는 api 연결 * feat: 참여자 수를 조정하는 api 연결 * refactor: name -> title로 파라미터명 수정 * feat: 이벤트아이디를 url에서 불러오는 훅 구현 * feat: 지출 내역, 인원 조정 api연결 후 provider로 전파 * feat: url에서 eventId를 받아오도록 추가 * feat: submit이벤트를 form 엘리먼트에 연결 * remove: 사용하지 않는 파일 제거 * feat: useContext를 사용해 총 가격을 불러오도록 연결 * feat: provider를 사용하기 위한 Layout 컴포넌트 추가 * feat: 디자인시스템 수정에 다른 컴포넌트 호출 형태 변경 * chore: 주석 추가 * remove: 사용하지 않는 파일 제거 * feat: router 에 home, admin 경로에서 띄울 컴포넌트 연결 * fix: 변경된 interface에 맞게 body 수정 * feat: 참여자 목록을 넘겨주지 않고, 참여자 타입 전달 * chore: 불필요한 props 삭제 * feat: 공백된 값 제거 * feat: 네비게이션을 위한 구현 * fix: useStepList훅이 context를 반환하도록 수정 * feat: TopNav 추가 * feat: Admin 페이지 구현 * feat: Home 페이지 구현 * chore: 디자인시스템 라이브러리 업데이트 * chore: await 추가 * feat: stepList를 호출하도록 api 연결 * chore: 사용하지 않는 변수 제거 * chore: lint 적용 * feat: steps를 꺼내서 return하도록 수정 * feat: 인원이 있어야 memberNameList를 갱신하도록 로직 작성 * feat: StepList 의 타입 작성 * design: 불필요한 padding 제거 * chore: 관리 탭에서 StepList를 보여주기 위해 임시로 조건문 제거 * feat: 홈 페이지에서 총 지출 금액 표시 * chore: 디자인 시스템 업데이트 * fix: meta tag 설정 - mixed content, scalable 등 * design: 메인 페이지 및 행사 생성 페이지 디자인 수정 * fix: 새로 고침하면 내역이 출력되지 않는 오류 수정 eventId의 변화에 따라 지출 내역을 다시 호출하도록 종속성을 연결하지 않아서 발생한 문제입니다. * chore: Content-Security-Policy 삭제 * fix: FixedButton disabled 속성 추가 * fix: 행사 이름 입력 페이지 FixedButton disalbed 추가 및 공백 제거 * style: lint 적용 * fix: 불필요한 인자를 넘겨주는 것 제거 * chore: 사용되지 않는 import 제거 * fix: 참여자별 지출 내역을 받아오는 api의 엔드포인트 올바르게 수정 * fix: eventId, 전체 검색 결과에 따라 검색 결과가 보여지도록 수정 * design: 이벤트 홈 타이틀과 탭 사이 공백 제거 * feat: 임시로 행사 이름을 표시하도록 수정 * style: 사용하지 않는 변수 및 import 제거 * design: 전역 스크롤바 숨김 처리 * design: 바텀 버튼만큼 contents 위로 올라오도록 변경 * rename: steList 타입 파일 useStepList 폴더로 이동 후 type.ts로 이름 변경 * chore: 디자인시스템 버전 업데이트 * feat: 검색창 placeholder 참여자 이름 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * refactor: 도커 계정 관련 정보 secrets으로 수정 (#139) * feat: 2차 스프린트 디자인 시스템 수정 (#83) * design: Title Component width 100%로 수정 * design: TopNav width 100%로 수정 * fix: index.tsx export 수정 * chore: v0.1.2 배포 * design: input 좌우 1rem 추가 * feat: MainLayout 추가 * chore: v0.1.3 배포 * feat: TopNav none 타입 추가 * chore: storybook-addon-react-router-v6 dev dependency 추가 * fix: ExpenseItem button props 넣을 수 있도록 수정 * design: button cursor pointer 전역설정 * refactor: BottomSheet component 구조 수정 * chore: v0.1.4 배포 * refactor: tab components 합성방식으로 변경 * feat: Flex component backgroundColor 받을 수 있도록 변경 * fix: 주석이 xml 내부에서 적용안되던 오류 해결 * chore: v0.1.5 배포 * refactor: flex background prop 로직 처리 방법 변경 * feat: MainLayout backgroundColor prop 추가 * fix: flex backgroundColor defaultValue 제거 * chore: v0.1.6 배포 * fix: MainLayout margin padding으로 변경 * fix: Switch 및 TopNav 내부 로직 변경 * test: Switch storybook 수정 * fix: TopNav navigate currentPath를 이용하도록 수정 * feat: v0.1.18 배포 * fix: TopNav navigate 변경 * design: tab item과 panel 사이에 gap 넣을 수 있도록 설정 및 flex container 사용 * refactor: in out type uppercase로 수정 * design: in out item font size 변경 및 텍스트 바꿔서 작성한 내용 수정 * test: InOutItem storybook 수정 * chore: v0.1.20 배포 * design: hasDragableItem 비활성화 시 마진 수정 * fix: props 네이밍 스토리북에 반영 * fix: navigate 뒤로가기 3번 발생하는 이슈 해결 * chore: v0.1.22 배포 * fix: Switch 내부의 불필요한 로직 제거 * chore: v0.1.23 배포 * fix: navigate path 로직 변경 * fix: 새로고침 됐을 때 해당 location 페이지를 유지하도록 수정 * style: children이 없는 태그 스스로 닫도록 수정 * style: todo 주석 제거 * chore: v0.1.25 배포 * design: fixedButton position 변경 * chore: v0.1.26 배포 * fix: 라우팅 변경 이동 오류 해결 * chore: v0.1.27 배포 * chore: v0.1.28 배포 * fix: location set 로직을 home 모드에서만 작동하도록 변경 * chore: v0.1.29 배포 * fix: TopNav navigation 로직 외부에서 넣도록 변경 * chore: v0.1.30 배포 * fix: index.ts 경로 문제로 제거 * chore: v0.1.13 배포 * chore: v0.1.32 배포 * fix: Fixed Button 하단 고정되도록 변경 * chore: v0.1.33 배포 * v0.1.35 배포 * fix: 가격과 원을 붙여서 표기 * fix: TopNav가 children이 없어도 작동하도록 변경 * fix: children이 필수가 아니도록 변경 * remove: 사용하지 않는 NavSwitch 제거 * chore: 파이프라인 테스트를 위한 push * chore: 파이프라인 테스트를 위한 push * remove: merge를 위한 /sever dir 삭제 * style: lint 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> * chore: server directory 복구 (#150) * fix: gradlew 권한 버그 수정 (#152) * remove: 서버 코드 삭제 * [FE] 스프린트3 디자인 수정 (#162) * chore: esbuild 설치 및 eslint 업데이트 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: error 및 trash svg 파일 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: token color 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * design: Button 컴포넌트 destructive 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: merge로 생긴 불필요한 태그 제거 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: FixedButton 퍼블리싱 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Input 컴포넌트 focus 및 error시 outline 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: LabelInput 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: Toast 컴포넌트 기능 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: useInput에 focus 기능 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: Toast에서 show를 isShow로 네이밍 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: v0.1.36 배포 * chore: yml 파일 branches를 develop에서 fe-dev로 변경 및 storybook build 명령어 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * style: lint 적용 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: 이태훈 <rhymint@gmail.com> * chore: branch 변경에 따른 yml 파일 수정 (#165) * fix: 스토리북 워크플로우 오류 (#168) * fix: 스토리북 배포를 위한 workflow 수정 * fix: develop 브랜치로 트리거하던 걸 fe-dev 브랜치로 수정 * chore: 스토리북을 배포한 사람의 아이디를 출력하도록 수정 * feat: 토스트 생성 (#166) * feat: Toast 컴포넌트에 position 추가 * feat: 되돌리기 버튼과 클릭했을 시 닫히도록 하는 기능 추가 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * design: 두 개의 svg로고가 같은 크기, 중앙 정렬을 갖도록 svg 파일 수정 * feat: 토스트의 타입, 되돌리기 유무, 닫힘 콜백 타입 추가 * design: isShow로 토스트를 켜고 끄지 않도록하고 마진 수정 * remove: ToastProvider에 합쳐진 파일이므로 제거 * test: 다양한 모습의 토스트를 스토리북으로 시연 * feat: 토스트를 사용하기 위한 Provider와 hook 구현 * test: ToastProvider를 시연하기 위한 스토리북 작성 * feat: Toast, ToastProvider, useToast export * chore: package-lock.json 업데이트 * design: 버튼의 내부 텍스트가 줄넘김 되지 않도록 css 추가 * test: Toast 스토리북 message 수정 * feat: Toast default position을 bottom으로 셋팅 * chore: lint 적용 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: client 디렉토리 reset, 전역 스타일 GlobalStyle을 사용하는 것으로 변경 (#173) * refactor: css를 global style로 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * refactor: global style app과 index에 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: css 파일을 읽기 위한 의존성 삭제 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> --------- Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * design: Button이 disabled일 때 커서가 포인터가 아니도록 수정 (#171) * feat: Input 컴포넌트 관련한 기능 수정, useDynamic-* 훅 관련 오류 수정, 네이밍 통일, 의미를 명확하게 담도록 네이밍 수정 (#143, #183) * chore: hdesign v0.1.37 배포 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * remove: 사용하지 않는 코드 제거 * feat: v0.1.44 배포 input 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * refactor: event/create 페이지 input 작동 방식 변경 및 새로운 input 적용 * design: Input outline boxshadow로 변경 및 우선순위 조정 * feat: 초기 멤버 설정 modal 내의 input 동작 방식 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: LabelInput, LabelGroupInput 등 다양한 Input Component 생성 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: 공백이 존재하는 input 제거 * style: lint 적용 * style: lint 적용 * chore: v0.1.47 배포 * feat: v0.1.49 배포 input sync가 제대로 맞지 않던 오류 수정 errorMessage 제대로 적용되지 않던 오류 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * feat: v0.1.51 배포 * feat: DynamicInput 수정 및 유효성 검사 추가 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: 충돌 병합 * feat: v0.1.52 디자인시스템 배포 * fix: 다음 입력을 기대하는 인풋이 뜨도록 하고 중간 인풋을 삭제했을 때 input 엘리먼트 자체가 사라지도록 구현 * rename: SerPurchase -> AddBillActionListModalContent로 이름 변경 * rename: UpdateParticipants -> AddMemberActionListModalContent 로 이름 변경 * rename: SetPurchase -> SetActionListModal 로 이름 변경 * rename: SetInitialParticipants -> SetInitialMemberListModal 로 이름 변경 * feat: enter가 눌렸을 때 실행할 로직을 훅 안으로 이동 * fix: 0, 1번만 있을 때 2개의 빈 잇풋 엘리먼트가 남아버리는 문제 해결, handleBlur -> deleteEmptyInputElementOnBlur 로 기능을 드러내는 함수명으로 변경 * feat: canSubmit 상태를 관리하는 로직을 함수로 분리 * refactor: 현재 변화중인 targetInput을 가져오는 반복되는 로직을 분리, 선언되어있는 함수 순서를 useEffect, on-* props에 장착되는 함수, 유틸성 함수로 정리 * rename: pages안의 파일에 전부 -Page 를 붙여 컴포넌트 성격을 잘 드러낼 수 있도록 이름 변경 * fix: 인덱스틀 사용해 인풋 쌍을 관리하도록 수정. 인덱스를 사용함에 따라 모든 함수도 인덱스를 사용하도록 수정 * feat: pair당 하나의 인덱스를 갖지만, input element는 두 개이므로 정확한 input element특정을 위해 인덱스를 계산해 focus를 넘겨주도록 구현 * rename: 해당 파일에 이미 도메인과 깊게 얽힌 코드가 내장되어 있으므로 의미를 더 드러내는 이름으로 변경. useDynamicInputPair -> useDynamicBillActionInput * chore: Modal 폴더 내의 이름 변경으로 인해 생긴 import 변동 사항 * fix: 함수가 state를 사용하지 않도록 수정 * feat: type.d.ts에 있던 내용을 옮겨옴 * chore: import 경로 수정 * chore: package-lock 업데이트 * design: Input에 css props 적용 * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * refactor: 리뷰 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * style: lint 적용 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * fix: Toast 2번 import 되던 오류 수정 * chore: yml workflow 수정 * chore: client pr workflow 수정 * chore: client workflow 수정 * chore: workflow 수정 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: jinhokim98 <jinhokim98@users.noreply.github.com> * feat: 변경된 API endpoint로 수정 (#196) * feat: 변경된 API endpoint로 수정 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * chore: 디자인시스템 버전 업데이트 Co-Authored-By: Pakxe <64801796+pakxe@users.noreply.github.com> Co-Authored-By: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: 디자인시스템 hover, mouse, transition animation (#198) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * [FE] ListButton component 생성 (#203) * fix: input delete button onMouseDown 으로 변경 * feat: input 및 button active 속성 추가, input focus 관련 버그 수정 * fix: conflict 해결 * fix: transition이 중복되어 작성된 오류 수정 * feat: v0.1.54 배포 * style: lint 적용 * design: input label text에 transition 적용되도록 구조 변경 * design: BottomSheet 전환에 따른 animation 적용 * chore: v0.1.55 배포 * chore: HDesign workflow run-name 수정 * chore: @swc/chore 설치 * feat: BottomSheet handler drag 추가 * feat: ListComponent 생성 * style: drag threshold 상수화 * style: 중복되는 css 로직 분리 * style: :not 선택자 공통 부분 묶어서 수정 * style: onClose, onOpen 함수명 변경 * feat: 개별 ActionItem 컨트롤을 위한 StepItem 및 BillItem / InOutItem component 구조 변경 (#211) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * feat: DragHandleItem이 BillItem, InOutItem의 역할을 대체할 수 있도록 구조 변경 * remove: 필요하지 않은 BillItem 및 InOut component 제거 * feat: StepItem의 역할을 대신 할 DragHandleItemContainer component 구현 * remove: 필요하지 않은 StepItem component 제거 * test: IconButton component storybook children 변경 * style: lint 적용 * chore: v0.1.58 배포 * feat: 삭제 아이콘을 위한 IconButton component 수정 (#209) * chore: greenColor token 추가 * remove: 사용하지 않는 svg 삭제 * fix: 지난번 변경사항이 반영되지 않은 문제 해결 * fix: 동적으로 변경되는 color를 사용하기 위해 svg 내 fill 및 stroke attribute를 currentColor로 설정 * feat: Icon component 구현 * feat: IconButton Component 구현 * fix: DefaultColor가 제대로 적용되지 않던 오류 수정 * fix: StepItem prop type이 잘못 지정된 오류 수정 * style: lint 적용 * fix: size prop optional로 변경 * test: IconButton storybook props 변경 * fix: 사용하지 않는 css svg 속성 제거 * fix: Icon 위아래 정렬이 맞지 않는 오류 수정 * fix: confirm, error Icon이 제대로 export 되어있지 않던 오류 수정 * feat: Icon, ListButton export * refactor: Icon / IconButton 변경으로 인한 기존 코드 이에 맞게 변경 * fix: 잘못 사용된 주석 변경 * style: lint 적용 * chore: v0.1.57 배포 * test: storybook에서 Icon component가 잘못 사용되던 오류 수정 * refactor: style prop이 여러개인 경우, 객체를 통해 prop 전달하도록 변경 * fix: svg 파일 변경 * feat: 멤버 액션 삭제 기능 구현 + 바뀐 디자인시스템 적용 (#214) * chore: 역할 체인지 위한 저장 * feat: 들어온 인원 삭제 기능 구현 Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> * feat: StepList에 사용되는 타입 파일 작성 * refactor: 전역 타입 선언을 types 디렉토리에서 import하는 형식으로 변경 * refactor: type 관리 변경으로 인한 import 추가 * refactor: Step 내부를 Bill과 Member로 나눔 * fix: 타입 import types 디렉토리로 옮기면서 import 누락 수정 * refactor: member action 훅으로 분리 * refactor: evenPageLayout 파일이름 오류 수정 * refactor: 머지 중 발생한 잔재 처리 * chore: dev dependency로 옮겨야 할 것 옮김 * refactor: index.ts 정의 및 props 이름 변경 * remove: 사용하지 않는 파일 제거 * refactor: index.ts를 통해 import문 줄임 * refactor: 사용하지 않는 타입 제거 * remove: 사용하지 않는 action 함수 제거 * refactor: get out member modal 사용하지 않는 파일로 인해 오류 터지는 현상 해결 * fix: 잘못된 import 수정 -> 새로 만들어진 멤버삭제 api로 연결 * remove: 사용하지 않는 컴포넌트 제거 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 인원 삭제 모달 구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 행동디자인 props 변경으로 인한 수정 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: 행동디자인 최신버전 반영 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 토스트 사용하기 위한 provider 적용 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * feat: 삭제 모달에 현재 인원 숫자 표시 * feat: 삭제 요청 도중 오류가 났을 때 토스트모달 보여주는 기능구현 Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * fix: 에러일 때 error가 throw되도록 수정 * chore: 행동디자인 버전 업데이트 반영 * feat: 다른 차수에 동일한 인원의 액션이 있을 때 삭제 시 경고창을 띄우는 기능 구현 * fix: 행동디자인 변경으로 인해 그에 맞는 새로운 컴포넌트로 변경 * fix: 인덱스가 0일 때 알림을 주지 않았던 현상 해결 * refactor: 행동디자인을 적용하면서 사용하지 않는 스타일 제거 * feat: confirm에서 에러토스트로 변경 (누가 사라져요), 삭제 시 바텀시트 닫히는 기능 구현 * feat: 행동디자인 변경에 따른 BillStepItem 반영 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * style: 안 쓰는 import문 제거 * chore: stepList mock 데이터 변경 * remove: 없어진 inoutitem 반영 --------- Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * fix: FixedButton의 delete button type "button"으로 변경 (#234) * fix: fixedButton의 delete button type button으로 변경 * design: 잘못 적용된 large size 디자인 적용 * fix: IconButton 및 Icon 생성에 따라 내부 구조 변경 * chore: v0.1.60 배포 * feat: 행사생성 flow에서 admin 접근을 위한 비밀번호를 입력받는 기능 추가 (#226) * remove: 중복되는 코드 삭제 * feat: requestPostNewEvent에 password 정보를 보내도록 수정 * fix: SetEventNamePage에서 api를 호출하지 않고, password page로 이동하도록 수정 * feat: SetEventPasswordPage 구현 * fix: 새로 생긴 page에 router가 대응할 수 있도록 수정 * style: lint 적용 * fix: cookie가 제대로 전달되지 않던 오류 수정 * feat: 지출 액션 수정, 삭제 기능 구현 (#230) * feat: 지출액션 수정 삭제 모달 퍼블리싱 * feat: 각 input에 에러 정보를 주기 위한 필드추가 * chore: 다른 곳에서 사용하게 되어서 export 사용 * feat: 지출액션 수정 기능 구현 * feat: 지출액션 삭제 기능 구현 * chore: 최신 행동디자인 버전 반영 * feat: 지출액션 삭제 후 바텀시트 닫기 기능구현 * style: 명시적 형 변환 사용 * refactor: element key 수정 * refactor: 에러메시지 상수화 * refactor: 시멘틱 태그 header -> h2로 바꿉니다 * design: 바텀시트 스타일 변경 * design: 삭제멤버 모달도 올바른 스타일 적용 * feat: 전체 참여자 BottomSheet 내부 디자인 퍼블리싱 (#228) * feat: ListButton 추가 및 디자인, ListButton 클릭시 BottomSheet 띄우기 * chore: css 컴포넌트 upperCase로 되어있는 것 camelCase로 변경 * design: BottomSheet 내부 Title 퍼블리싱 * design: Input과 DeleteButton 퍼블리싱 * design: FixedButton 추가 및 overflow를 위한 paddingBottom 추가 * feat: 초기 인원 설정이 완료되어야 ListButton이 렌더링되도록 변경 * design: 삭제하기 버튼의 size를 css가 아닌 props size로 사용하기 * style: openBottomSheet 상태명을 isOpenBottomSheet로 변경. 외에도 FixedButton BottomSheet와 전체 참여자 BottomSheet 상태명 상세히 변경 * style: InputAndDeleteButton 컴포넌트 파일 분리 * style: ModalBasedOnMemeberCount 파일 분리 * feat: api에러 등의 에러를 잡아 핸들링 (#232) * chore: ErrorBoundary사용 시 에러가 뜨지 않도록 overlay 속성 끔 * feat: 에러 상태를 전역적으로 관라하기 위한 훅과 컨텍스트 구현 * feat: ErrorProvider가 ToastProvider를 감싸도록 작성 * feat: api 콜할 때 이 useFetch훅을 사용해 전역상태로 만들어준 에러를 핸들하도록 구현 * chore: 임시로 만들어둔 useFetch사용 예시 * chore: useFetch의 request에 넘겨주기 위한 response 타입 export * feat: Toast를 수정해 사용하기 위해 임시로 가져옴 * feat: 전역 에러를 옵저빙하면서 에러가 있다면 토스트를 띄우도록 기능 추가 * fix: 타입에 이름이 일치하지 않는 부분 수정 * feat: 서버 에러 code와 에러 메세지를 매칭하는 상수 구현 * chore: msw, react-error-boundary 설치 * chore: 브라우저 환경에서 msw를 사용하기 위한 세팅 파일 설치 * feat: msw를 앱 시작 지점에 연결 * test: 테스트를 위한 간단한 post 모킹 함수 구현 * feat: 핸들되지 않는 에러 또는 지정되지 않은 path로 이동시 보여줄 에러 페이지 구현 * feat: 불필요한 state제거와 type narrowing * feat: 다뤄지지 않는 에러가 발생했을 시 외부로 에러 던지기 * feat: 핸들되는 에러 판단을 위한 함수 구현 * feat: 불필요한 state, setTimeout제거 * feat: 지정되지 않은 path로 이동 시 에러 페이지 띄우도록 함 * feat: 반복되는 숫자 상수화와 불필요한 jsx 주석 제거 * feat: 잡아서 다루지 않는 에러를 위한 에러 바운더리 컴포넌트 구현 * chore: 불필요하게 사용되는 contentType관련 코드 제거 * feat: Toast에 showingTime을 전달해 애니메이션을 지속 시간만큼 유지할 수 있도록 함 * feat: 에러를 일정 시간 후에 초기화하는 책임을 useError에 위임 * feat: 알 수 없는 에러에 대한 에러 메세지와 이름 작성 * feat: 이벤트를 새로 생성하기 위한 api콜을 담당하는 useEvent훅 구현 * feat: useEvent를 사용해 이벤트를 생성하도록 수정 * chore: 불필요한 import 제거 * chore: msw, react-error-boundary 라이브러리 설치 * chore: 사용하지 않는 import와 주석 제거 * refactor: queryFn -> queryFuntion으로 프로퍼티명 변경 * design: Toast 디자인 수정 * chore: msw를 사용하는 코드 주석 처리 * chore: 린트 적용 * fix: /가 하나 더 들어가있던 부분 수정 * fix: 함수가 아닌 객체로 수정 * design: px to rem * refactor: 불필요한 useCallback제거 * chore: fadeIn -> fadeInWithTransformY 식으로 이름 변경 * chore: 빌드 환경 prod와 dev로 구분 (#217) * chore: env.prod, env.dev 를 위한 gitignore 수정 * chore: dev, prod 환경의 공통 설정을 webpack.common.mjs 로 분리 * chore: dev, prod 환경에 따른 webpack 설정을 위해 webpack.dev.mjs, webpack.prod.mjs 생성 * remove: 사용하지 않는 webpack.config.js 파일 제거 * chore: webpack-merge dependency 설치 * chore: package.json 스크립트 수정 * fix: webpack devserver overlay 적용 * fix: webpack.common.mjs 수정 * fix: merge를 통해 발생한 에러 해결 (#246) * fix: setOpenBottomSheet 이름 변경되지 않아 발생한 충돌을 setIsOpenBottomSheet로 변경하여 해결 * chore: msw 사용을 위한 코드 주석처리 * fix: requestPost에서 contentType 분기 삭제로 인해 에러 발생한 것을 분기 추가하면서해결 * fix: input value 수정이 되지 않는 문제 (#253) * fix: propsValue가 변했을 때 value가 수정되도록 수정 * chore: v0.1.61 publish --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * fix: useToast 에러바운더리 문제 해결 (#264) * fix: 디자인시스템 Text 컴포넌트 color prop 받도록 변경 (#257) * refactor: Text Component color prop 받도록 수정 * fix: Text가 사용된 component에 color prop 사용 * chore: v0.1.62 배포 * fix: Text component의 color prop을 textColor로 변경 * chore: v0.1.63 배포 * style: lint 적용 * fix: 디자인시스템 Input value 동기화 오류 수정 (#266) * fix: useInput에 value dependency를 받도록 설정 * chore: v0.1.65 publish * fix: 행동디자인 Search 컴포넌트 기능 제거 (#260) * feat: Search 컴포넌트 검색 기능을 빼서 연관검색어 작동만 하도록 수정 * refactor: term =>match 이름 변경 반영 * feat: 행사 생성 완료 페이지 유저 친화적으로 변경 (#271) * chore: react-copy-to-clipboard dependency 설치 * feat: 행사 링크 복사 기능 구현 * style: lint 적용 * design: toast 위치 변경 * feat: 인원 탈주 시 인원 검색 기능 구현 (#270) * feat: 인원 검색 시 현재 참여 인원 중에서 검색 후 클릭 시 input에 입력되는 기능 구현 * chore: 새로운 행동디자인 버전 반영 * feat: Search 컴포넌트를 이용한 검색기능 구현 * refactor: 훅 반환타입 명시 * feat: 인원 탈주시에만 검색창이 뜨도록 설정 * style: css 불필요한 함수 스타일 제거 * fix: 행동디자인 Search와 props 수정 * chore: 해결된 todo 주석 제거 * refactor: terms => match 이름 변경으로 인한 리팩토링 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 데이터 요청하고 출력하기 (#250) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 전체 참여자 이름 수정 및 삭제 (#276) * feat: requestGetAllMemberList 전체 참여자 조회 요청 함수 생성 * feat: useStepList에 전체 참여자 조회 요청 함수 사용하여 allMemberList 상태에 저장하여 ListButton에 출력하기 * chore: 필요하지 않은 memberNameList(현재 참여자) 삭제 * chore: 이전 커밋에서 삭제된 상태(memberNameList) 대신에 전체 참여자 상태 (allMemberList)로 변경 * feat: get한 전체 참여자 인원을 각 Input에 출력 * chore: ModalBasedOnMemberCount 컴포넌트를 Modal/index.ts에 추가 * chore: 디자인시스템 버전 업데이트 * chore: 디자인시스템 업데이트로 인해 propsValue의 이름을 value로 변경 (이전에는 사용하지 못했음) * feat: 전체 참여자 이름 수정 api 함수 생성 * feat: 전체 참여자 삭제 api 함수 생성 * remove: 불필요한 props drilling으로 인해 파일 분리 삭제 * feat: useSetAllMemberList 훅 생성 & 참여자 이름 변경하는 handleNameChange 생성 (BottomSheet를 닫으면 초기화됨) * feat: 전체 참여자 이름 변경 handleNameChange 구현 * feat: 전체 참여자 이름 삭제 handleClickDeleteButton 기능 생성 * chore: 디자인시스템 업데이트 및 console.log 제거 * feat: 전체 참여자 인원 삭제 api 요청에서 에러가 발생하면 setState를 실행하지 않도록 변경 * chore: 디자인시스템 버전 업데이트 * feat: 참여자 삭제시 리렌더링 시켜주기 * feat: allMemberListBottomSheet를 닫는 함수 훅에 넘겨주기 * fix: toast가 BottomSheet보다 z-index보다 아래여서 띄워지지 않는 에러 발생. z-index 추가 * feat: api 요청시 errorToast 띄워지도록 추가 * feat: input에서 에러 발생시 에러 메세지를 띄우기 & 에러가 발생한 Input에만 에러 테두리 적용 * chore: 참여자 이름 maxLength를 8에서 4로 수정 * feat: 초기 참여자 이름과 현재 참여자 이름을 비교하여 변경된 사항만 서버로 요청하기 * feat: 변경사항이 존재하지 않을 경우 FixedButton일 경우 disabled 기능 구현 * style: 인원수 출력 Text 컴포넌트에 그레이 컬러 추가 * chore: 불필요한 console.log 삭제 * fix: 불필요한 color props 삭제 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: sentry 적용 (#262) * feat: useStepList훅에서 useFetch함수를 사용하여 에러에 대한 책임을 위임 * chore: sentry 사용을 위한 진입점 파일 세팅 * chore: sentry 라이브러리 설치 * chore: sentry env 파일 ignore 추가 * chore: sentry 관련 라이브러리 설치 * chore: 웹팩에 sentry 플러그인 추가 * feat: 다뤄지지 않는 에러에 대한 조건 추가 * chore: sentry 사용을 위한 진입점 파일 수정 * feat: 에러 로그 전송을 위해 에러 정보들을 담은 FetchError 클래스 구현 * chore: 세미콜론 추가 * feat: 에러 발생시 에러 정보를 갖고 있는 FetchError를 throw하도록 수정 * feat: 에러 코드에 맞게 level을 설정해 sentry에 보내는 함수 구현 * feat: sentry 에 endpoint, url, errorCode, message, status, requestBody 로그를 담아 보내는 함수 구현 * feat: 에러를 잡아 sentry로 보낼 수 있도록 catch에서 sentry 로그 함수 호출 * chore: 불필요한 타입 선언 제거 * fix: Primitive타입만 tag의 value에 넘겨줄 수 있으므로 객체를 JSON문자열로 바꿔 넘겨주도록 수정 * feat: FetchError가 Error의 타입을 상속하도록 함 * chore: lint 적용 * fix: body파라미터를 문자열 타입으로 변경 * chore: alert를 띄우지 않기 위해 주석처리 * chore: errors폴더를 alias 에 추가 * feat: UNHANDLED_ERROR -> UNKNOWN_ERROR로 에러 상수 변경 * feat: 다루지 못하는 에러인 경우 에러를 다시 포장하지 않고 그대로 에러바운더리로 던지도록 수정 * chore: 불필요해보이는 코드 주석처리 * feat: 언노운 에러도 sentry에 에러를 보내도록 추가 * feat: 에러 이름을에는 errorCode만 넣도록 수정 * chore: 불필요한 코드가 삽입되어있는 부분 제거 * feat: FetchError에 status 필드 추가 * chore: sentry로 status도 보내도록 추가 * chore: 린트 적용 --------- Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: 3차 데모데이 merge 중 발생한 문제 수정 (#280) * fix: merge 오류 해결 * fix: 누락된 파일 추가 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: requestPost에 대해 response가 있는 post와 없는 post로 분기해 사용하도록함 (#281) * fix: merge 오류 해결 * fix: 누락된 파일 추가 * feat: requestPost를 리스폰스가 있는 post와 리스폰스가 없는 post로 분리 * chore: 린트 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 홈에서 액션 수정 삭제 바텀시트 활성화 버그 (#285) * style: key props index외 다른 값 추가 * style: children 없는 태그 스스로 닫도록 설정 * fix: 홈에서 액션 수정 삭제 되지 않도록 설정 * feat: cookie가 없는 경우 비밀번호 입력 페이지로 이동 (#286) * feat: ConfirmPasswordPage 구현 * feat: api 연결 * fix: 로그인 시 오류가 발생하던 문제 해결 * fix: 잘못 삭제된 sentry 설정 복구 * style: lint 적용 * style: lint 적용 * feat: 데모데이를 위해 페이지 약간 수정 (#289) * chore: 데모데이 시연을 위해 페이지 약간 수정 * chore: 린트 적용 * fix: import 가 안되어있는 부분 수정 (#293) * fix: 인원 탈주 검색 인풋 오류 (#299) * fix: key를 단순 index로 고치니 해결되네 meet in 커밋메시지에 이렇게 적고 싶지 않았는데 개화나서 적음 * fix: 여러개 한 번에 보이던 문제 해결 * style: console log 제거 * fix: 커밋 잘못 올려서;; 여러 개 한 번에 보이는 문제 해결 * chore: hooks폴더 구조 정리 (#312) * fix: import 가 안되어있는 부분 수정 * chore: 윈도우에서도 동작하는 lint 명령어로 수정 * chore: hooks폴더 안의 내용물을 폴더 밖으로 빼냄 * chore: lint 적용 * chore: lint 적용 * chore: @sentry/react 라이브러리 설치 * feat: 전체 참여자 수정 및 삭제 수정 (#315) * feat: 두 배열이 동일한 값인지 비교하는 util 함수 생성 * feat: 수정완료를 클릭해야 삭제 api 요청이 실행되도록 로직 변경 * fix: 삭제 상태 반영으로 인해 nameChange api 요청의 index가 맞지 않는 에러 해결 * feat: 차수 멤버 확인, useFetch 확장, BottomSheet 활성화 수정 (#311) * feat: 드래그핸들아이템컨테이너 상하좌우 텍스트 onClick 메서드 연결 및 우측 위 텍스트 스타일 변경 * feat: 차수 멤버 확인 기능 퍼블리싱 및 구현 * refactor: 차수 event layout에서 outlet context로 내려주는 방식으로 변경 * refactor: 차수 이름 생성 책임 백엔드로 위임 * feat: useFetch onSuccess, onError 기능 추가 * design: 멤버삭제 모달 텍스트 컬러 수정 * refactor: useFetch queryFunction 객체형으로 수정 및 useFetch 적용되지 않았던 부분 적용 * fix: 오류 시 모달 닫히지 않도록 설정 및 멤버 삭제 실패 시 상태 원복 * fix: 입력이 없을 때 bottom sheet 활성화되던 현상 해결 * feat: 지출액션 추가할 때 요청 성공 시 모달이 닫히도록 설정 * feat: 참여 인원 확인 임시 버튼 삭제 (#318) * fix: export default 인데 중괄호가 있었던 문제 해결 * feat: 인원수를 누를 때 현재 지출 참여인원을 확인할 수 있도록 변경 * chore: 행동디자인 최신버전 반영 * feat: bottomSheet maxWidth 768px 되도록 변경 (#321) * feat: 메인, 관리 페이지 설명 글 수정 (#324) * chore: svg 파일 인식을 위한 declare * feat: Logo asset 추가 및 컴포넌트 생성 * feat: 메인페이지 설명 수정 및 로고 적용 * feat: 어드민 페이지 초기 설정 마무리되면 설명문 변경되도록 설정 * fix: useDynamicInput 버그 수정 (#327) * fix: 행사 참여자 글자수 제한 변경에 따른 errorMessage 수정 * feat: 에러가 발생한 Input에 에러 테두리 출력 및 반복 코드 함수화 * feat: input의 값이 빈배열인지 확인하는 함수 trim으로 구분 * fix: 새로운 input 생성 조건에 현재 Input의 value가 빈 문자가 아닐때 추가 * chore: getFilledInputList 수정으로 인해 불필요한 코드 삭제 * feat: useDynamic을 사용하는 컴포넌트에 error 테두리 적용 * feat: useDynamicInput 수정에 맞게 useDynamicBillActionInput 수정 * chore: console.log 삭제 * feat: 홈 및 관리 페이지에서 링크 복사 기능 추가 (#329) * chore: v0.1.69 배포 * chore: HDesign 신규 버전 적용 * 실행 환경에 따라 복사하는 url 다르게 적용되도록 변경 * feat: eventPageLayout에서 링크 복사하기 기능 추가 * refactor: adminPage, homePage에서 eventName, eventId를 호출하지 않도록 변경 * style: lint 추가 * fix: "정산 초대하기"에서도 실행 환경에 따라 링크가 변경되도록 수정 * fix: 공통된 곳에서 사용되는 문자열 변수에 저장 * design: toast bottom 높이 추가 --------- Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> * feat: pr issue close workflow 생성 (#328) * test: cypress 적용 및 행사 생성 flow e2e 테스트 작성 (#331) * chore: cypress 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * test: 이벤트 생성 cypress 테스트 코드 작성 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * chore: cypress workflow 추가 * chore: dev 환경에서 eval source map 사용하도록 변경 * chore: cypress 명령어 세분화 * chore: cypress workflow 추가 * chore: 사용하지 않는 코드 제거 * chore: 사용하지 않는 dotenv 제거 * test: interceptAPI command 작성 * test: 반복되는 테스트 코드 매직넘버 상수화 * chore: postEvent fixture 생성 * test: API 요청이 필요한 부분 intercept * style: 불필요한 주석 제거 --------- Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * fix: 토큰이 없을 때, 관리페이지로 이동하면 오류가 발생하는 부분 수정 (#338) * feat: url을 통해 eventId를 분리하는 util 함수 구현 * refactor: useEventId를 사용하던 부분 getEventIdByUrl 함수로 대체 및 공백문자 분기처리 제거 * remove: 필요하지 않은 코드 제거 * style: lint 적용 * fix: stepList가 제대로 초기화되지 않는 오류 수정 * fix: 함수 이름 수정 * fix: regexp constants로 분리 * fix: 인원 탈주 추가 시 disable 버그 (#339) * style: 검색어 클릭 시 input set 함수 이름 변경 * fix: can submit 호출 시점 변경 * feat: Sentry prod 환경에서만 돌아가도록 fetcher 설정 (#343) * chore: typescript에 NodeEnv 환경설정 타입 선언 * chore: Sentry 캡쳐 에러를 prod 환경에서만 실행되도록 설정 * refactor: captureError에서 early return 방식으로 변경 * feat: 환경 변수 타입 선언 (#345) * chore: env key 타입 선언 * refactor: env type 선언으로 인한 빈 문자열 대체 제거 * refactor: NODE_ENV 타입 선언으로 빈 문자열 제거 및 development 환경 바로 비교 * refactor: 이벤트 페이지 url 자주사용되는 로직 유틸로 분리 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * feat: useDeleteMemberAction 토스트 함수 결합도 제거 (#347) * refactor: useDeleteMemberAction 토스트 로직 UI 컴포넌트로 이동 * refactor: isExistSameMember 함수 훅 외부로 넘겨주지 않고 특이한 케이스를 검사하는 함수를 훅 인자로 넘겨줌 * refactor: UI 컴포넌트에 토스트 띄우는 함수만 남기고 훅으로 이동 * chore: todo 주석 삭제 * feat: 사용성 개선 - Title component 변경 및 UX writing 수정 (#352) * fix: Text component 줄바꿈 가능하도록 변경 * fix: Title component 변경 * chore: v0.1.72 배포 * feat: ux writing 변경 * fix: 디자인시스템 버전 변경 * feat: 비밀번호 입력 페이지 커스텀 훅으로 분리 (#354) * refactor: 비밀번호 설정 커스텀 훅으로 분리 * refactor: event name 상태 제거 * style: index.ts에 setEventPasswordPage 컴포넌트 추가 * refactor: navigate 책임을 UI 컴포넌트로 위임 * style: 비밀번호 입력을 관리하는 함수라는 의미로 변경 * fix: 탭 클릭 시 전체가 클릭되는 것처럼 보이는 현상 해결 (#356) * feat: 사용성 개선 - 지출 내역 입력 아이템 구현 (#357) * feat: EditableItem Component 구현 * chore: v0.1.73 배포 * style: lint 적용 * style: 오타 수정 * fix: EditableItem을 export 하지 않던 오류 수정 * chore: v0.1.74 배포 --------- Co-authored-by: Pakxe <64801796+pakxe@users.noreply.github.com> * refactor: 행사 생성 완료 페이지에서 불필요한 상태 제거 (#350) * refactor: 행사생성 완료페이지 불필요한 상태 제거 * refactor: 사용하지 않는 import 구문 제거 및 코드 제거 * fix: 인원 탈주 시 검색이 되지 않는 버그 해결 (#368) * fix: 머지하면서 신경쓰지 못한 코드오류 해결 (#381) * feat: Input 검증 에러 메시지 타입 구조 변경 (#376) * refactor: errorMessage 타입을 string | undefined에서 string | null로 변경 * refactor: 에러가 아닐 때 errorMessage를 null로 리턴 * fix: 에러 import 되지 않던 현상 해결 * refactor: 에러 메시지 validate 함수 리턴하는 대로 그대로 set * feat: 에러메시지 보여지도록 추가 * refactor: 에러메시지 타입 string | null로 변경 * feat: 공통 input 코드를 useInput hook으로 분리 (#379) * feat: 반복적으로 사용하는 Input 코드를 useInput 훅으로 분리 * refactor: errorMessage 상수화 * fix: useInput 분리에 따라 발생한 useSearchInMemberList 에러 해결 * feat: input에 빈문자열이 들어온다면 canSubmit을 false로 invalid한 입력값은 지우고 canSubmit은 true로 변경 * refactor: Input이 하나 인 곳에서 index를 입력하지 않아도 작동되도록 수정 * test: 훅에 필요한 테스트 추가 (#358) * refactor: useAuth에서 return하는 함수들의 이름에 하는 일의 의미를 담도록 수정 * chore: 테스트를 위한 라이브러리 설치 * chore: jest사용을 위한 환경 세팅 * chore: 테스트가 있으므로 폴더 내부로 파일 이동 * test: 이벤트 아이디를 반환하는 훅인 useEventId 테스트 로직 작성 * chore: jest 환경 세팅 파일도 컴파일 할 수 있도록 tsconfig include에 추가 * test: 토큰과 로그인을 위한 useAuth 훅 테스트 작성 * chore: polyfills와 path alias세팅 추가 * chore: useFetch를 apis에서 hooks로 이동 * feat: 새로 추가된 에러 코드에 대한 메세지 추가 * chore: 파일 이동에 따른 수정 * feat: useAuth훅이 eventId를 스스로 호출하도록 함 * refactor: 객체를 쿼리스트링으로 바꾸는 함수를 분리 * chore: 불필요한 콘솔로그 제거 * test: 모든 테스트 사전에 실행되어야 하는 모킹 수행 * chore: 불필요한 콘솔로그 제거 * test: auth 도메인의 msw 모킹 함수 구현 * chore: jsdom환경에서 실행할 msw server 세팅 * refactor: withEventId 타입을 사용하도록 수정 * test: 이벤트를 생성하기 위한 useEvent 훅을 위한 테스트 코드 작성 * test: api 요청과 에러 상태 조작을 위한 useFetch 훅의 테스트 코드 작성 * chore: useFetch 파일 이동으로 인한 수정 * chore: 파일 이동 * refactor: captureError 함수를 useFetch로부터 분리 * test: 이벤트 도메인을 위한 msw 모킹 함수 구현 * chore: 불필요한 폴더는 커버리지 분석에 포함되지 않도록 함 * chore: jsdom 테스트를 위한 라이브러리 설치 * feat: 환경변수에 저장된 서버 도메인이 없는 경우 빈 문자열을 사용하도록 수정 * feat: useError가 error도 return하도록 수정 * chore: test 명령어 추가 * test: 멤버 목록을 위한 모킹 함수 작성 * test: 멤버를 지우는 useDeleteMemberAction의 테스트 코드 작성 * test: 로그를 위한 useStepList 훅의 테스트 코드 작성 * test: 정산 현황 조회에서 이름 검색 결과를 위한 useSearchMemberReportList 훅의 테스트 코드 작성 * chore: test환경에서의 location과 pathname 세팅 * chore: tsconfig에 jest 추가 * chore: 콘솔로그 제거 * fix: 바뀐 endpoint로 변경 * chore: 위치 변경으로 인한 수정 * chore: 위치 변경으로 인한 수정 * chore: 경로 모킹 로직을 setup으로 위임 * chore: 사용하지 않는 파일 제거 * chore: lint 적용 * chore: useFetch를 위해 핸들링 되는, 되지 않는 에러를 뱉는 모킹 함수 구현 * test: stepList와 관련된 api 모킹 함수 구현 * test: 정산 내역과 관련된 api 모킹 함수 구현 * chore: lint 적용 * test: test에 사용하는 상수 선언 * chore: stepListHandler에 합쳐진 모킹 함수 파일 제거 * test: 정상인 경우를 먼저 판단하도록 조건문 순서 변경 * test: 정산 내역 목데이터 선언 * test: 멤버 목록 목데이터 선언 * test: 프로젝트에서 사용되는 도메인의 모킹 핸들러를 export * test: 지출 내역을 위한 useStepList 훅의 테스트 코드 작성 * chore: 테스트를 위한 라이브러리 설치 * chore: CI과정에서 test를 진행하도록 명령어 추가 * test: provider안에서 호출되지 않으면 에러를 뱉는 로직의 테스트 코드 작성 * chore: 불필요한 파일이 coverage 에 뜨지 않도록 추가 * test: useDeleteMemberAction 훅의 삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 원래대로 돌려놓는 지 확인하는 테스트 코드 작성 * test: Error, FetchError 인 경우에 대해 올바르게 에러를 핸들링하는지 테스트 코드 작성 * test: 에러를 발생시키기 위해 음수 actionId가 들어온 경우 에러 반환 * feat: 불필요한 alert문 제거 * chore: toEqual -> toStrictEqual로 변경 * chore: 린트 적용 * fix: endpoint를 잘못 기재한 부분 수정 * chore: 파일이동에 따른 경로 수정 * chore: 린트 적용 * chore: 파일이동에 따른 경로 수정 * feat: 비밀번호 길이인 4를 상수화해 사용하도록 수정 * test: 요청 성공시 어떤 값을 반환하는지 구체적으로 테스트 이름에 명시 * chore: 린트 적용 * test: 토큰의 다양한 에러 타입에 대해 테스트하기 위한 상수 선언 * test: 토큰 내용에 따라 forbidden, expired 에러를 뱉도록 분기 추가 * test: 토큰이 forbidden, expired 일 경우 에러를 반환하는지 테스트 코드 작성 * chore: 디자인 시스템 라이브러리 업데이트 * feat: production에서만 sentry 에 로그를 보내도록 함 * chore: 린트 적용 * chore: 999라는 오류가 발생하는 멤버를 포함하는 stepList 목데이터 작성 * chore: 외부에서 사용하지 않는 함수 return에서 제거 * test: memberActionList를 typeNarrowing으로 정제하여 사용하도록 수정 * test: 삭제 요청에서 오류가 발생하는 경우를 테스트하기 위해 오류 데이터가 포함된 stepList 목데이터를 사용하도록 수정 * test: stepList 데이터가 채워진 후 테스트를 진행하도록 waitFor 추가 * test: 에러 시연을 위해 actionId가 999인 경우 에러 응답을 반환하도록 변경 * chore: 불필요한 주석 제거 * chore: 린트 적용 * chore: import 경로 수정 * refactor: 멤버 액션 삭제 훅 리팩토링 (#383) * refactor: alive -> delete member list로 변경 * refactor: 비동기 아닌 함수 async await 제거 * fix: 훅 내에서 errorIndexList 사용하고 있지 않아서 제거했습니다. * refactor: 이벤트 생성 페이지 리팩토링 (#385) * refactor: event name 관련 커스텀 훅 분리 * style: 필요하지 않은 children 제거 * feat: navigate replace true 조건으로 입력 중 상태로 되돌아갈 수 없도록 설정 * fix: 비밀번호 입력 창에서는 뒤로가기 할 때 이름으로 가도록 설정 * test: useError, useToast 테스트코드 작성 (#387) * style: errorBody -> errorInfo로 이름 변경 * test: jest에서 svg파일을 못읽으므로 이를 모킹해 오류가 발생하지 않도록 대처 * chore: coverage에서 errorProvider가 보이도록 ignore에서 제거 * feat: 불필요하게 낭비되는 상태인 hasError를 제거하고 errorMessage는 클라이언트에서 보여지는 에러메세지이므로 clientErrorMessage로 이름 수정 * refactor: ErrorProvider에서 useError를 파일로 분리 * test: 전역 에러 상태를 위한 useError 훅의 테스트 코드 작성 * chore: 파일 위치 변경으로 인한 import 경로 수정 * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 import * chore: toBeInTheDocument 를 사용하기 위한 라이브러리 설치 * chore: Property 'toBeInTheDocument' does not exist on type 'JestMatchers<HTMLElement>' 에러를 발생시키지 않기 위한 타입 추가 * refactor: ToastProvider에서 useToast분리 * test: 핸들링 가능한 에러발생 시 토스트를 띄우고, 핸들링 불가능한 에러 발생 시 토스트를 띄우지 않는지 테스트 코드 작성 * feat: Toast 컴포넌트에 토스트 엘리먼트 식별을 위한 id='toast' 추가 * chore: 파일을 hooks내부로 이동 * chore: 파일 이동으로 인한 import 경로 수정 * chore: components폴더 내부는 커버리지에 포함되지 않도록 ignore에 추가 * feat: Zustand, react-query 도입 및 적용 (#388) * chore: react-query, zustand 설치 및 환경설정 * feat: react-query hook 생성 * remove: 사용하지 않는 코드 삭제 * feat: StepList 리팩토링을 위한 코드 * fix: 객체로 묶여있지 않던 prop 변경 * refactor: react-query 적용 * refactor: SetEventNamePage, SetEventPasswordPage 비즈니스 로직 hook으로 분리 * fix: CompleteCreateEventPage 변경 * refactor: react-query 적용 * feat: StepList 구조 변경을 위한 store 생성 * feat: 총 지출금액을 계산하기 위한 store 구현 * style: lint 적용 * fix: eventName을 EventPageLayout에서 받도록 변경 * style: lint 적용 * fix: 빠진 쿼리키 수정 * fix: merge 이후 수정이 필요한 부분 해결 * remove: 사용하지 않는 useStepList 파일 제거 * fix: react-query 사용으로 테스트 코드에 QueryClientProvider 감싸주는 작업 진행 * chore: store 디렉토리 추가로 jest config에 반영 * refactor: 파생상태를 활용해서 state 제거 * style: 사용하지 않는 import 문 제거 * style: 사용하지 않는 import문 제거 * chore: replace:true 추가 * remove: 사용하지 않는 파일 제거 * chore: 변경된 이름 반영 * chore: useRequest- 파일을 hooks/queries 폴더로 이동 * chore: lint 적용 * fix: jest 설정. merge 시 누락된 코드 재적용 --------- Co-authored-by: 김진호 <rlawlsgh1227@gmail.com> Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * fix: valideMemberName의 조건문 name은 1 이하일 수 없다를 제거 (#396) Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> * feat: 총액 업데이트 로직을 store안으로 이동 (#401) * feat: 총액 계산 로직을 store에게 위임 * chore: 사용하지 않는 import 제거 * fix: action log가 길어질 때 heigth 잘리는 버그 수정 (#408) * feat: 전체 인원 수정 '삭제' api 로직 롤백 수정 (#409) * fix: merge를 진행하며 삭제된 수정 완료시 삭제 api 요청 로직으로 수정 * fix: 삭제 버튼 클릭 후 이름을 수정하면 index 불일치로 발생하는 버그 해결 * chore: 사용하지 않는 console.log 삭제 * feat: EditableItem.Input이 동적인 width를 갖도록 수정 (#411) * feat: backGroundColor를 옵셔널로 설정할 수 있도록 수정 * feat: prefix, suffix라벨 ui구현 * style: label의 css 작성 * test: 라벨이 있는 EditableItem, 라벨이 여러개 있는 EditableItem, 리스트 형태의 EditableItem의 스토리북 작성 * chore: 필요없어진 주석 제거 * chore: v0.1.75 publish * feat: theme 인자가 필요한 타입을 위한 WithTheme 타입 작성 * feat: 실제 컴포넌트를 렌더링하고 보여지는 width를 가져오는 함수 구현 * feat: 동적으로 input의 width가 변하도록 가상 컴포넌트인 shadowRef를 추가하여 구현 * design: 동적으로 width가 변하는 input을 위한 css작성 * feat: value가 없으면 동적으로 길이를 계산할 수 없으므로 반드시 받도록하고, 변동 여부와 읽기 전용 여부를 인자로 받도록 함 * test: value를 반드시 넘겨주도록 스토리북 수정 * feat: 불필요한 삼항연산문 제거 * test: 배열 EditableItem을 테스트하는데 지장이 없도록 세터 상세하게 구현 * chore: 사용하지 않는 스타일 제거 * refactor: 길이를 직접 할당해 불필요해진 상태와 함수 제거 * refactor: 불필요하게 배열에 담아 css 프롭을 넘겨주던 부분을 제거 * feat: 기존에 사용하던 hasFocus방식과 useImperativeHandle을 돌려놓음 * feat: width를 style로 넘기는 방식이 한 틱 늦게 반영되므로 제거 * chore: 사용하지 않는 타입 제거 * feat: disabled 속성 제거 * feat: autoFocus 속성 제거 * chore: v0.1.76 배포 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 차등 정산 기능 구현 및 테스트 작성 (#406) * feat: 고정 가격을 설정했는지에 대한 isFixed 타입 추가 * feat: 지출 상세 조회, 수정 api 함수 작성 * feat: Get, Put query, mutation 작성 * feat: 고정값으로 수정할 때, 나머지 인원의 가격이 계산되는 기능 추가 * fix: isFixed field 추가로 반영되지 못한 테스트 수정 * test: useMemberReportListInAction 훅 텟트 작성 아직 엣지케이스는 작성하지 못 함;; * fix: put body 형식 수정 * test: submit 함수 테스트 코드 작성 * feat: 모든 인원의 가격을 고정시키려 했을 때 반영하지 않는 기능 * test: 모든 인원을 담을 때 테스트 작성 * fix: invalidate queries querykey actionId 명시 * fix: 중복 인원이 들어왔을 때 잘못 계산되던 문제 해결 * test: 중복 인원일 때 테스트 코드 작성 * refactor: 지출상세 훅 리팩터링 * test: 같은 멤버 다른 가격으로 변환 시 다시 계산되는 테스트 작성 * fix: isFixed 추가로 발생한 테스트 오류 수정 * feat: 각 멤버 별 isFixed 추가 반영 * refactor: 서버의 isFixed 관리로 불필요한 상태 제거 * test: isFixed 필드 추가 테스트 반영 * feat: 계산값으로 값을 변경했을 때 isFixed를 해제하는 기능구현 * test: isFixed 해제 관련 테스트 작성 * feat: member report validation 로직 작성 * chore: 테스트를 위한 코드 작성 추후 삭제 * chore: 테스트용 라우팅 삭제 * feat: 총 금액보다 큰지 검증하는 기능 추가 * feat: 차등 적용 input으로 handle하는 기능 추가 * remove: 사용하지 않는 파일 제거 * feat: 차등 적용 적용 중 지원되지 않는 기능 수정 (#423) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: 차등 적용 can submit이 valid 하지만 false되는 버그 (#428) * fix: 0원을 허용하도록 수정 * feat: 총 금액이 변동됐을 때 재계산을 실행하는 기능 추가 * feat: 하나라도 조정값이 있는지를 판단하는 기능 추가 * test: 조정된 값이 있는지 여부를 주는 기능 test 작성 * feat: 조정되지 않은 인원이 1명일 때, input을 막아버리는 기능 추가 * feat: 서버상태와 클라이언트 상태 가격이 전부 동일하면 can submit false 기능 추가 * fix: input list가 변했을 때 can submit이 돌도록 변경 * fix: 데이터가 없을 때 초기화 되어버리는 현상 해결 * feat: 지출 내역 추가 변경사항 적용 (#414) * design: 지출 추가, 인원 추가 button 퍼블리싱 * feat: 변경된 Button에 BottomSheet onClick연결 * chore: 디자인시스템 버전 업데이트 * feat: step.type이 Bill이 아니더라도 isAddEditableItem가 true라면 BillStepItem을 렌더링하여 지출 내역 추가 Input을 띄우기 * feat: onChange에 billInput 변경하기 및 blur시 조건을 충족할 경우 서버로 api 요청 보내기 * feat: 지출 내역 post api를 요청하면 지출 내역 Input을 닫기 * feat: 디자인시스템과의 병합을 위해 Input에 value 추가 * chore: 불필요한 주석 제거 * fix: 불필요한 조건문 제거 * chore: 불필요한 console.log 삭제 * feat: 마지막 BillItem에만 EditableItem.Input을 렌더링하기 * design: 관리 페이지 디자인 수정 * fix: billInput 값을 초기화 * feat: BillItem이 존재하지 않을 때, 새로운 BillItem을 생성하여 지출 input 만들기 * feat: member action 추가후, 빈 stepList가 생성되지 않는 에러 해결 * chore: 디자인시스템 업데이트 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> * feat: 지출 내역 아이템 클릭시 뜨는 차등 정산 모달 퍼블리싱 (#431) * refactor: IsFixedIcon이 재사용되기 시작했으므로 컴포넌트로 분리 * feat: DragHandleItem에 IsFixed 속성을 추가하고 IsFixedIcon 가 보여지도록 함 * test: isFixed가 있는 DragHandleItem의 스토리 추가 * chore: 불필요한 import 제거 * chore: 디자인시스템 라이브러리 업데이트 * feat: 변경된 시안에 맞게 ui 수정 * feat: 차등 정산이 적용되었을 때 제출 버튼을 활성화하는 로직을 추가 * feat: 마지막으로 차등 정산을 적용하려는 참여자는 readOnly로 수정을 막도록 함 * feat: 지출 내역 아이템에 수정 여부를 표시하기 * fix: 유효길이를 초과해 입력하려는 경우 값은 이전의 유효값으로 고정이지만 canSubmit이 false라 요청이 불가능한 오류를 수정 * feat: BottomSheet 지출 부분 삭제 & input autoFocus (#433) * chore: webpack, react, typescript 환경 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: eslint, prettier 설정 Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * docs: pr 템플릿 및 issue 템플릿 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * docs: issue 템플릿에 타이틀과 관련된 부가 정보 추가 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> * chore: 모든 install 에 legacy-peer-deps를 사용하도록 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: emotion css props 사용 예제 작성 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: webpack, @emotion/react 라이브러리 설치 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props를 사용하기 위해 'jsxImportSource' 옵션 설정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: css props 사용 위해 모든 파일 최상단에 주석을 자동으로 작성해주도록 플러그인 세팅 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 개발서버 포트번호 3001 -> 3000 으로 수정 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: prettier에서 useTabs를 사용하지 않도록 제거 Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com>, Todari <rhymint@gmail.com> * chore: 여러 명이 co-authored-by로 들어갈 수 있는지 테스트 커밋 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 임시로 지웠던 types 옵션을 다시 활성화 Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: Todari <rhymint@gmail.com> * chore: 기본 webpack 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: theme, token 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: storybook 설정 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Button 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * feat: Text 구현 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * fix: webpack 설정 entry 파일 확장자 tsx에서 ts로 변경 Co-Authored-By: TaehunLee <85233397+Todari@users.noreply.github.com> * chore: modify-source-webpack-plugin 의존성 반영되지 않은 것 추가 Co-authored-by: pakxe <pigkill40@naver.com> * chore: css파일을 처리하기 위한 webpack 세팅 Co-author… * feat: 지출 내역이 없을 때 홈페이지에서 없다고 띄우기 (#520) * feat: 데이터가 없는 경우 없다고 띄우는 기능 추가 * feat: 지출 상세 데이터를 return하도록 함 * chore: 라이브러리 업데이트 (#525) * chore: 충돌 해결 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> Co-authored-by: pakxe <pigkill40@naver.com>, soi-ha <soy2302ten@gmail.com>, jinhokim98 <rlawlsgh1227@gmail.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: soi-ha <soy2302ten@gmail.com> Co-authored-by: TaehunLee <85233397+Todari@users.noreply.github.com> Co-authored-by: kunsanglee <gosmdochee2@gmail.com> Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Arachne <66822642+Arachneee@users.noreply.github.com> Co-authored-by: Arachneee <jhg2819@naver.com> Co-authored-by: juha <khabh@naver.com> Co-authored-by: Juhwan Kim <13selfesteem91@naver.com> Co-authored-by: JUHA <84626225+khabh@users.noreply.github.com> Co-authored-by: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Co-authored-by: JUHA <khabh@users.noreply.github.com> Co-authored-by: Arachne <Arachneee@users.noreply.github.com> --- .../EditableItem/EditableItem.Input.tsx | 3 ++ client/package-lock.json | 8 ++--- client/package.json | 2 +- .../MemberReportList/MemberReportList.tsx | 20 +++++++++--- .../PutAndDeleteBillActionModal.tsx | 5 +++ client/src/components/StepList/StepList.tsx | 32 ++++++++++++------- .../useSearchMemberReportList.tsx | 1 + 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/HDesign/src/components/EditableItem/EditableItem.Input.tsx index c0a08bc0e..87dd187e6 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.tsx +++ b/HDesign/src/components/EditableItem/EditableItem.Input.tsx @@ -29,10 +29,13 @@ export const EditableItemInput = forwardRef<HTMLInputElement, InputProps>(functi return ( <div css={inputWrapperStyle}> + <input type="number" /> + <Flex flexDirection="row"> <div ref={shadowRef} css={editingContainerStyle}> <Text size={textSize}>{htmlProps.value || htmlProps.placeholder}</Text> </div> + {isFixed && <IsFixedIcon />} <div css={underlineStyle({theme, hasError, hasFocus})}> <input diff --git a/client/package-lock.json b/client/package-lock.json index 61a529538..6625b0479 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.81", + "haengdong-design": "^0.1.82", "jest-canvas-mock": "^2.5.2", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", @@ -10171,9 +10171,9 @@ } }, "node_modules/haengdong-design": { - "version": "0.1.81", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.81.tgz", - "integrity": "sha512-IiXkt0zXSEmn7vstTLOeNZLFS35JO8lXbXavM55wdyAJd+w0e5kfRxyDk/K2oSiAnX2c2YPiGep/A0x2/gZPDg==", + "version": "0.1.82", + "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.82.tgz", + "integrity": "sha512-AjVvLle+7N71d8cDkSTHyyYTCuANhlppcBaS3qwv4wTnJJrn68mpWUKQ1Lt2lUt8WMRmZuoF2Bql7t0LHMyodQ==", "dependencies": { "@emotion/react": "^11.11.4", "@storybook/addon-webpack5-compiler-swc": "^1.0.5", diff --git a/client/package.json b/client/package.json index 6d673dd06..bd117af40 100644 --- a/client/package.json +++ b/client/package.json @@ -69,7 +69,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.81", + "haengdong-design": "^0.1.82", "jest-canvas-mock": "^2.5.2", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx index 1004540fa..21da76bed 100644 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -1,11 +1,11 @@ -import {ExpenseList, Flex, Input} from 'haengdong-design'; -import React, {useState} from 'react'; +import {ExpenseList, Flex, Input, Text} from 'haengdong-design'; +import React, {useEffect, useState} from 'react'; import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; const MemberReportList = () => { const [name, setName] = useState(''); - const {memberReportSearchList} = useSearchMemberReportList({name}); + const {memberReportSearchList, memberReportList} = useSearchMemberReportList({name}); const changeName = ({target}: React.ChangeEvent<HTMLInputElement>) => { setName(target.value); @@ -13,8 +13,18 @@ const MemberReportList = () => { return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - <Input inputType="search" value={name} onChange={changeName} placeholder="참여자 이름" /> - <ExpenseList expenseList={memberReportSearchList} /> + {memberReportList.length > 0 ? ( + <> + <Input inputType="search" value={name} onChange={changeName} placeholder="참여자 이름" /> + {memberReportSearchList.length !== 0 && <ExpenseList expenseList={memberReportSearchList} />} + </> + ) : ( + <Flex width="100%" justifyContent="center"> + <Text size="body" textColor="gray" style={{paddingTop: '1rem'}}> + 지금은 참여자가 한 명도 없어요. :( + </Text> + </Flex> + )} </Flex> ); }; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index 5f7d4501e..de88a7128 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -1,6 +1,7 @@ import type {BillAction} from 'types/serviceType'; import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; +import {useEffect} from 'react'; import validatePurchase from '@utils/validate/validatePurchase'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; @@ -64,6 +65,10 @@ const PutAndDeleteBillActionModal = ({ actions.find(({actionId}) => actionId === billAction.actionId), )[0].members; + useEffect(() => { + console.log(inputList); + }, [inputList]); + return ( <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> <form diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index d6a507247..c08f1b7a3 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,4 +1,4 @@ -import {Flex} from 'haengdong-design'; +import {Flex, Text} from 'haengdong-design'; import {useEffect, useMemo, useState} from 'react'; import {BillStep, MemberStep} from 'types/serviceType'; @@ -58,17 +58,25 @@ const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - {stepList.map((step, index) => ( - <Step - index={index} - step={step} - lastBillItemIndex={lastBillItemIndex} - lastItemIndex={lastItemIndex} - key={`${step.stepName}${index}`} - isAddEditableItem={isAddEditableItem} - setIsAddEditableItem={setIsAddEditableItem} - /> - ))} + {stepList.length > 0 ? ( + stepList.map((step, index) => ( + <Step + index={index} + step={step} + lastBillItemIndex={lastBillItemIndex} + lastItemIndex={lastItemIndex} + key={`${step.stepName}${index}`} + isAddEditableItem={isAddEditableItem} + setIsAddEditableItem={setIsAddEditableItem} + /> + )) + ) : ( + <Flex width="100%" justifyContent="center"> + <Text size="body" textColor="gray" style={{paddingTop: '1rem'}}> + 지금은 지출 내역이 없어요. :( + </Text> + </Flex> + )} </Flex> ); }; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx index 4a967e45c..58608062b 100644 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx @@ -10,6 +10,7 @@ const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { return { memberReportSearchList: memberReportList.filter(memberReport => memberReport.name.includes(name)), + memberReportList, }; }; From 6045a55f4614282d89b045a531ffc2afb4432ab1 Mon Sep 17 00:00:00 2001 From: pakxe <pigkill40@naver.com> Date: Fri, 23 Aug 2024 13:45:46 +0900 Subject: [PATCH 226/273] =?UTF-8?q?fix:=20number=ED=83=80=EC=9E=85?= =?UTF-8?q?=EC=9D=98=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=EB=A5=BC=204?= =?UTF-8?q?=EC=9E=90=EB=A6=AC=EC=9D=98=20=EB=AC=B8=EC=9E=90=EC=97=B4?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=9B=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/apis/request/event.ts | 2 +- client/src/hooks/queries/useRequestPostEvent.ts | 2 +- client/src/hooks/useEventLogin.ts | 4 ++-- client/src/hooks/useSetEventPasswordPage.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index c9299c813..6d559e94f 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -4,7 +4,7 @@ import {WithEventId} from '@apis/withEventId.type'; export type RequestPostNewEvent = { eventName: string; - password: number; + password: string; }; export type ResponsePostNewEvent = { diff --git a/client/src/hooks/queries/useRequestPostEvent.ts b/client/src/hooks/queries/useRequestPostEvent.ts index 5327710fc..5767738ec 100644 --- a/client/src/hooks/queries/useRequestPostEvent.ts +++ b/client/src/hooks/queries/useRequestPostEvent.ts @@ -4,7 +4,7 @@ import {requestPostNewEvent} from '@apis/request/event'; interface PostEventMutationProps { eventName: string; - password: number; + password: string; } const usePostEvent = () => { diff --git a/client/src/hooks/useEventLogin.ts b/client/src/hooks/useEventLogin.ts index ccabe20c1..e6f2cf2ec 100644 --- a/client/src/hooks/useEventLogin.ts +++ b/client/src/hooks/useEventLogin.ts @@ -7,7 +7,7 @@ import RULE from '@constants/rule'; import useRequestPostLogin from './queries/useRequestPostLogin'; const useEventLogin = () => { - const [password, setPassword] = useState(''); + const [password, setPassword] = useState<string>(''); const [errorMessage, setErrorMessage] = useState<string | null>(null); const [canSubmit, setCanSubmit] = useState(false); const {mutate: postLogin} = useRequestPostLogin(); @@ -15,7 +15,7 @@ const useEventLogin = () => { const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); - postLogin({password}, {onError: () => setErrorMessage('비밀번호가 틀렸어요')}); + postLogin({password: String(password).padStart(4, '0')}, {onError: () => setErrorMessage('비밀번호가 틀렸어요')}); }; const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts index 82ca72fb1..17079f3a9 100644 --- a/client/src/hooks/useSetEventPasswordPage.ts +++ b/client/src/hooks/useSetEventPasswordPage.ts @@ -29,7 +29,7 @@ const useSetEventPasswordPage = () => { event.preventDefault(); postEvent( - {eventName, password: parseInt(password)}, + {eventName, password: String(password).padStart(4, '0')}, { onSuccess: data => { navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId: data.eventId})}`, { From af1bf73fc721e6ab057af83fb7da6ff06b4db474 Mon Sep 17 00:00:00 2001 From: pakxe <pigkill40@naver.com> Date: Fri, 23 Aug 2024 13:49:18 +0900 Subject: [PATCH 227/273] =?UTF-8?q?fix:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=9D=B4=EB=A6=84=20=EA=B8=B8=EC=9D=B4=EA=B0=80=20?= =?UTF-8?q?20=EC=9E=90=EA=B0=80=20=EB=84=98=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/usePutAndDeleteBillAction.ts | 2 ++ client/src/hooks/useSetBillInput.ts | 3 +++ 2 files changed, 5 insertions(+) diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts index 6f1e4feaf..9126bf905 100644 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ b/client/src/hooks/usePutAndDeleteBillAction.ts @@ -36,6 +36,8 @@ const usePutAndDeleteBillAction = ( const handleInputChange = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; + if (value.length > 20) return; + const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue(field, value)); setErrorMessage(errorMessage); diff --git a/client/src/hooks/useSetBillInput.ts b/client/src/hooks/useSetBillInput.ts index a14b2a481..4f534791d 100644 --- a/client/src/hooks/useSetBillInput.ts +++ b/client/src/hooks/useSetBillInput.ts @@ -23,6 +23,9 @@ const useSetBillInput = ({setIsAddEditableItem}: UseSetBillInputProps): UseSetBi const handleChangeBillInput = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { const {value} = event.target; + + if (value.length > 20) return; + const {isValid} = validatePurchase({ ...billInput, [field]: value, From efea07b760dc4370170f4d8c38aa6126c51879f6 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 6 Sep 2024 17:02:10 +0900 Subject: [PATCH 228/273] =?UTF-8?q?refactor:=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=ED=8F=90=EC=A7=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=ED=8F=B4=EB=8D=94=20=EA=B5=AC=EC=A1=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#543)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 디자인 시스템 폐지로 인한 폴더구조 변경 Co-authored-by: TaehunLee <Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> * chore: 파일 구조 변경에 따른 workflow 수정 * remove: server directory 삭제 * chore: workflow에서 cache 설정 제거 * fix: lint 적용 * fix: lint 설정 HDesign 추가로 인한 lint 수정 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> * chore: workflow에 defaults 추가 * chore: alias jest에 추가 * chore: 의존성 정리 * refactor: hdesign svg를 assets로 이동 * fix: hdesign assets를 옮기면서 생긴 test 오류수정 * chore: chromatic log 추가 * chore: chromatic working-directory 추가 * chore: chromatic working-directory 위치 변경 * chore: chromatic cache dependencies 설정 추가 * chore: chromatic working-directory 제거 * chore: chromatic working directory 설정 다시 추가 * chore: chromatic 설정 변경 * fix: 스토리북 절대경로 제대로 설정 * chore: chromatic 배포 다시 설정 * chore: chromatic 배포 다시 설정 * fix: chromatic snapshot 변경 사항을 무시하고 CI 통과하도록 설정 * fix: working directory 다시 설정 --------- Co-authored-by: TaehunLee <Todari@users.noreply.github.com> Co-authored-by: Pakxe <pakxe@users.noreply.github.com> Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> --- .github/workflows/design-pull-request.yml | 54 - .github/workflows/frontend-pull-request.yml | 52 +- HDesign/.gitignore | 12 - HDesign/.npmignore | 7 - HDesign/.npmrc | 2 - HDesign/.prettierrc | 12 - HDesign/.storybook/main.ts | 47 - HDesign/eslint.config.mjs | 153 - HDesign/package-lock.json | 13707 ---------------- HDesign/package.json | 72 - HDesign/src/assets/index.ts | 7 - HDesign/src/assets/svg.d.ts | 6 - .../src/components/Toast/Toast.stories.tsx | 71 - HDesign/src/components/Toast/Toast.style.ts | 44 - HDesign/src/components/Toast/Toast.tsx | 73 - HDesign/src/components/Toast/Toast.type.ts | 21 - .../Toast/ToastProvider.stories.tsx | 46 - .../src/components/Toast/ToastProvider.tsx | 59 - HDesign/src/index.tsx | 62 - HDesign/tsconfig.json | 34 - client/.gitignore | 3 + client/.storybook/main.ts | 59 + {HDesign => client}/.storybook/preview.tsx | 2 +- client/eslint.config.mjs | 5 + client/jest.config.ts | 9 + client/package-lock.json | 7114 ++++++-- client/package.json | 19 +- client/src/App.tsx | 3 +- client/src/UnhandledErrorBoundary.tsx | 2 +- .../src/assets/image}/buljusa.svg | 0 .../src/assets/image}/confirm.svg | 0 .../src/assets/image}/error.svg | 0 .../src/assets/image}/inputDelete.svg | 0 .../src/assets/image}/loadingAnimation.json | 0 .../src/assets/image}/rightChevron.svg | 0 .../src/assets/image}/search.svg | 0 .../src/assets/image}/trash.svg | 0 .../AppErrorBoundary/ErrorCatcher.test.tsx | 3 +- .../BottomSheet/BottomSheet.stories.tsx | 4 +- .../BottomSheet/BottomSheet.style.ts | 0 .../components/BottomSheet/BottomSheet.tsx | 3 +- .../BottomSheet/BottomSheet.type.ts | 0 .../components/BottomSheet/useBottomSheet.ts | 2 + .../components/Button/Button.stories.tsx | 0 .../Design}/components/Button/Button.style.ts | 5 +- .../Design}/components/Button/Button.tsx | 9 +- .../Design}/components/Button/Button.type.ts | 0 .../DragHandleItem/DragHandleItem.stories.tsx | 2 +- .../DragHandleItem/DragHandleItem.style.ts | 1 - .../DragHandleItem/DragHandleItem.tsx | 9 +- .../DragHandleItem/DragHandleItem.type.ts | 1 - .../DragHandleItemContainer.stories.tsx | 4 +- .../DragHandleItemContainer.style.ts | 1 - .../DragHandleItemContainer.tsx | 0 .../DragHandleItemContainer.type.ts | 0 .../EditableItem/EditableItem.Input.style.ts | 3 +- .../EditableItem/EditableItem.Input.tsx | 7 +- .../EditableItem/EditableItem.Input.type.ts | 3 +- .../EditableItem/EditableItem.context.tsx | 0 .../EditableItem.input.stories.tsx | 2 +- .../EditableItem/EditableItem.stories.tsx | 6 +- .../EditableItem/EditableItem.style.ts | 1 - .../components/EditableItem/EditableItem.tsx | 5 +- .../EditableItem/EditableItem.type.ts | 1 - .../EditableItem/useEditableItem.ts | 0 .../EditableItem/useEditableItemInput.ts | 2 + .../ExpenseList/ExpenseList.stories.tsx | 2 +- .../ExpenseList/ExpenseList.style.ts | 0 .../components/ExpenseList/ExpenseList.tsx | 5 +- .../ExpenseList/ExpenseList.type.ts | 0 .../FixedButton/FixedButton.stories.tsx | 2 +- .../FixedButton/FixedButton.style.ts | 8 +- .../components/FixedButton/FixedButton.tsx | 12 +- .../FixedButton/FixedButton.type.ts | 3 +- .../Design}/components/Flex/Flex.style.ts | 2 +- .../Design}/components/Flex/Flex.tsx | 2 +- .../Design}/components/Flex/Flex.type.ts | 2 +- .../Design}/components/Icon/Icon.stories.tsx | 2 +- .../Design}/components/Icon/Icon.style.ts | 1 - .../Design}/components/Icon/Icon.tsx | 11 +- .../Design}/components/Icon/Icon.type.ts | 1 - .../IconButton/IconButton.stories.tsx | 4 +- .../components/IconButton/IconButton.style.ts | 3 +- .../components/IconButton/IconButton.tsx | 3 +- .../components/IconButton/IconButton.type.ts | 0 .../components/Input/Input.stories.tsx | 6 +- .../Design}/components/Input/Input.style.ts | 0 .../Design}/components/Input/Input.tsx | 11 +- .../Design}/components/Input/Input.type.ts | 0 .../Design}/components/Input/useInput.ts | 0 .../IsFixedIcon/IsFixedIcon.style.ts | 0 .../components/IsFixedIcon/IsFixedIcon.tsx | 0 .../components/LabelGroupInput/Element.tsx | 0 .../LabelGroupInput/Element.type.ts | 0 .../LabelGroupInput/GroupInputContext.tsx | 0 .../LabelGroupInput.stories.tsx | 2 +- .../LabelGroupInput/LabelGroupInput.style.ts | 0 .../LabelGroupInput/LabelGroupInput.tsx | 3 +- .../LabelGroupInput/LabelGroupInput.type.ts | 0 .../components/LabelGroupInput/index.ts | 0 .../LabelInput/LabelInput.stories.tsx | 2 +- .../components/LabelInput/LabelInput.style.ts | 2 +- .../components/LabelInput/LabelInput.tsx | 3 +- .../components/LabelInput/LabelInput.type.ts | 0 .../components/LabelInput/useLabelInput.ts | 0 .../ListButton/ListButton.stories.tsx | 2 +- .../components/ListButton/ListButton.style.ts | 0 .../components/ListButton/ListButton.tsx | 9 +- .../components/ListButton/ListButton.type.ts | 0 .../components/Search/Search.stories.tsx | 2 +- .../Design}/components/Search/Search.style.ts | 0 .../Design}/components/Search/Search.tsx | 3 +- .../components/Switch/Switch.stories.tsx | 2 +- .../Design}/components/Switch/Switch.style.ts | 0 .../Design}/components/Switch/Switch.tsx | 0 .../Design}/components/Switch/Switch.type.ts | 0 .../Design}/components/Tabs/Tab.tsx | 0 .../Design}/components/Tabs/Tab.type.ts | 0 .../Design}/components/Tabs/Tabs.stories.tsx | 2 +- .../Design}/components/Tabs/Tabs.style.ts | 0 .../Design}/components/Tabs/Tabs.tsx | 0 .../Design}/components/Text/Text.stories.tsx | 2 +- .../Design}/components/Text/Text.style.ts | 0 .../Design}/components/Text/Text.tsx | 2 +- .../Design}/components/Text/Text.type.ts | 1 - .../TextButton/TextButton.stories.tsx | 2 +- .../components/TextButton/TextButton.style.ts | 1 - .../components/TextButton/TextButton.tsx | 0 .../components/TextButton/TextButton.type.ts | 0 .../components/Title/Title.stories.tsx | 2 +- .../Design}/components/Title/Title.style.ts | 0 .../Design}/components/Title/Title.tsx | 9 +- .../Design}/components/Title/Title.type.ts | 0 .../Design}/components/TopNav/Back.tsx | 2 +- .../components/TopNav/TopNav.stories.tsx | 2 +- .../Design}/components/TopNav/TopNav.style.ts | 0 .../Design}/components/TopNav/TopNav.tsx | 2 +- client/src/components/Design/index.tsx | 56 + .../Design}/layouts/ContentLayout.tsx | 0 .../components/Design}/layouts/MainLayout.tsx | 0 .../components/Design}/theme/GlobalStyle.ts | 0 .../Design}/theme/HDesignProvider.tsx | 1 - .../components/Design}/theme/theme.type.ts | 0 .../src/components/Design}/token/colors.ts | 0 .../components/Design}/token/typography.ts | 0 .../Design}/type/strictPropsWithChildren.ts | 0 .../src/components/Design}/type/withTheme.ts | 0 .../utils/changeCamelCaseToKebabCase.ts | 0 .../src/components/Design}/utils/colors.ts | 0 .../MemberReportList/MemberReportList.tsx | 3 +- .../ExpenseDetailModal/ExpenseDetailModal.tsx | 4 +- .../MemberListInBillStep.tsx | 2 +- .../AddMemberActionListModalContent.tsx | 4 +- .../InMember.tsx | 4 +- .../OutMember.tsx | 4 +- .../DeleteMemberActionModal.tsx | 4 +- .../PutAndDeleteBillActionModal.tsx | 3 +- .../SetActionModal/SetActionListModal.tsx | 3 +- .../SetAllMemberListModal.tsx | 4 +- .../SetInitialMemberListModal.tsx | 4 +- .../src/components/StepList/BillStepItem.tsx | 3 +- .../components/StepList/MemberStepItem.tsx | 3 +- client/src/components/StepList/StepList.tsx | 3 +- client/src/components/Toast/Toast.tsx | 3 +- .../useDeleteMemberAction.test.tsx | 3 +- client/src/hooks/useToast/useToast.test.tsx | 3 +- client/src/mocks/svgMock.ts | 7 + .../CompleteCreateEventPage.tsx | 3 +- .../CreateEventPage/SetEventNamePage.tsx | 3 +- .../CreateEventPage/SetEventPasswordPage.tsx | 4 +- client/src/pages/ErrorPage/ErrorPage.tsx | 2 +- .../pages/EventPage/AdminPage/AdminPage.tsx | 3 +- .../EventPage/AdminPage/EventLoginPage.tsx | 4 +- .../src/pages/EventPage/EventPageLayout.tsx | 3 +- .../src/pages/EventPage/HomePage/HomePage.tsx | 3 +- client/src/pages/MainPage/MainPage.tsx | 2 +- client/src/pages/MainPage/Nav/Nav.tsx | 3 +- .../pages/MainPage/Section/AddBillSection.tsx | 3 +- .../MainPage/Section/AddMemberSection.tsx | 5 +- .../MainPage/Section/DescriptionSection.tsx | 4 +- .../pages/MainPage/Section/MainSection.tsx | 3 +- .../MainPage/Section/MemberReportSection.tsx | 3 +- client/tsconfig.json | 10 +- client/webpack.common.mjs | 7 + server/.gitignore | 244 - server/Dockerfile | 9 - server/build.gradle | 86 - server/docs/24-08-04-erd.sql | 65 - server/docs/24-08-04-erd.svg | 4 - server/gradle/wrapper/gradle-wrapper.jar | Bin 43453 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - server/gradlew | 249 - server/gradlew.bat | 92 - server/settings.gradle | 1 - server/src/docs/asciidoc/billAction.adoc | 121 - .../src/docs/asciidoc/billActionDetail.adoc | 93 - server/src/docs/asciidoc/event.adoc | 205 - server/src/docs/asciidoc/index.adoc | 15 - server/src/docs/asciidoc/memberAction.adoc | 100 - .../src/docs/asciidoc/memberBillReport.adoc | 17 - .../haengdong/HaengdongApplication.java | 15 - .../haengdong/application/ActionService.java | 39 - .../haengdong/application/AuthService.java | 41 - .../application/BillActionDetailService.java | 76 - .../application/BillActionService.java | 80 - .../haengdong/application/EventService.java | 170 - .../application/MemberActionFactory.java | 62 - .../application/MemberActionService.java | 100 - .../request/BillActionAppRequest.java | 15 - .../BillActionDetailUpdateAppRequest.java | 8 - .../BillActionDetailsUpdateAppRequest.java | 8 - .../request/BillActionUpdateAppRequest.java | 7 - .../application/request/EventAppRequest.java | 10 - .../request/EventLoginAppRequest.java | 4 - .../request/MemberActionSaveAppRequest.java | 12 - .../request/MemberActionsSaveAppRequest.java | 6 - .../request/MemberNameUpdateAppRequest.java | 7 - .../request/MemberNamesUpdateAppRequest.java | 8 - .../response/ActionAppResponse.java | 61 - .../response/BillActionDetailAppResponse.java | 18 - .../BillActionDetailsAppResponse.java | 14 - .../response/CurrentMemberAppResponse.java | 10 - .../response/EventAppResponse.java | 10 - .../response/EventDetailAppResponse.java | 10 - .../response/MemberBillReportAppResponse.java | 4 - .../response/MembersAppResponse.java | 8 - .../haengdong/config/AdminInterceptor.java | 51 - .../config/RequestServletFilter.java | 23 - .../server/haengdong/config/WebMvcConfig.java | 66 - .../haengdong/domain/TokenProvider.java | 12 - .../haengdong/domain/action/Action.java | 42 - .../domain/action/ActionRepository.java | 23 - .../haengdong/domain/action/BillAction.java | 156 - .../domain/action/BillActionDetail.java | 61 - .../action/BillActionDetailRepository.java | 20 - .../domain/action/BillActionRepository.java | 27 - .../domain/action/CurrentMembers.java | 81 - .../haengdong/domain/action/MemberAction.java | 76 - .../domain/action/MemberActionRepository.java | 53 - .../domain/action/MemberActionStatus.java | 19 - .../domain/action/MemberBillReport.java | 75 - .../domain/action/MemberGroupIdProvider.java | 11 - .../server/haengdong/domain/event/Event.java | 70 - .../domain/event/EventRepository.java | 11 - .../haengdong/domain/event/EventStep.java | 28 - .../domain/event/EventTokenProvider.java | 12 - .../haengdong/domain/event/Password.java | 52 - .../exception/AuthenticationException.java | 19 - .../haengdong/exception/ErrorResponse.java | 15 - .../exception/GlobalExceptionHandler.java | 90 - .../exception/HaengdongErrorCode.java | 69 - .../exception/HaengdongException.java | 19 - .../auth/AuthenticationExtractor.java | 23 - .../infrastructure/auth/CookieProperties.java | 15 - .../infrastructure/auth/JwtTokenProvider.java | 54 - .../infrastructure/auth/TokenProperties.java | 7 - .../presentation/ActionController.java | 26 - .../presentation/BillActionController.java | 55 - .../BillActionDetailController.java | 42 - .../presentation/EventController.java | 120 - .../presentation/MemberActionController.java | 60 - .../BillActionDetailUpdateRequest.java | 21 - .../BillActionDetailsUpdateRequest.java | 16 - .../request/BillActionSaveRequest.java | 19 - .../request/BillActionUpdateRequest.java | 18 - .../request/BillActionsSaveRequest.java | 18 - .../request/EventLoginRequest.java | 14 - .../request/EventSaveRequest.java | 18 - .../request/MemberActionsSaveRequest.java | 25 - .../request/MemberNameUpdateRequest.java | 18 - .../request/MemberNamesUpdateRequest.java | 17 - .../presentation/response/ActionResponse.java | 26 - .../response/ActionResponse2.java | 22 - .../response/ActionsResponse.java | 14 - .../response/BillActionDetailResponse.java | 18 - .../response/BillActionDetailsResponse.java | 16 - .../response/CurrentMembersResponse.java | 15 - .../response/EventDetailResponse.java | 10 - .../presentation/response/EventResponse.java | 10 - .../response/MemberBillReportResponse.java | 10 - .../response/MemberBillReportsResponse.java | 15 - .../response/MembersResponse.java | 13 - .../presentation/response/StepResponse.java | 27 - .../presentation/response/StepsResponse.java | 56 - server/src/main/resources/application.yml | 66 - server/src/main/resources/config | 1 - server/src/main/resources/logback-spring.xml | 97 - .../application/ActionServiceTest.java | 91 - .../BillActionDetailServiceTest.java | 111 - .../application/BillActionServiceTest.java | 229 - .../application/EventServiceTest.java | 231 - .../application/MemberActionFactoryTest.java | 223 - .../application/MemberActionServiceTest.java | 251 - .../application/ServiceTestSupport.java | 11 - .../docs/ActionControllerDocsTest.java | 70 - .../docs/BillActionControllerDocsTest.java | 128 - .../BillActionDetailControllerDocsTest.java | 127 - .../docs/EventControllerDocsTest.java | 381 - .../docs/MemberActionControllerDocsTest.java | 157 - .../haengdong/docs/RestDocsSupport.java | 28 - .../haengdong/domain/action/ActionTest.java | 31 - .../domain/action/BillActionTest.java | 89 - .../domain/action/CurrentMembersTest.java | 97 - .../domain/action/MemberBillReportTest.java | 56 - .../haengdong/domain/event/EventTest.java | 65 - .../haengdong/domain/event/PasswordTest.java | 19 - .../presentation/ActionControllerTest.java | 36 - .../BillActionControllerTest.java | 97 - .../BillActionDetailControllerTest.java | 56 - .../presentation/ControllerTestSupport.java | 53 - .../presentation/EventControllerTest.java | 111 - .../MemberActionControllerTest.java | 74 - .../response/StepsResponseTest.java | 63 - .../support/extension/DatabaseCleaner.java | 52 - .../extension/DatabaseCleanerExtension.java | 19 - .../haengdong/support/fixture/Fixture.java | 15 - 316 files changed, 6219 insertions(+), 23200 deletions(-) delete mode 100644 .github/workflows/design-pull-request.yml delete mode 100644 HDesign/.gitignore delete mode 100644 HDesign/.npmignore delete mode 100644 HDesign/.npmrc delete mode 100644 HDesign/.prettierrc delete mode 100644 HDesign/.storybook/main.ts delete mode 100644 HDesign/eslint.config.mjs delete mode 100644 HDesign/package-lock.json delete mode 100644 HDesign/package.json delete mode 100644 HDesign/src/assets/index.ts delete mode 100644 HDesign/src/assets/svg.d.ts delete mode 100644 HDesign/src/components/Toast/Toast.stories.tsx delete mode 100644 HDesign/src/components/Toast/Toast.style.ts delete mode 100644 HDesign/src/components/Toast/Toast.tsx delete mode 100644 HDesign/src/components/Toast/Toast.type.ts delete mode 100644 HDesign/src/components/Toast/ToastProvider.stories.tsx delete mode 100644 HDesign/src/components/Toast/ToastProvider.tsx delete mode 100644 HDesign/src/index.tsx delete mode 100644 HDesign/tsconfig.json create mode 100644 client/.storybook/main.ts rename {HDesign => client}/.storybook/preview.tsx (91%) rename {HDesign/src/assets => client/src/assets/image}/buljusa.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/confirm.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/error.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/inputDelete.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/loadingAnimation.json (100%) rename {HDesign/src/assets => client/src/assets/image}/rightChevron.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/search.svg (100%) rename {HDesign/src/assets => client/src/assets/image}/trash.svg (100%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/BottomSheet.stories.tsx (86%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/BottomSheet.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/BottomSheet.tsx (94%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/BottomSheet.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/BottomSheet/useBottomSheet.ts (99%) rename {HDesign/src => client/src/components/Design}/components/Button/Button.stories.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/Button/Button.style.ts (95%) rename {HDesign/src => client/src/components/Design}/components/Button/Button.tsx (83%) rename {HDesign/src => client/src/components/Design}/components/Button/Button.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItem/DragHandleItem.stories.tsx (94%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItem/DragHandleItem.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItem/DragHandleItem.tsx (85%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItem/DragHandleItem.type.ts (99%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItemContainer/DragHandleItemContainer.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItemContainer/DragHandleItemContainer.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/DragHandleItemContainer/DragHandleItemContainer.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.Input.style.ts (97%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.Input.tsx (91%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.Input.type.ts (89%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.context.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.input.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.stories.tsx (98%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/EditableItem.type.ts (99%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/useEditableItem.ts (100%) rename {HDesign/src => client/src/components/Design}/components/EditableItem/useEditableItemInput.ts (98%) rename {HDesign/src => client/src/components/Design}/components/ExpenseList/ExpenseList.stories.tsx (90%) rename {HDesign/src => client/src/components/Design}/components/ExpenseList/ExpenseList.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/ExpenseList/ExpenseList.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/ExpenseList/ExpenseList.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/FixedButton/FixedButton.stories.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/FixedButton/FixedButton.style.ts (93%) rename {HDesign/src => client/src/components/Design}/components/FixedButton/FixedButton.tsx (80%) rename {HDesign/src => client/src/components/Design}/components/FixedButton/FixedButton.type.ts (85%) rename {HDesign/src => client/src/components/Design}/components/Flex/Flex.style.ts (94%) rename {HDesign/src => client/src/components/Design}/components/Flex/Flex.tsx (91%) rename {HDesign/src => client/src/components/Design}/components/Flex/Flex.type.ts (93%) rename {HDesign/src => client/src/components/Design}/components/Icon/Icon.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/Icon/Icon.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/Icon/Icon.tsx (59%) rename {HDesign/src => client/src/components/Design}/components/Icon/Icon.type.ts (99%) rename {HDesign/src => client/src/components/Design}/components/IconButton/IconButton.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/IconButton/IconButton.style.ts (97%) rename {HDesign/src => client/src/components/Design}/components/IconButton/IconButton.tsx (88%) rename {HDesign/src => client/src/components/Design}/components/IconButton/IconButton.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Input/Input.stories.tsx (90%) rename {HDesign/src => client/src/components/Design}/components/Input/Input.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Input/Input.tsx (82%) rename {HDesign/src => client/src/components/Design}/components/Input/Input.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Input/useInput.ts (100%) rename {HDesign/src => client/src/components/Design}/components/IsFixedIcon/IsFixedIcon.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/IsFixedIcon/IsFixedIcon.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/Element.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/Element.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/GroupInputContext.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/LabelGroupInput.stories.tsx (96%) rename HDesign/src/components/LabelInput/LabelInput.style.ts => client/src/components/Design/components/LabelGroupInput/LabelGroupInput.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/LabelGroupInput.tsx (97%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/LabelGroupInput.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelGroupInput/index.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelInput/LabelInput.stories.tsx (95%) rename HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts => client/src/components/Design/components/LabelInput/LabelInput.style.ts (93%) rename {HDesign/src => client/src/components/Design}/components/LabelInput/LabelInput.tsx (96%) rename {HDesign/src => client/src/components/Design}/components/LabelInput/LabelInput.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/LabelInput/useLabelInput.ts (100%) rename {HDesign/src => client/src/components/Design}/components/ListButton/ListButton.stories.tsx (90%) rename {HDesign/src => client/src/components/Design}/components/ListButton/ListButton.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/ListButton/ListButton.tsx (82%) rename {HDesign/src => client/src/components/Design}/components/ListButton/ListButton.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Search/Search.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/Search/Search.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Search/Search.tsx (96%) rename {HDesign/src => client/src/components/Design}/components/Switch/Switch.stories.tsx (92%) rename {HDesign/src => client/src/components/Design}/components/Switch/Switch.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Switch/Switch.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/Switch/Switch.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Tabs/Tab.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/Tabs/Tab.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Tabs/Tabs.stories.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/Tabs/Tabs.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Tabs/Tabs.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/Text/Text.stories.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/Text/Text.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Text/Text.tsx (87%) rename {HDesign/src => client/src/components/Design}/components/Text/Text.type.ts (99%) rename {HDesign/src => client/src/components/Design}/components/TextButton/TextButton.stories.tsx (93%) rename {HDesign/src => client/src/components/Design}/components/TextButton/TextButton.style.ts (99%) rename {HDesign/src => client/src/components/Design}/components/TextButton/TextButton.tsx (100%) rename {HDesign/src => client/src/components/Design}/components/TextButton/TextButton.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Title/Title.stories.tsx (94%) rename {HDesign/src => client/src/components/Design}/components/Title/Title.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/Title/Title.tsx (77%) rename {HDesign/src => client/src/components/Design}/components/Title/Title.type.ts (100%) rename {HDesign/src => client/src/components/Design}/components/TopNav/Back.tsx (84%) rename {HDesign/src => client/src/components/Design}/components/TopNav/TopNav.stories.tsx (95%) rename {HDesign/src => client/src/components/Design}/components/TopNav/TopNav.style.ts (100%) rename {HDesign/src => client/src/components/Design}/components/TopNav/TopNav.tsx (92%) create mode 100644 client/src/components/Design/index.tsx rename {HDesign/src => client/src/components/Design}/layouts/ContentLayout.tsx (100%) rename {HDesign/src => client/src/components/Design}/layouts/MainLayout.tsx (100%) rename {HDesign/src => client/src/components/Design}/theme/GlobalStyle.ts (100%) rename {HDesign/src => client/src/components/Design}/theme/HDesignProvider.tsx (99%) rename {HDesign/src => client/src/components/Design}/theme/theme.type.ts (100%) rename {HDesign/src => client/src/components/Design}/token/colors.ts (100%) rename {HDesign/src => client/src/components/Design}/token/typography.ts (100%) rename {HDesign/src => client/src/components/Design}/type/strictPropsWithChildren.ts (100%) rename {HDesign/src => client/src/components/Design}/type/withTheme.ts (100%) rename {HDesign/src => client/src/components/Design}/utils/changeCamelCaseToKebabCase.ts (100%) rename {HDesign/src => client/src/components/Design}/utils/colors.ts (100%) create mode 100644 client/src/mocks/svgMock.ts delete mode 100644 server/.gitignore delete mode 100644 server/Dockerfile delete mode 100644 server/build.gradle delete mode 100644 server/docs/24-08-04-erd.sql delete mode 100644 server/docs/24-08-04-erd.svg delete mode 100644 server/gradle/wrapper/gradle-wrapper.jar delete mode 100644 server/gradle/wrapper/gradle-wrapper.properties delete mode 100644 server/gradlew delete mode 100644 server/gradlew.bat delete mode 100644 server/settings.gradle delete mode 100644 server/src/docs/asciidoc/billAction.adoc delete mode 100644 server/src/docs/asciidoc/billActionDetail.adoc delete mode 100644 server/src/docs/asciidoc/event.adoc delete mode 100644 server/src/docs/asciidoc/index.adoc delete mode 100644 server/src/docs/asciidoc/memberAction.adoc delete mode 100644 server/src/docs/asciidoc/memberBillReport.adoc delete mode 100644 server/src/main/java/server/haengdong/HaengdongApplication.java delete mode 100644 server/src/main/java/server/haengdong/application/ActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/AuthService.java delete mode 100644 server/src/main/java/server/haengdong/application/BillActionDetailService.java delete mode 100644 server/src/main/java/server/haengdong/application/BillActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/EventService.java delete mode 100644 server/src/main/java/server/haengdong/application/MemberActionFactory.java delete mode 100644 server/src/main/java/server/haengdong/application/MemberActionService.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/EventAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java delete mode 100644 server/src/main/java/server/haengdong/application/response/ActionAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/EventAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/application/response/MembersAppResponse.java delete mode 100644 server/src/main/java/server/haengdong/config/AdminInterceptor.java delete mode 100644 server/src/main/java/server/haengdong/config/RequestServletFilter.java delete mode 100644 server/src/main/java/server/haengdong/config/WebMvcConfig.java delete mode 100644 server/src/main/java/server/haengdong/domain/TokenProvider.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/Action.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/ActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillAction.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionDetail.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/BillActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/CurrentMembers.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberAction.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberBillReport.java delete mode 100644 server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/Event.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventRepository.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventStep.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java delete mode 100644 server/src/main/java/server/haengdong/domain/event/Password.java delete mode 100644 server/src/main/java/server/haengdong/exception/AuthenticationException.java delete mode 100644 server/src/main/java/server/haengdong/exception/ErrorResponse.java delete mode 100644 server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java delete mode 100644 server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java delete mode 100644 server/src/main/java/server/haengdong/exception/HaengdongException.java delete mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java delete mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java delete mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java delete mode 100644 server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java delete mode 100644 server/src/main/java/server/haengdong/presentation/ActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/BillActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/BillActionDetailController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/EventController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/MemberActionController.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/EventResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/MembersResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/StepResponse.java delete mode 100644 server/src/main/java/server/haengdong/presentation/response/StepsResponse.java delete mode 100644 server/src/main/resources/application.yml delete mode 160000 server/src/main/resources/config delete mode 100644 server/src/main/resources/logback-spring.xml delete mode 100644 server/src/test/java/server/haengdong/application/ActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/BillActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/EventServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java delete mode 100644 server/src/test/java/server/haengdong/application/MemberActionServiceTest.java delete mode 100644 server/src/test/java/server/haengdong/application/ServiceTestSupport.java delete mode 100644 server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java delete mode 100644 server/src/test/java/server/haengdong/docs/RestDocsSupport.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/ActionTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/BillActionTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/event/EventTest.java delete mode 100644 server/src/test/java/server/haengdong/domain/event/PasswordTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/ActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java delete mode 100644 server/src/test/java/server/haengdong/presentation/EventControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java delete mode 100644 server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java delete mode 100644 server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java delete mode 100644 server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java delete mode 100644 server/src/test/java/server/haengdong/support/fixture/Fixture.java diff --git a/.github/workflows/design-pull-request.yml b/.github/workflows/design-pull-request.yml deleted file mode 100644 index af168a976..000000000 --- a/.github/workflows/design-pull-request.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Storybook Deployment - -on: - pull_request: - branches: - - fe-dev - paths: - - 'HDesign/**' - -jobs: - chromatic: - name: Run Chromatic - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '20.15.1' - - - name: Cache dependencies - id: cache - uses: actions/cache@v3 - with: - path: '**/node_modules' - key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-npm- - - - name: Install dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: | - cd HDesign - npm install - - - name: Run lint - run: npm run lint - working-directory: ./HDesign - - - name: Run Chromatic - uses: chromaui/action@latest - id: publish_chromatic - with: - workingDir: HDesign - projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} - - - name: Comment on PR - uses: thollander/actions-comment-pull-request@v2 - with: - message: '🚀 **storybook**: ${{ steps.publish_chromatic.outputs.storybookUrl }}' diff --git a/.github/workflows/frontend-pull-request.yml b/.github/workflows/frontend-pull-request.yml index c2749939b..913ba783d 100644 --- a/.github/workflows/frontend-pull-request.yml +++ b/.github/workflows/frontend-pull-request.yml @@ -5,7 +5,7 @@ on: types: [opened, synchronize] branches: [main, fe-dev] paths: - - 'client/**' + - "client/**" jobs: test: @@ -23,18 +23,15 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '20.15.1' + node-version: "20.15.1" - name: Install dependencies - working-directory: ./client run: npm install - name: Run lint - working-directory: ./client run: npm run lint - name: Run test - working-directory: ./client run: npm run test - name: Cypress test @@ -47,3 +44,48 @@ jobs: - name: Run Cypress tests run: npm run cypress-run + + chromatic: + name: Run Chromatic + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ./client + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20.15.1" + + - name: Cache dependencies + id: cache + uses: actions/cache@v3 + with: + path: "**/node_modules" + key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}-v1 + restore-keys: | + ${{ runner.os }}-npm- + + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: npm install + + - name: Run Chromatic + uses: chromaui/action@latest + id: publish_chromatic + with: + workingDir: client + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + + - name: Comment on PR + uses: thollander/actions-comment-pull-request@v2 + with: + message: "🚀 **storybook**: ${{ steps.publish_chromatic.outputs.storybookUrl }}" diff --git a/HDesign/.gitignore b/HDesign/.gitignore deleted file mode 100644 index b98928456..000000000 --- a/HDesign/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -logs -*.log -npm-debug.log* - -node_modules -dist - -.env - -storybook-static -*storybook.log -.DS_Store diff --git a/HDesign/.npmignore b/HDesign/.npmignore deleted file mode 100644 index 363c89306..000000000 --- a/HDesign/.npmignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules/ -src/ -tsconfig.json -.storybook/ -.eslintrc.json -.prettierrc -webpack.config.js \ No newline at end of file diff --git a/HDesign/.npmrc b/HDesign/.npmrc deleted file mode 100644 index ece05f588..000000000 --- a/HDesign/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -engine-strict = true -legacy-peer-deps = true diff --git a/HDesign/.prettierrc b/HDesign/.prettierrc deleted file mode 100644 index c025201f4..000000000 --- a/HDesign/.prettierrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "all", - "printWidth": 120, - "tabWidth": 2, - "semi": true, - "arrowParens": "avoid", - "endOfLine": "auto", - "jsxSingleQuote": false, - "bracketSpacing": false, - "proseWrap": "preserve" -} diff --git a/HDesign/.storybook/main.ts b/HDesign/.storybook/main.ts deleted file mode 100644 index a1fa61591..000000000 --- a/HDesign/.storybook/main.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** @type { import('@storybook/react-webpack5').StorybookConfig } */ -import type {StorybookConfig} from '@storybook/react-webpack5'; -import path from 'path'; - -const config: StorybookConfig = { - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], - addons: [ - '@storybook/addon-webpack5-compiler-swc', - '@storybook/addon-onboarding', - '@storybook/addon-links', - '@storybook/addon-essentials', - '@chromatic-com/storybook', - '@storybook/addon-interactions', - ], - framework: { - name: '@storybook/react-webpack5', - options: {}, - }, - webpackFinal: async config => { - if (config.resolve) { - config.resolve.alias = { - ...config.resolve.alias, - '@components': path.resolve(__dirname, '../src/components'), - '@token': path.resolve(__dirname, '../src/token'), - '@type': path.resolve(__dirname, '../src/type'), - '@theme': path.resolve(__dirname, '../src/theme'), - '@assets': path.resolve(__dirname, '../src/assets'), - '@utils': path.resolve(__dirname, '../src/utils'), - }; - } - - config.module = config.module || {}; - config.module.rules = config.module.rules || []; - - const imageRule = config.module.rules.find(rule => rule?.['test']?.test('.svg')); - if (imageRule) { - imageRule['exclude'] = /\.svg$/; - } - - config.module.rules.push({ - test: /\.svg$/, - use: ['@svgr/webpack'], - }); - return config; - }, -}; -export default config; diff --git a/HDesign/eslint.config.mjs b/HDesign/eslint.config.mjs deleted file mode 100644 index e025936a4..000000000 --- a/HDesign/eslint.config.mjs +++ /dev/null @@ -1,153 +0,0 @@ -import path from 'node:path'; -import {fileURLToPath} from 'node:url'; - -import {fixupConfigRules, fixupPluginRules} from '@eslint/compat'; -import react from 'eslint-plugin-react'; -import typescriptEslint from '@typescript-eslint/eslint-plugin'; -import _import from 'eslint-plugin-import'; -import prettier from 'eslint-plugin-prettier'; -import tsParser from '@typescript-eslint/parser'; -import js from '@eslint/js'; -import {FlatCompat} from '@eslint/eslintrc'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, -}); - -export default [ - ...fixupConfigRules( - compat.extends( - 'eslint:recommended', - 'plugin:react/recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - 'plugin:import/typescript', - 'plugin:import/recommended', - 'plugin:import/errors', - 'plugin:import/warnings', - 'prettier', - 'plugin:prettier/recommended', - ), - ), - { - plugins: { - react: fixupPluginRules(react), - '@typescript-eslint': fixupPluginRules(typescriptEslint), - import: fixupPluginRules(_import), - prettier: fixupPluginRules(prettier), - }, - - languageOptions: { - parser: tsParser, - }, - - settings: { - 'import/resolver': { - node: { - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }, - - typescript: { - directory: './lib', - }, - }, - - 'import/parsers': { - '@typescript-eslint/parser': ['.ts', '.tsx'], - }, - - 'import/ignore': ['lottie-react'], - }, - - rules: { - 'no-use-before-define': 0, - 'prettier/prettier': 'error', - 'react/react-in-jsx-scope': 'off', - 'react/prop-types': 'off', - 'import/prefer-default-export': 0, - 'import/no-named-as-default': 0, - 'import/namespace': 0, - 'import/extensions': 0, - 'import/no-cycle': 0, - 'react/no-unknown-property': 0, - 'react/jsx-filename-extension': [1, {extensions: ['.ts', '.tsx']}], - 'react/function-component-definition': 0, - 'react/jsx-props-no-spreading': 0, - 'react/jsx-key': 0, - 'react/button-has-type': 'off', - 'no-shadow': 0, - 'no-console': 0, - 'no-alert': 0, - 'react/no-children-prop': 'off', - 'react/no-array-index-key': 'off', - 'react-hooks/exhaustive-deps': 'off', - 'react-hooks/rules-of-hooks': 'off', - 'react/jsx-no-useless-fragment': 'off', - 'react/jsx-no-constructed-context-values': 'off', - 'jsx-a11y/click-events-have-key-events': 'off', - 'jsx-a11y/no-static-element-interactions': 'off', - - '@typescript-eslint/no-unused-vars': 0, - - // 'react/jsx-uses-vars': 'error', - // '@typescript-eslint/no-use-before-define': ['error'], - // '@typescript-eslint/explicit-module-boundary-types': 'error', - - 'import/order': [ - 'error', - { - 'newlines-between': 'always', - - groups: ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'], - - pathGroups: [ - { - pattern: 'react*', - group: 'external', - position: 'before', - }, - { - pattern: '@components/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@layouts/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@assets/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@theme/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@token/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@types/*', - group: 'internal', - position: 'after', - }, - { - pattern: '@utils/*', - group: 'internal', - position: 'after', - }, - ], - }, - ], - }, - }, -]; diff --git a/HDesign/package-lock.json b/HDesign/package-lock.json deleted file mode 100644 index fb92d2ae1..000000000 --- a/HDesign/package-lock.json +++ /dev/null @@ -1,13707 +0,0 @@ -{ - "name": "haengdong-design", - "version": "0.1.81", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "haengdong-design", - "version": "0.1.81", - "license": "ISC", - "dependencies": { - "@emotion/react": "^11.11.4", - "@storybook/addon-webpack5-compiler-swc": "^1.0.5", - "@svgr/webpack": "^8.1.0", - "lottie-react": "^2.4.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" - }, - "devDependencies": { - "@chromatic-com/storybook": "^1.6.1", - "@eslint/compat": "^1.1.0", - "@eslint/js": "^9.6.0", - "@storybook/addon-essentials": "^8.2.2", - "@storybook/addon-interactions": "^8.2.2", - "@storybook/addon-links": "^8.2.2", - "@storybook/addon-onboarding": "^8.2.2", - "@storybook/blocks": "^8.2.2", - "@storybook/react": "^8.2.2", - "@storybook/react-webpack5": "^8.2.3", - "@storybook/test": "^8.2.2", - "@swc/core": "^1.7.6", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "esbuild": "^0.23.0", - "eslint": "^9.8.0", - "eslint-config-prettier": "^9.1.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.4", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-storybook": "^0.8.0", - "file-loader": "^6.2.0", - "globals": "^15.8.0", - "prettier": "3.3.2", - "storybook": "^8.2.2", - "storybook-addon-react-router-v6": "^2.0.15", - "ts-loader": "^9.5.1", - "tsc-alias": "^1.8.10", - "typescript": "^5.5.3", - "typescript-eslint": "^7.16.0" - }, - "engines": { - "node": ">=20.15.1", - "npm": ">=10.7.0" - } - }, - "node_modules/@adobe/css-tools": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", - "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", - "dev": true - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", - "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", - "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.9", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-module-transforms": "^7.24.9", - "@babel/helpers": "^7.24.8", - "@babel/parser": "^7.24.8", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.9", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/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==" - }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.9.tgz", - "integrity": "sha512-G8v3jRg+z8IwY1jHFxvCNhOPYPterE4XljNgdGTYfSTtzzwjIswIzIaSPSLs3R7yFuqnqNeay5rjICfqVr+/6A==", - "dependencies": { - "@babel/types": "^7.24.9", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", - "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", - "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", - "dependencies": { - "@babel/compat-data": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "browserslist": "^4.23.1", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", - "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.8", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", - "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", - "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", - "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", - "dependencies": { - "@babel/traverse": "^7.24.8", - "@babel/types": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", - "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", - "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", - "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-wrap-function": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", - "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", - "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", - "dependencies": { - "@babel/helper-function-name": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", - "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", - "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", - "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", - "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", - "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", - "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", - "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", - "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", - "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", - "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", - "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", - "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", - "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", - "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", - "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", - "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", - "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", - "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", - "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/template": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", - "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", - "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", - "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", - "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", - "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", - "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz", - "integrity": "sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-flow": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", - "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", - "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", - "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", - "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", - "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", - "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", - "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", - "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-simple-access": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", - "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", - "dependencies": { - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", - "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", - "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", - "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", - "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", - "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", - "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", - "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", - "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", - "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", - "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", - "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", - "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", - "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", - "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", - "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", - "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", - "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", - "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", - "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", - "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", - "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", - "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", - "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", - "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", - "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", - "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-create-class-features-plugin": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/plugin-syntax-typescript": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", - "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", - "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", - "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", - "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", - "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", - "dependencies": { - "@babel/compat-data": "^7.24.8", - "@babel/helper-compilation-targets": "^7.24.8", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.7", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.24.7", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.24.7", - "@babel/plugin-transform-class-properties": "^7.24.7", - "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.24.8", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-dotall-regex": "^7.24.7", - "@babel/plugin-transform-duplicate-keys": "^7.24.7", - "@babel/plugin-transform-dynamic-import": "^7.24.7", - "@babel/plugin-transform-exponentiation-operator": "^7.24.7", - "@babel/plugin-transform-export-namespace-from": "^7.24.7", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.24.7", - "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.24.7", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-member-expression-literals": "^7.24.7", - "@babel/plugin-transform-modules-amd": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.24.7", - "@babel/plugin-transform-modules-umd": "^7.24.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-new-target": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-object-super": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-property-literals": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-reserved-words": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-template-literals": "^7.24.7", - "@babel/plugin-transform-typeof-symbol": "^7.24.8", - "@babel/plugin-transform-unicode-escapes": "^7.24.7", - "@babel/plugin-transform-unicode-property-regex": "^7.24.7", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.37.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-flow": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", - "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-transform-flow-strip-types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-react": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", - "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-transform-react-display-name": "^7.24.7", - "@babel/plugin-transform-react-jsx": "^7.24.7", - "@babel/plugin-transform-react-jsx-development": "^7.24.7", - "@babel/plugin-transform-react-pure-annotations": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", - "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/register": { - "version": "7.24.6", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", - "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.6", - "source-map-support": "^0.5.16" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/register/node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/register/node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/register/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" - }, - "node_modules/@babel/runtime": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", - "integrity": "sha512-5F7SDGs1T72ZczbRwbGO9lQi0NLjQxzl6i4lJxLxfW9U5UluCSyEJeniWvnhl3/euNiqQVbo8zruhsDfid0esA==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", - "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.8", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.8", - "@babel/types": "^7.24.8", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/traverse/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/types": { - "version": "7.24.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", - "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", - "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@base2/pretty-print-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", - "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", - "dev": true - }, - "node_modules/@chromatic-com/storybook": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.6.1.tgz", - "integrity": "sha512-x1x1NB3j4xpfeSWKr96emc+7ZvfsvH+/WVb3XCjkB24PPbT8VZXb3mJSAQMrSzuQ8+eQE9kDogYHH9Fj3tb/Cw==", - "dev": true, - "dependencies": { - "chromatic": "^11.4.0", - "filesize": "^10.0.12", - "jsonfile": "^6.1.0", - "react-confetti": "^6.1.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=16.0.0", - "yarn": ">=1.22.18" - } - }, - "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@chromatic-com/storybook/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@emotion/babel-plugin": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", - "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/serialize": "^1.1.2", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "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", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/hash": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", - "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" - }, - "node_modules/@emotion/memoize": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", - "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" - }, - "node_modules/@emotion/react": { - "version": "11.11.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", - "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "hoist-non-react-statics": "^3.3.1" - }, - "peerDependencies": { - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@emotion/serialize": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz", - "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==", - "dependencies": { - "@emotion/hash": "^0.9.1", - "@emotion/memoize": "^0.8.1", - "@emotion/unitless": "^0.8.1", - "@emotion/utils": "^1.2.1", - "csstype": "^3.0.2" - } - }, - "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==" - }, - "node_modules/@emotion/unitless": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", - "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", - "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "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==" - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/compat": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.0.tgz", - "integrity": "sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", - "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", - "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", - "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", - "dev": true, - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", - "dev": true, - "dependencies": { - "@types/mdx": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=16", - "react": ">=16" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@remix-run/router": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.17.1.tgz", - "integrity": "sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q==", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/addon-actions": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.2.tgz", - "integrity": "sha512-SN4cSRt3f0qXi5te+yhMseSdQuZntA8lGlASbRmN77YQTpIaGsNiH88xFoky0s9qz531hiRfU1R0ZSMylBwSKw==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@types/uuid": "^9.0.1", - "dequal": "^2.0.2", - "polished": "^4.2.2", - "uuid": "^9.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-actions/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@storybook/addon-backgrounds": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.2.tgz", - "integrity": "sha512-m/xJe7uKL+kfJx7pQcHwAeIvJ3tdLIpDGrMAVDNDJHcAxfe44cFjIInaV/1HKf3y5Awap+DZFW66ekkxuI9zzA==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "memoizerific": "^1.11.3", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-controls": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.2.tgz", - "integrity": "sha512-y241aOANGzT5XBADUIvALwG/xF5eC6UItzmWJaFvOzSBCq74GIA0+Hu9atyFdvFQbXOrdvPWC4jR+9iuBFRxAA==", - "dev": true, - "dependencies": { - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-docs": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.2.tgz", - "integrity": "sha512-qk/yjAR9RpsSrKLLbeCgb6u58c8TmYqyJSnXgbAozZZNKHBWlIpvZ/hTNYud8qo0coPlxnLdjnZf32TykWGlAg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.4", - "@mdx-js/react": "^3.0.0", - "@storybook/blocks": "8.2.2", - "@storybook/csf-plugin": "8.2.2", - "@storybook/global": "^5.0.0", - "@storybook/react-dom-shim": "8.2.2", - "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "fs-extra": "^11.1.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "rehype-external-links": "^3.0.0", - "rehype-slug": "^6.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-docs/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@storybook/addon-essentials": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.2.tgz", - "integrity": "sha512-yN//BFMbSvNV0+Sll2hcKmgJX06TUKQDm6pZimUjkXczFtOmK7K/UdDmKjWS+qjhfJdWpxdRoEpxoHvvRmNfsA==", - "dev": true, - "dependencies": { - "@storybook/addon-actions": "8.2.2", - "@storybook/addon-backgrounds": "8.2.2", - "@storybook/addon-controls": "8.2.2", - "@storybook/addon-docs": "8.2.2", - "@storybook/addon-highlight": "8.2.2", - "@storybook/addon-measure": "8.2.2", - "@storybook/addon-outline": "8.2.2", - "@storybook/addon-toolbars": "8.2.2", - "@storybook/addon-viewport": "8.2.2", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-highlight": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.2.tgz", - "integrity": "sha512-yDTRzzL+IJAymgY32xoZl09BGBVmPOUV2wVNGYcZkkBLvz2GSQMTfUe1/7F4jAx//+rFBu48/MQzsTC7Bk8kPw==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-interactions": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.2.tgz", - "integrity": "sha512-zRRuUwm/l41JtTUgjIoQTUgLT99Hsdz9cqKca/8NYo1MGBdEcKE41DH4aBIzKaOKFu7p9q00/o/X1EqYX4LMUA==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@storybook/instrumenter": "8.2.2", - "@storybook/test": "8.2.2", - "polished": "^4.2.2", - "ts-dedent": "^2.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-links": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.2.tgz", - "integrity": "sha512-eGh7O7SgTJMtnuXC0HlRPOegu1njcJS2cnVqjbzjvjxsPSBhbHpdYMi9Q9E7al/FKuqMUOjIR9YLIlmK1AJaqA==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@storybook/global": "^5.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } - } - }, - "node_modules/@storybook/addon-measure": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.2.tgz", - "integrity": "sha512-3rCo/aMltt5FrBVdr2dYlD8HlE2q9TLKGJZnwh9on4QyL6ArHbdYw0LmyHe/LrFahJ49w1XQZBMSJcAdRkkS7w==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "tiny-invariant": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-onboarding": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.2.tgz", - "integrity": "sha512-dCdE8Mt/JW6cq6dY7co35Sul/bAkUT3ixaxBrUagFUYUQ/PTYM6p4/B+45RURD5S9z8LVHH1rVgmEeScm3U78w==", - "dev": true, - "dependencies": { - "react-confetti": "^6.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-outline": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.2.tgz", - "integrity": "sha512-Y+PQtfTNO8GLX5nz+3x5AMfHNvdGvBXazJ29+Rl1ygYN1+Q9ZhRJDE1kAK0wLxb7CG14peAgdYEaQb3Rduv7HQ==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-toolbars": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.2.tgz", - "integrity": "sha512-JGOueOc3EPljlCl9dVSQee0aMYoqGNvN0UH+R6wYJ3bDZ+tUG/iYpsZVPUOvS8vzp3Imk5Is1kzQbQYJtzdGLg==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-viewport": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.2.tgz", - "integrity": "sha512-gkZ8bsjGGP0NuevkT2iKC+szezSy+w4BrBDknf490mRU2K/B2e7TGojf/j/AtxzILMzD4IKzKUXbE/zwcqjZvA==", - "dev": true, - "dependencies": { - "memoizerific": "^1.11.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/addon-webpack5-compiler-swc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", - "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", - "dependencies": { - "@swc/core": "^1.7.3", - "swc-loader": "^0.2.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@storybook/blocks": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.2.tgz", - "integrity": "sha512-av0Tryg4toDl2L/d1ABErtsAk9wvM1su6+M4wq5/Go50sk5IjGTldhbZFa9zNOohxLkZwaj0Q5xAgJ1Y+m5KrQ==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@storybook/global": "^5.0.0", - "@storybook/icons": "^1.2.5", - "@types/lodash": "^4.14.167", - "color-convert": "^2.0.1", - "dequal": "^2.0.2", - "lodash": "^4.17.21", - "markdown-to-jsx": "^7.4.5", - "memoizerific": "^1.11.3", - "polished": "^4.2.2", - "react-colorful": "^5.1.2", - "telejson": "^7.2.0", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack5": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.3.tgz", - "integrity": "sha512-yU9rtcVpo12vD8m/nbdepyJ09K937ZnSsrvIM9XfzbxXA/+p4Cov9Rjg1VfoWyRd1ApxaztSktQlawBlb6bKEA==", - "dev": true, - "dependencies": { - "@storybook/core-webpack": "8.2.3", - "@types/node": "^18.0.0", - "@types/semver": "^7.3.4", - "browser-assert": "^1.2.1", - "case-sensitive-paths-webpack-plugin": "^2.4.0", - "cjs-module-lexer": "^1.2.3", - "constants-browserify": "^1.0.0", - "css-loader": "^6.7.1", - "es-module-lexer": "^1.5.0", - "express": "^4.19.2", - "fork-ts-checker-webpack-plugin": "^8.0.0", - "fs-extra": "^11.1.0", - "html-webpack-plugin": "^5.5.0", - "magic-string": "^0.30.5", - "path-browserify": "^1.0.1", - "process": "^0.11.10", - "semver": "^7.3.7", - "style-loader": "^3.3.1", - "terser-webpack-plugin": "^5.3.1", - "ts-dedent": "^2.0.0", - "url": "^0.11.0", - "util": "^0.12.4", - "util-deprecate": "^1.0.2", - "webpack": "5", - "webpack-dev-middleware": "^6.1.2", - "webpack-hot-middleware": "^2.25.1", - "webpack-virtual-modules": "^0.6.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.3" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", - "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "chalk": "^4.1.2", - "chokidar": "^3.5.3", - "cosmiconfig": "^7.0.1", - "deepmerge": "^4.2.2", - "fs-extra": "^10.0.0", - "memfs": "^3.4.1", - "minimatch": "^3.0.4", - "node-abort-controller": "^3.0.1", - "schema-utils": "^3.1.1", - "semver": "^7.3.5", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">=12.13.0", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "typescript": ">3.6.0", - "webpack": "^5.11.0" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/@storybook/builder-webpack5/node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dev": true, - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", - "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.12", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } - } - }, - "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", - "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/@storybook/codemod": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.2.2.tgz", - "integrity": "sha512-wRUVKLHVUhbLJYKW3QOufUxJGwaUT4jTCD8+HOGpHPdJO3NrwXu186xt4tuPZO2Y/NnacPeCQPsaK5ok4O8o7A==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/preset-env": "^7.24.4", - "@babel/types": "^7.24.0", - "@storybook/core": "8.2.2", - "@storybook/csf": "0.1.11", - "@types/cross-spawn": "^6.0.2", - "cross-spawn": "^7.0.3", - "globby": "^14.0.1", - "jscodeshift": "^0.15.1", - "lodash": "^4.17.21", - "prettier": "^3.1.1", - "recast": "^0.23.5", - "tiny-invariant": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/codemod/node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/codemod/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/codemod/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/core": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.2.tgz", - "integrity": "sha512-L4ojYI+Os/i5bCReDIlFgEDQSS94mbJlNU9WRzEGZpqNC5/hbFEC9Tip7P1MiRx9NrewkzU7b+UCP7mi3e4drQ==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@types/express": "^4.17.21", - "@types/node": "^18.0.0", - "browser-assert": "^1.2.1", - "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", - "esbuild-register": "^3.5.0", - "express": "^4.19.2", - "process": "^0.11.10", - "recast": "^0.23.5", - "util": "^0.12.4", - "ws": "^8.2.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/core-webpack": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.3.tgz", - "integrity": "sha512-0M4mJM6i4Oqp1javRMg/8wJW7VJ6p6Z8GKp6evfHLEWZAzdnexQIkPd5FFaDlFXbQNH1H0oJ+6ei4nIBtEegKg==", - "dev": true, - "dependencies": { - "@types/node": "^18.0.0", - "ts-dedent": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.3" - } - }, - "node_modules/@storybook/core-webpack/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/core/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/core/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/@storybook/csf": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", - "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", - "dev": true, - "dependencies": { - "type-fest": "^2.19.0" - } - }, - "node_modules/@storybook/csf-plugin": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.2.2.tgz", - "integrity": "sha512-3K2RUpDDvq3DT46qAIj2VBC+fzTTebRUcZUsRfS6G1AzaX9p25iClEHiwcJacFkgQKhkci8A/Ly3Z4JJ3b4Pgw==", - "dev": true, - "dependencies": { - "unplugin": "^1.3.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/global": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", - "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", - "dev": true - }, - "node_modules/@storybook/icons": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.9.tgz", - "integrity": "sha512-cOmylsz25SYXaJL/gvTk/dl3pyk7yBFRfeXTsHvTA3dfhoU/LWSq0NKL9nM7WBasJyn6XPSGnLS4RtKXLw5EUg==", - "dev": true, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/instrumenter": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.2.2.tgz", - "integrity": "sha512-refwnHqKHhya45MgqakhMG0jKhTiEIAl0aOwAaQy9+zf9ncMIYQAXRQsSZ2Z188lFWE24wbeHKteb62a5ZfWwQ==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@vitest/utils": "^1.3.1", - "util": "^0.12.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/preset-react-webpack": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.3.tgz", - "integrity": "sha512-i886+vCMGlpFgOAOIg6BxSHgt38MXS6gqNX8Z65KVVIlI6i/9WqEQeHYfukbdGvVZ96cYWmdrnqUieIIkdCdBw==", - "dev": true, - "dependencies": { - "@storybook/core-webpack": "8.2.3", - "@storybook/react": "8.2.3", - "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", - "@types/node": "^18.0.0", - "@types/semver": "^7.3.4", - "find-up": "^5.0.0", - "fs-extra": "^11.1.0", - "magic-string": "^0.30.5", - "react-docgen": "^7.0.0", - "resolve": "^1.22.8", - "semver": "^7.3.7", - "tsconfig-paths": "^4.2.0", - "webpack": "5" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.3" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/preset-react-webpack/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/react": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.3.tgz", - "integrity": "sha512-818F6pJWFBiwG0r6DiUVrV+qndwbIso2gtgJoituBgIJO2eIzNmkPNSsckbaR7u+FpE4dWiIIhmDVZSnRwvDlA==", - "dev": true, - "dependencies": { - "@storybook/global": "^5.0.0", - "@storybook/react-dom-shim": "8.2.3", - "@types/escodegen": "^0.0.6", - "@types/estree": "^0.0.51", - "@types/node": "^18.0.0", - "acorn": "^7.4.1", - "acorn-jsx": "^5.3.1", - "acorn-walk": "^7.2.0", - "escodegen": "^2.1.0", - "html-tags": "^3.1.0", - "lodash": "^4.17.21", - "prop-types": "^15.7.2", - "react-element-to-jsx-string": "^15.0.0", - "semver": "^7.3.7", - "ts-dedent": "^2.0.0", - "type-fest": "~2.19", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.3", - "typescript": ">= 4.2.x" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/react-docgen-typescript-plugin": { - "version": "1.0.6--canary.9.0c3f3b7.0", - "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", - "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "endent": "^2.0.1", - "find-cache-dir": "^3.3.1", - "flat-cache": "^3.0.4", - "micromatch": "^4.0.2", - "react-docgen-typescript": "^2.2.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "typescript": ">= 4.x", - "webpack": ">= 4" - } - }, - "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@storybook/react-dom-shim": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.2.tgz", - "integrity": "sha512-4fb1/yT9WXHzHjs0In6orIEZxga5eXd9UaXEFGudBgowCjDUVP9LabDdKTbGusz20lfaAkATsRG/W+EcSLoh8w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.2" - } - }, - "node_modules/@storybook/react-webpack5": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.3.tgz", - "integrity": "sha512-lcm73r8S5Uy2ENuFDSR07fW+KRSYGNcrF53VItP+rgFZHrOm7gaeebrjSIA6r4tQwdd9218VaqpQGFrKAURS2w==", - "dev": true, - "dependencies": { - "@storybook/builder-webpack5": "8.2.3", - "@storybook/preset-react-webpack": "8.2.3", - "@storybook/react": "8.2.3", - "@types/node": "^18.0.0" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.3", - "typescript": ">= 4.2.x" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/react-webpack5/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/react/node_modules/@storybook/react-dom-shim": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.3.tgz", - "integrity": "sha512-N8AsM6N1S867GGWt2J2q5oY5ryqxohh3y1HqNtjg+wXf5+RkTD6M2Cgqe6p+JHz81nDKyvvVzP60MvvDhY5VOA==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.2.3" - } - }, - "node_modules/@storybook/react/node_modules/@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "node_modules/@storybook/react/node_modules/@types/node": { - "version": "18.19.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.39.tgz", - "integrity": "sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@storybook/react/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@storybook/test": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.2.2.tgz", - "integrity": "sha512-X2qAKErjTh1X7XLAZqCMtU0ZK8JuwdKmgiqU0oXWxIDmCX6/Dm9ZIcdMZHs/S+K/UnIByjNlQpTShLVfRUeN1w==", - "dev": true, - "dependencies": { - "@storybook/csf": "0.1.11", - "@storybook/instrumenter": "8.2.2", - "@testing-library/dom": "10.1.0", - "@testing-library/jest-dom": "6.4.5", - "@testing-library/user-event": "14.5.2", - "@vitest/expect": "1.6.0", - "@vitest/spy": "1.6.0", - "util": "^0.12.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "storybook": "^8.2.2" - } - }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", - "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", - "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-preset": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", - "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", - "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", - "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", - "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", - "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", - "@svgr/babel-plugin-transform-svg-component": "8.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/core": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", - "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^8.1.3", - "snake-case": "^3.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", - "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", - "dependencies": { - "@babel/types": "^7.21.3", - "entities": "^4.4.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/@svgr/plugin-jsx": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", - "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@svgr/babel-preset": "8.1.0", - "@svgr/hast-util-to-babel-ast": "8.0.0", - "svg-parser": "^2.0.4" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" - } - }, - "node_modules/@svgr/plugin-svgo": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", - "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", - "dependencies": { - "cosmiconfig": "^8.1.3", - "deepmerge": "^4.3.1", - "svgo": "^3.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@svgr/core": "*" - } - }, - "node_modules/@svgr/webpack": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", - "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", - "dependencies": { - "@babel/core": "^7.21.3", - "@babel/plugin-transform-react-constant-elements": "^7.21.3", - "@babel/preset-env": "^7.20.2", - "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.21.0", - "@svgr/core": "8.1.0", - "@svgr/plugin-jsx": "8.1.0", - "@svgr/plugin-svgo": "8.1.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@swc/core": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.6.tgz", - "integrity": "sha512-FZxyao9eQks1MRmUshgsZTmlg/HB2oXK5fghkoWJm/1CU2q2kaJlVDll2as5j+rmWiwkp0Gidlq8wlXcEEAO+g==", - "hasInstallScript": true, - "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.12" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.7.6", - "@swc/core-darwin-x64": "1.7.6", - "@swc/core-linux-arm-gnueabihf": "1.7.6", - "@swc/core-linux-arm64-gnu": "1.7.6", - "@swc/core-linux-arm64-musl": "1.7.6", - "@swc/core-linux-x64-gnu": "1.7.6", - "@swc/core-linux-x64-musl": "1.7.6", - "@swc/core-win32-arm64-msvc": "1.7.6", - "@swc/core-win32-ia32-msvc": "1.7.6", - "@swc/core-win32-x64-msvc": "1.7.6" - }, - "peerDependencies": { - "@swc/helpers": "*" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.6", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.6.tgz", - "integrity": "sha512-6lYHey84ZzsdtC7UuPheM4Rm0Inzxm6Sb8U6dmKc4eCx8JL0LfWG4LC5RsdsrTxnjTsbriWlnhZBffh8ijUHIQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, - "node_modules/@swc/types": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", - "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", - "dependencies": { - "@swc/counter": "^0.1.3" - } - }, - "node_modules/@testing-library/dom": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", - "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", - "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", - "dev": true, - "dependencies": { - "@adobe/css-tools": "^4.3.2", - "@babel/runtime": "^7.9.2", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "lodash": "^4.17.21", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" - }, - "peerDependencies": { - "@jest/globals": ">= 28", - "@types/bun": "latest", - "@types/jest": ">= 28", - "jest": ">= 28", - "vitest": ">= 0.32" - }, - "peerDependenciesMeta": { - "@jest/globals": { - "optional": true - }, - "@types/bun": { - "optional": true - }, - "@types/jest": { - "optional": true - }, - "jest": { - "optional": true - }, - "vitest": { - "optional": true - } - } - }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", - "dev": true - }, - "node_modules/@testing-library/jest-dom/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/user-event": { - "version": "14.5.2", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", - "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", - "dev": true, - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/doctrine": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", - "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", - "dev": true - }, - "node_modules/@types/emscripten": { - "version": "1.39.13", - "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", - "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==", - "dev": true - }, - "node_modules/@types/escodegen": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz", - "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==", - "dev": true - }, - "node_modules/@types/eslint": { - "version": "8.56.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", - "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", - "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/lodash": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", - "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==", - "dev": true - }, - "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true - }, - "node_modules/@types/qs": { - "version": "6.9.15", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", - "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/resolve": { - "version": "1.20.6", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", - "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/unist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", - "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", - "dev": true - }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.16.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "node_modules/@vitest/expect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", - "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", - "dev": true, - "dependencies": { - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", - "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", - "dev": true, - "dependencies": { - "tinyspy": "^2.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", - "dev": true, - "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vitest/utils/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@vitest/utils/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/@yarnpkg/fslib": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", - "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", - "dev": true, - "dependencies": { - "@yarnpkg/libzip": "^2.3.0", - "tslib": "^1.13.0" - }, - "engines": { - "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" - } - }, - "node_modules/@yarnpkg/fslib/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/@yarnpkg/libzip": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", - "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", - "dev": true, - "dependencies": { - "@types/emscripten": "^1.39.6", - "tslib": "^1.13.0" - }, - "engines": { - "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" - } - }, - "node_modules/@yarnpkg/libzip/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "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": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "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, - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.toreversed": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz", - "integrity": "sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ast-types": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", - "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "node_modules/available-typed-arrays": { - "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, - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", - "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/babel-core": { - "version": "7.0.0-bridge.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", - "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, - "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", - "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.2", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", - "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-assert": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", - "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.1.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001642", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", - "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chromatic": { - "version": "11.5.5", - "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.5.5.tgz", - "integrity": "sha512-YS0GJwegF0vpMbwZE68/xJlI4SlUGMqI78V2ATAF19YwTHaq8jGP1CPQGKUSlgWUhzPtyu3ELy6Dvv/owYljAg==", - "dev": true, - "bin": { - "chroma": "dist/bin.js", - "chromatic": "dist/bin.js", - "chromatic-cli": "dist/bin.js" - }, - "peerDependencies": { - "@chromatic-com/cypress": "^0.*.* || ^1.0.0", - "@chromatic-com/playwright": "^0.*.* || ^1.0.0" - }, - "peerDependenciesMeta": { - "@chromatic-com/cypress": { - "optional": true - }, - "@chromatic-com/playwright": { - "optional": true - } - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/citty": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", - "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", - "dev": true, - "dependencies": { - "consola": "^3.2.3" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", - "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", - "dev": true - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/compare-versions": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", - "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/confbox": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", - "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", - "dev": true - }, - "node_modules/consola": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", - "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", - "dev": true, - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "node_modules/core-js-compat": { - "version": "3.37.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", - "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", - "dependencies": { - "browserslist": "^4.23.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dev": true, - "dependencies": { - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", - "dev": true - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true - }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "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.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "dev": true - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "dev": true - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.827", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.827.tgz", - "integrity": "sha512-VY+J0e4SFcNfQy19MEoMdaIcZLmDCprqvBtkii1WTCTQHpRvf5N8+3kTYCgL/PcntvwQvmMJWTuDPsq+IlhWKQ==" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/endent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", - "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", - "dev": true, - "dependencies": { - "dedent": "^0.7.0", - "fast-json-parse": "^1.0.3", - "objectorarray": "^1.0.5" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", - "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "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, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "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, - "dependencies": { - "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==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" - } - }, - "node_modules/esbuild-register": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.5.0.tgz", - "integrity": "sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "peerDependencies": { - "esbuild": ">=0.12 <1" - } - }, - "node_modules/esbuild-register/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/esbuild-register/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.8.0.tgz", - "integrity": "sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.17.1", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.8.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-node/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 - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint-import-resolver-typescript/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils/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 - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "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.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/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 - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { - "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, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", - "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", - "dev": true, - "dependencies": { - "aria-query": "~5.1.3", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.9.1", - "axobject-query": "~3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.19", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", - "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.6" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.34.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.4.tgz", - "integrity": "sha512-Np+jo9bUwJNxCsT12pXtrGhJgT3T44T1sHhn1Ssr42XFn8TES0267wPGo5nNrMHi8qkyimDAX2BUmkf9pSaVzA==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.toreversed": "^1.1.2", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-react/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-storybook": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.8.0.tgz", - "integrity": "sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==", - "dev": true, - "dependencies": { - "@storybook/csf": "^0.0.1", - "@typescript-eslint/utils": "^5.62.0", - "requireindex": "^1.2.0", - "ts-dedent": "^2.2.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "eslint": ">=6" - } - }, - "node_modules/eslint-plugin-storybook/node_modules/@storybook/csf": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", - "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.15" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", - "dev": true, - "dependencies": { - "acorn": "^8.12.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", - "dev": true, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.6.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "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 - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-parse": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", - "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fast-uri": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", - "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-package-json": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", - "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", - "dev": true, - "dependencies": { - "walk-up-path": "^3.0.1" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/file-entry-cache/node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/filesize": { - "version": "10.1.4", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.4.tgz", - "integrity": "sha512-ryBwPIIeErmxgPnm6cbESAzXjuEFubs+yKYLBZvg3CaiNcmkJChoOGcBSrZ6IwkMwPABwPpVXE6IlNdGJJrvEg==", - "dev": true, - "engines": { - "node": ">= 10.4.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flat-cache/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true - }, - "node_modules/flow-parser": { - "version": "0.239.1", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.239.1.tgz", - "integrity": "sha512-topOrETNxJ6T2gAnQiWqAlzGPj8uI2wtmNOlDIMNB+qyvGJZ6R++STbUOTAYmvPhOMz2gXnXPH0hOvURYmrBow==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", - "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/giget": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", - "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", - "dev": true, - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.2.3", - "defu": "^6.1.4", - "node-fetch-native": "^1.6.3", - "nypm": "^0.3.8", - "ohash": "^1.1.3", - "pathe": "^1.1.2", - "tar": "^6.2.0" - }, - "bin": { - "giget": "dist/cli.mjs" - } - }, - "node_modules/github-slugger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", - "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", - "dev": true - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/globals": { - "version": "15.8.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.8.0.tgz", - "integrity": "sha512-VZAJ4cewHTExBWDHR6yptdIBlx9YSSZuwojj9Nt5mBRXQzrKakDsVKQ1J63sklLvzAJm0X5+RpO4i3Y2hcOnFw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "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, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "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==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "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, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "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==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hast-util-heading-rank": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", - "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-element": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", - "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", - "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", - "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", - "dev": true, - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-absolute-url": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", - "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.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==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "dependencies": { - "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==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.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", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jscodeshift": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", - "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.23.0", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/preset-flow": "^7.22.15", - "@babel/preset-typescript": "^7.23.0", - "@babel/register": "^7.22.15", - "babel-core": "^7.0.0-bridge.0", - "chalk": "^4.1.2", - "flow-parser": "0.*", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.4", - "neo-async": "^2.5.0", - "node-dir": "^0.1.17", - "recast": "^0.23.3", - "temp": "^0.8.4", - "write-file-atomic": "^2.3.0" - }, - "bin": { - "jscodeshift": "bin/jscodeshift.js" - }, - "peerDependencies": { - "@babel/preset-env": "^7.1.6" - }, - "peerDependenciesMeta": { - "@babel/preset-env": { - "optional": true - } - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lottie-react": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", - "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", - "dependencies": { - "lottie-web": "^5.10.2" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/lottie-web": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", - "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "dev": true, - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/map-or-similar": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", - "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", - "dev": true - }, - "node_modules/markdown-to-jsx": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.4.7.tgz", - "integrity": "sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==", - "dev": true, - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "react": ">= 0.14.0" - } - }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memoizerific": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", - "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", - "dev": true, - "dependencies": { - "map-or-similar": "^1.5.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mlly": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", - "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "pathe": "^1.1.2", - "pkg-types": "^1.1.1", - "ufo": "^1.5.3" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/mylas": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/mylas/-/mylas-2.1.13.tgz", - "integrity": "sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/raouldeheer" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "dev": true - }, - "node_modules/node-dir": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", - "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", - "dev": true, - "dependencies": { - "minimatch": "^3.0.2" - }, - "engines": { - "node": ">= 0.10.5" - } - }, - "node_modules/node-dir/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/node-dir/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/node-fetch-native": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", - "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/nypm": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.9.tgz", - "integrity": "sha512-BI2SdqqTHg2d4wJh8P9A1W+bslg33vOE9IZDY6eR2QC+Pu1iNBVZUqczrd43rJb+fMzHU7ltAYKsEFY/kHMFcw==", - "dev": true, - "dependencies": { - "citty": "^0.1.6", - "consola": "^3.2.3", - "execa": "^8.0.1", - "pathe": "^1.1.2", - "pkg-types": "^1.1.1", - "ufo": "^1.5.3" - }, - "bin": { - "nypm": "dist/cli.mjs" - }, - "engines": { - "node": "^14.16.0 || >=16.10.0" - } - }, - "node_modules/nypm/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/nypm/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/nypm/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nypm/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/nypm/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "dependencies": { - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "dependencies": { - "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" - } - }, - "node_modules/objectorarray": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", - "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", - "dev": true - }, - "node_modules/ohash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", - "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-types": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.3.tgz", - "integrity": "sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==", - "dev": true, - "dependencies": { - "confbox": "^0.1.7", - "mlly": "^1.7.1", - "pathe": "^1.1.2" - } - }, - "node_modules/plimit-lit": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/plimit-lit/-/plimit-lit-1.6.1.tgz", - "integrity": "sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==", - "dev": true, - "dependencies": { - "queue-lit": "^1.5.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/polished": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", - "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.17.8" - }, - "engines": { - "node": ">=10" - } - }, - "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, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", - "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", - "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", - "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-lit": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/queue-lit/-/queue-lit-1.5.2.tgz", - "integrity": "sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-colorful": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", - "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", - "dev": true, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "node_modules/react-confetti": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", - "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", - "dev": true, - "dependencies": { - "tween-functions": "^1.2.0" - }, - "engines": { - "node": ">=10.18" - }, - "peerDependencies": { - "react": "^16.3.0 || ^17.0.1 || ^18.0.0" - } - }, - "node_modules/react-docgen": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.0.3.tgz", - "integrity": "sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.18.9", - "@babel/traverse": "^7.18.9", - "@babel/types": "^7.18.9", - "@types/babel__core": "^7.18.0", - "@types/babel__traverse": "^7.18.0", - "@types/doctrine": "^0.0.9", - "@types/resolve": "^1.20.2", - "doctrine": "^3.0.0", - "resolve": "^1.22.1", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=16.14.0" - } - }, - "node_modules/react-docgen-typescript": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", - "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", - "dev": true, - "peerDependencies": { - "typescript": ">= 4.3.x" - } - }, - "node_modules/react-docgen/node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-element-to-jsx-string": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", - "integrity": "sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==", - "dev": true, - "dependencies": { - "@base2/pretty-print-object": "1.0.1", - "is-plain-object": "5.0.0", - "react-is": "18.1.0" - }, - "peerDependencies": { - "react": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0", - "react-dom": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0" - } - }, - "node_modules/react-element-to-jsx-string/node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-element-to-jsx-string/node_modules/react-is": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", - "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", - "dev": true - }, - "node_modules/react-inspector": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz", - "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==", - "dev": true, - "peerDependencies": { - "react": "^16.8.4 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-router": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.1.tgz", - "integrity": "sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg==", - "dependencies": { - "@remix-run/router": "1.17.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.24.1.tgz", - "integrity": "sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg==", - "dependencies": { - "@remix-run/router": "1.17.1", - "react-router": "6.24.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/recast": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", - "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", - "dev": true, - "dependencies": { - "ast-types": "^0.16.1", - "esprima": "~4.0.0", - "source-map": "~0.6.1", - "tiny-invariant": "^1.3.3", - "tslib": "^2.0.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/redent/node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "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", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/rehype-external-links": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", - "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-is-element": "^3.0.0", - "is-absolute-url": "^4.0.0", - "space-separated-tokens": "^2.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-slug": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", - "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "github-slugger": "^2.0.0", - "hast-util-heading-rank": "^3.0.0", - "hast-util-to-string": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true, - "engines": { - "node": ">=0.10.5" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/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 - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.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, - "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, - "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/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", - "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/storybook": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.2.2.tgz", - "integrity": "sha512-xDT9gyzAEFQNeK7P+Mj/8bNzN+fbm6/4D6ihdSzmczayjydpNjMs74HDHMY6S4Bfu6tRVyEK2ALPGnr6ZVofBA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/types": "^7.24.0", - "@storybook/codemod": "8.2.2", - "@storybook/core": "8.2.2", - "@types/semver": "^7.3.4", - "@yarnpkg/fslib": "2.10.3", - "@yarnpkg/libzip": "2.3.0", - "chalk": "^4.1.0", - "commander": "^6.2.1", - "cross-spawn": "^7.0.3", - "detect-indent": "^6.1.0", - "envinfo": "^7.7.3", - "execa": "^5.0.0", - "fd-package-json": "^1.2.0", - "find-up": "^5.0.0", - "fs-extra": "^11.1.0", - "giget": "^1.0.0", - "globby": "^14.0.1", - "jscodeshift": "^0.15.1", - "leven": "^3.1.0", - "ora": "^5.4.1", - "prettier": "^3.1.1", - "prompts": "^2.4.0", - "semver": "^7.3.7", - "strip-json-comments": "^3.0.1", - "tempy": "^3.1.0", - "tiny-invariant": "^1.3.1", - "ts-dedent": "^2.0.0" - }, - "bin": { - "getstorybook": "bin/index.cjs", - "sb": "bin/index.cjs", - "storybook": "bin/index.cjs" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/storybook-addon-react-router-v6": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/storybook-addon-react-router-v6/-/storybook-addon-react-router-v6-2.0.15.tgz", - "integrity": "sha512-4vOYIQwehlQLyXaCT9K0Iu0po2Z+pANGsqkfm/BQuAEjE9MoN7vrsrQLHINhKbmQVtNMmuS/oBR3GGNbqQ1gew==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "compare-versions": "^6.0.0", - "react-inspector": "6.0.2" - }, - "peerDependencies": { - "@storybook/blocks": "^7.0.0", - "@storybook/channels": "^7.0.0", - "@storybook/components": "^7.0.0", - "@storybook/core-events": "^7.0.0", - "@storybook/manager-api": "^7.0.0", - "@storybook/preview-api": "^7.0.0", - "@storybook/theming": "^7.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-router-dom": "^6.4.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/storybook/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/storybook/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/storybook/node_modules/globby": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", - "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/storybook/node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", - "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", - "dev": true, - "dependencies": { - "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", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", - "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "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, - "dependencies": { - "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" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-loader": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", - "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", - "dev": true, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" - }, - "node_modules/svgo": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", - "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^5.1.0", - "css-tree": "^2.3.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" - } - }, - "node_modules/svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/svgo/node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/svgo/node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/svgo/node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/svgo/node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/svgo/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/swc-loader": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", - "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", - "dependencies": { - "@swc/counter": "^0.1.3" - }, - "peerDependencies": { - "@swc/core": "^1.2.147", - "webpack": ">=2" - } - }, - "node_modules/synckit": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", - "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/telejson": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", - "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", - "dev": true, - "dependencies": { - "memoizerific": "^1.11.3" - } - }, - "node_modules/temp": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", - "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", - "dev": true, - "dependencies": { - "rimraf": "~2.6.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/temp-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/temp/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/temp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/temp/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/temp/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/tempy": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", - "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", - "dev": true, - "dependencies": { - "is-stream": "^3.0.0", - "temp-dir": "^3.0.0", - "type-fest": "^2.12.2", - "unique-string": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terser": { - "version": "5.31.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.2.tgz", - "integrity": "sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.10", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", - "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.20", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.1", - "terser": "^5.26.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/tiny-invariant": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", - "dev": true - }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "dev": true, - "engines": { - "node": ">=6.10" - } - }, - "node_modules/ts-loader": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", - "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4", - "source-map": "^0.7.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-loader/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tsc-alias": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.10.tgz", - "integrity": "sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.3", - "commander": "^9.0.0", - "globby": "^11.0.4", - "mylas": "^2.1.9", - "normalize-path": "^3.0.0", - "plimit-lit": "^1.2.6" - }, - "bin": { - "tsc-alias": "dist/bin/index.js" - } - }, - "node_modules/tsc-alias/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tween-functions": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", - "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", - "dev": true - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", - "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", - "dev": true, - "dependencies": { - "@typescript-eslint/eslint-plugin": "7.16.0", - "@typescript-eslint/parser": "7.16.0", - "@typescript-eslint/utils": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/ufo": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", - "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", - "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==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dev": true, - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dev": true, - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unplugin": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.11.0.tgz", - "integrity": "sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "chokidar": "^3.6.0", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.6.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", - "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", - "dev": true, - "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.11.2" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/url/node_modules/qs": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", - "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/walk-up-path": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", - "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", - "dev": true - }, - "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webpack": { - "version": "5.93.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", - "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.0", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.2.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-hot-middleware": { - "version": "2.26.1", - "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", - "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", - "dev": true, - "dependencies": { - "ansi-html-community": "0.0.8", - "html-entities": "^2.1.0", - "strip-ansi": "^6.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-virtual-modules": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", - "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", - "dev": true - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "dependencies": { - "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.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/HDesign/package.json b/HDesign/package.json deleted file mode 100644 index 062987bf1..000000000 --- a/HDesign/package.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "name": "haengdong-design", - "version": "0.1.81", - "description": "", - "main": "./dist/index.js", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "start": "webpack serve ", - "build": "rm -rf dist && mkdir dist && tsc && cp -r ./src/assets ./dist && tsc-alias", - "storybook": "storybook dev -p 6006", - "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", - "format": "prettier --write {src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", - "build-storybook": "storybook build" - }, - "keywords": [], - "author": "", - "license": "ISC", - "devDependencies": { - "@chromatic-com/storybook": "^1.6.1", - "@eslint/compat": "^1.1.0", - "@eslint/js": "^9.6.0", - "@storybook/addon-essentials": "^8.2.2", - "@storybook/addon-interactions": "^8.2.2", - "@storybook/addon-links": "^8.2.2", - "@storybook/addon-onboarding": "^8.2.2", - "@storybook/blocks": "^8.2.2", - "@storybook/react": "^8.2.2", - "@storybook/react-webpack5": "^8.2.3", - "@storybook/test": "^8.2.2", - "@swc/core": "^1.7.6", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.16.0", - "@typescript-eslint/parser": "^7.16.0", - "esbuild": "^0.23.0", - "eslint": "^9.8.0", - "eslint-config-prettier": "^9.1.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-prettier": "^5.1.3", - "eslint-plugin-react": "^7.34.4", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-storybook": "^0.8.0", - "file-loader": "^6.2.0", - "globals": "^15.8.0", - "prettier": "3.3.2", - "storybook": "^8.2.2", - "storybook-addon-react-router-v6": "^2.0.15", - "ts-loader": "^9.5.1", - "tsc-alias": "^1.8.10", - "typescript": "^5.5.3", - "typescript-eslint": "^7.16.0" - }, - "dependencies": { - "@emotion/react": "^11.11.4", - "@storybook/addon-webpack5-compiler-swc": "^1.0.5", - "@svgr/webpack": "^8.1.0", - "lottie-react": "^2.4.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" - }, - "engines": { - "npm": ">=10.7.0", - "node": ">=20.15.1" - } -} diff --git a/HDesign/src/assets/index.ts b/HDesign/src/assets/index.ts deleted file mode 100644 index a9c277581..000000000 --- a/HDesign/src/assets/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export {default as InputDelete} from '@assets/inputDelete.svg'; -export {default as Buljusa} from '@assets/buljusa.svg'; -export {default as Error} from '@assets/error.svg'; -export {default as Confirm} from '@assets/confirm.svg'; -export {default as Trash} from '@assets/trash.svg'; -export {default as Search} from '@assets/search.svg'; -export {default as RightChevron} from '@assets/rightChevron.svg'; diff --git a/HDesign/src/assets/svg.d.ts b/HDesign/src/assets/svg.d.ts deleted file mode 100644 index 2db81e756..000000000 --- a/HDesign/src/assets/svg.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module '*.svg' { - import type React from 'react'; - - const SVG: React.FC<React.SVGProps<SVGSVGElement>>; - export default SVG; -} diff --git a/HDesign/src/components/Toast/Toast.stories.tsx b/HDesign/src/components/Toast/Toast.stories.tsx deleted file mode 100644 index fd672959c..000000000 --- a/HDesign/src/components/Toast/Toast.stories.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import Toast from '@components/Toast/Toast'; - -const meta = { - title: 'Components/Toast', - component: Toast, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - args: { - type: 'confirm', - position: 'top', - top: '80px', - message: `서버 오류로 인해 인원을 설정하는데 실패했어요. -두글자면 이렇게 보여요.`, - onUndo: () => alert('되돌리기 버튼이 눌렸습니다. 실행할 로직을 전달해주세요'), - }, -} satisfies Meta<typeof Toast>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const ConfirmToast: Story = { - args: { - ...meta.args, - type: 'confirm', - top: '80px', - message: `이 첫번째 토스트 그림자 짙은거 두 개 떠서 그런거임 css 잘못한거 아닙니다. 잘못 없습니다. 스토리북이 잘못한거에요. 저희는 최선을 다했어요.. `, - }, -}; - -export const ConfirmToastWithoutUndo: Story = { - args: { - ...meta.args, - onUndo: undefined, - top: '160px', - }, -}; - -export const ErrorToast: Story = { - args: { - ...meta.args, - top: '240px', - type: 'error', - message: `님 이거 다 작성했는데, 혹시 되돌림? - 되돌릴 수도 있음 ㅇㅇ 굿`, - }, -}; - -export const ErrorToastWithoutUndo: Story = { - args: { - ...meta.args, - top: '320px', - onUndo: undefined, - type: 'error', - }, -}; - -export const NoneToast: Story = { - args: { - ...meta.args, - top: '400px', - onUndo: undefined, - type: 'none', - message: '웨디는 커비의 먹잇감인가요? 그치만 감자는 웨디한테 먹힘 쿠스쿠스 ㅋ', - }, -}; diff --git a/HDesign/src/components/Toast/Toast.style.ts b/HDesign/src/components/Toast/Toast.style.ts deleted file mode 100644 index 0496bc722..000000000 --- a/HDesign/src/components/Toast/Toast.style.ts +++ /dev/null @@ -1,44 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -import {ToastPosition} from './Toast.type'; - -type ToastMarginStyle = { - position?: ToastPosition; - bottom?: string; - top?: string; -}; - -export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => - css({ - position: 'absolute', - bottom: position === 'bottom' ? `${bottom}` : 'auto', - top: position === 'top' ? `${top}` : 'auto', - left: '50%', - transform: 'translate(-50%)', - - width: '100%', - maxWidth: '48rem', - paddingInline: '0.5rem', - }); - -export const toastStyle = (theme: Theme) => - css({ - width: '100%', - padding: '0.625rem 1rem', - - backgroundColor: theme.colors.gray, - boxShadow: '0 8px 12px rgba(0, 0, 0, 0.16);', - - borderRadius: '1.25rem', - }); - -export const textStyle = (theme: Theme) => - css({ - width: '100%', - - color: theme.colors.white, - - whiteSpace: 'pre-line', - }); diff --git a/HDesign/src/components/Toast/Toast.tsx b/HDesign/src/components/Toast/Toast.tsx deleted file mode 100644 index 972ce6220..000000000 --- a/HDesign/src/components/Toast/Toast.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {createPortal} from 'react-dom'; - -import Text from '@components/Text/Text'; -import Flex from '@components/Flex/Flex'; -import Icon from '@components/Icon/Icon'; - -import {useTheme} from '@theme/HDesignProvider'; - -import Button from '../Button/Button'; - -import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; -import {ToastProps, ToastType} from './Toast.type'; - -const renderIcon = (type: ToastType) => { - switch (type) { - case 'error': - return <Icon iconType="error" />; - - case 'confirm': - return <Icon iconType="confirm" />; - - case 'none': - return null; - - default: - return null; - } -}; - -const Toast = ({ - type = 'confirm', - top = '0px', - bottom = '0px', - isClickToClose = true, - position = 'bottom', - message, - onUndo, - onClose, - ...htmlProps -}: ToastProps) => { - const {theme} = useTheme(); - const styleProps = {position, top, bottom}; - - const handleClickToClose = () => { - if (!isClickToClose || !onClose) return; - - onClose(); - }; - - return createPortal( - <div css={toastMarginStyle({...styleProps})} {...htmlProps} onClick={handleClickToClose}> - <div css={toastStyle(theme)}> - <Flex justifyContent="spaceBetween" alignItems="center"> - <Flex alignItems="center" gap="0.5rem"> - {renderIcon(type)} - <Text size="smallBodyBold" css={textStyle(theme)}> - {message} - </Text> - </Flex> - {onUndo && ( - <Button variants="tertiary" size="small" onClick={onUndo}> - 되돌리기 - </Button> - )} - </Flex> - </div> - </div>, - document.body, - ); -}; - -export default Toast; diff --git a/HDesign/src/components/Toast/Toast.type.ts b/HDesign/src/components/Toast/Toast.type.ts deleted file mode 100644 index 12a436c2d..000000000 --- a/HDesign/src/components/Toast/Toast.type.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type ToastPosition = 'bottom' | 'top'; -export type ToastType = 'error' | 'confirm' | 'none'; - -export interface ToastStyleProps { - bottom?: string; - top?: string; -} - -export interface ToastOptionProps { - position?: ToastPosition; - type?: ToastType; - onUndo?: () => void; - isClickToClose?: boolean; - onClose?: () => void; -} - -export interface ToastRequiredProps { - message: string; -} - -export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; diff --git a/HDesign/src/components/Toast/ToastProvider.stories.tsx b/HDesign/src/components/Toast/ToastProvider.stories.tsx deleted file mode 100644 index 32c8c6917..000000000 --- a/HDesign/src/components/Toast/ToastProvider.stories.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import Button from '../Button/Button'; - -import {ToastProvider, useToast} from './ToastProvider'; - -const meta = { - title: 'Components/ToastProvider', - component: ToastProvider, - tags: ['autodocs'], - decorators: [ - Story => ( - <ToastProvider> - <Story /> - </ToastProvider> - ), - ], -} satisfies Meta<typeof ToastProvider>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = { - decorators: [ - () => { - const {showToast} = useToast(); - - return ( - <Button - onClick={() => - showToast({ - isAlwaysOn: true, - message: '이거자냥 (feat. 쿠키)', - type: 'confirm', - position: 'top', - }) - } - > - 토스트 열기 - </Button> - ); - }, - ], -}; diff --git a/HDesign/src/components/Toast/ToastProvider.tsx b/HDesign/src/components/Toast/ToastProvider.tsx deleted file mode 100644 index 9201fdc6d..000000000 --- a/HDesign/src/components/Toast/ToastProvider.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {createContext, useCallback, useContext, useEffect, useState} from 'react'; - -import {ToastProps} from './Toast.type'; -import Toast from './Toast'; - -export const ToastContext = createContext<ToastContextProps | null>(null); - -interface ToastContextProps { - showToast: (args: ShowToast) => void; -} - -type ShowToast = ToastProps & { - showingTime?: number; - isAlwaysOn?: boolean; -}; - -const ToastProvider = ({children}: React.PropsWithChildren) => { - const [currentToast, setCurrentToast] = useState<ShowToast | null>(null); - - const showToast = useCallback(({showingTime = 3000, isAlwaysOn = false, ...toastProps}: ShowToast) => { - setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); - }, []); - - const closeToast = () => { - setCurrentToast(null); - }; - - useEffect(() => { - if (!currentToast) return; - - if (!currentToast.isAlwaysOn) { - const timer = setTimeout(() => { - setCurrentToast(null); - }, currentToast.showingTime); - - return () => clearTimeout(timer); - } - }, [currentToast]); - - return ( - <ToastContext.Provider value={{showToast}}> - {currentToast && <Toast onClose={closeToast} {...currentToast} />} - {children} - </ToastContext.Provider> - ); -}; - -const useToast = () => { - const context = useContext(ToastContext); - - if (!context) { - throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); - } - - return context; -}; - -export {ToastProvider, useToast}; diff --git a/HDesign/src/index.tsx b/HDesign/src/index.tsx deleted file mode 100644 index 656690951..000000000 --- a/HDesign/src/index.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import BottomSheet from '@components/BottomSheet/BottomSheet'; -import Button from '@components/Button/Button'; -import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; -import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; -import EditableItem from '@components/EditableItem/EditableItem'; -import ExpenseList from '@components/ExpenseList/ExpenseList'; -import FixedButton from '@components/FixedButton/FixedButton'; -import Flex from '@components/Flex/Flex'; -import Icon from '@components/Icon/Icon'; -import IconButton from '@components/IconButton/IconButton'; -import Input from '@components/Input/Input'; -import LabelInput from '@components/LabelInput/LabelInput'; -import ListButton from '@components/ListButton/ListButton'; -import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; -import Search from '@components/Search/Search'; -import Switch from '@components/Switch/Switch'; -import Tab from '@components/Tabs/Tab'; -import Tabs from '@components/Tabs/Tabs'; -import Text from '@components/Text/Text'; -import TextButton from '@components/TextButton/TextButton'; -import Title from '@components/Title/Title'; -import Toast from '@components/Toast/Toast'; -import Back from '@components/TopNav/Back'; -import TopNav from '@components/TopNav/TopNav'; -import {ToastProvider, useToast} from '@components/Toast/ToastProvider'; - -import {MainLayout} from '@layouts/MainLayout'; -import {ContentLayout} from '@layouts/ContentLayout'; - -import {HDesignProvider} from '@theme/HDesignProvider'; - -export { - BottomSheet, - Button, - DragHandleItem, - DragHandleItemContainer, - EditableItem, - ExpenseList, - FixedButton, - Flex, - Icon, - IconButton, - Input, - LabelInput, - ListButton, - LabelGroupInput, - Search, - Switch, - Tab, - Tabs, - Text, - TextButton, - Title, - Toast, - TopNav, - Back, - MainLayout, - ContentLayout, - ToastProvider, - useToast, - HDesignProvider, -}; diff --git a/HDesign/tsconfig.json b/HDesign/tsconfig.json deleted file mode 100644 index ca7b8b78f..000000000 --- a/HDesign/tsconfig.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "compilerOptions": { - "sourceMap": true, - "outDir": "./dist", - "target": "ES5", - "skipLibCheck": true, - "module": "commonjs", - "moduleResolution": "node", - "strict": true, - "declaration": true, - "declarationDir": "./dist", - "resolveJsonModule": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "jsx": "react-jsx", - "allowJs": true, - "baseUrl": ".", - "paths": { - "@*": ["src/*"], - "@components/*": ["src/components/*"], - "@layouts/*": ["src/layouts/*"], - "@token/*": ["src/token/*"], - "@type/*": ["src/type/*"], - "@theme/*": ["src/theme/*"], - "@assets/*": ["src/assets/*"], - "@utils/*": ["src/utils/*"] - }, - "jsxImportSource": "@emotion/react", - "allowSyntheticDefaultImports": true - }, - "include": ["src"], - "exclude": ["./node_modules", "dist"] -} diff --git a/client/.gitignore b/client/.gitignore index cf03bec6b..54b01c541 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -12,3 +12,6 @@ dist # Sentry Config File .env.sentry-build-plugin + +storybook-static +*storybook.log diff --git a/client/.storybook/main.ts b/client/.storybook/main.ts new file mode 100644 index 000000000..a06f80f22 --- /dev/null +++ b/client/.storybook/main.ts @@ -0,0 +1,59 @@ +/** @type { import('@storybook/react-webpack5').StorybookConfig } */ +import type {StorybookConfig} from '@storybook/react-webpack5'; +import path from 'path'; +import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: [ + '@storybook/addon-webpack5-compiler-swc', + '@storybook/addon-onboarding', + '@storybook/addon-links', + '@storybook/addon-essentials', + '@chromatic-com/storybook', + '@storybook/addon-interactions', + ], + framework: { + name: '@storybook/react-webpack5', + options: {}, + }, + webpackFinal: async config => { + if (config.resolve) { + config.resolve.alias = { + ...config.resolve.alias, + '@apis': path.resolve(__dirname, '../src/apis/'), + '@assets': path.resolve(__dirname, '../src/assets/'), + '@components': path.resolve(__dirname, '../src/components/'), + '@constants': path.resolve(__dirname, '../src/constants/'), + '@hooks': path.resolve(__dirname, '../src/hooks/'), + '@store': path.resolve(__dirname, '../src/store/'), + '@mocks': path.resolve(__dirname, '../src/mocks/'), + '@pages': path.resolve(__dirname, '../src/pages/'), + '@utils': path.resolve(__dirname, '../src/utils/'), + '@errors': path.resolve(__dirname, '../src/errors/'), + '@HDesign': path.resolve(__dirname, '../src/components/Design/'), + '@HDcomponents': path.resolve(__dirname, '../src/components/Design/components/'), + '@HDutils': path.resolve(__dirname, '../src/components/Design/utils/'), + '@token': path.resolve(__dirname, '../src/components/Design/token/'), + '@theme': path.resolve(__dirname, '../src/components/Design/theme/'), + '@layouts': path.resolve(__dirname, '../src/components/Design/layouts/'), + '@type': path.resolve(__dirname, '../src/components/Design/type/'), + }; + } + + config.module = config.module || {}; + config.module.rules = config.module.rules || []; + + const imageRule = config.module.rules.find(rule => rule?.['test']?.test('.svg')); + if (imageRule) { + imageRule['exclude'] = /\.svg$/; + } + + config.module.rules.push({ + test: /\.svg$/, + use: ['@svgr/webpack'], + }); + return config; + }, +}; +export default config; diff --git a/HDesign/.storybook/preview.tsx b/client/.storybook/preview.tsx similarity index 91% rename from HDesign/.storybook/preview.tsx rename to client/.storybook/preview.tsx index 22008ad03..a3c83803f 100644 --- a/HDesign/.storybook/preview.tsx +++ b/client/.storybook/preview.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import type {Preview} from '@storybook/react'; -import {HDesignProvider} from '../src/theme/HDesignProvider'; +import {HDesignProvider} from '../src/components/Design'; const preview: Preview = { parameters: { diff --git a/client/eslint.config.mjs b/client/eslint.config.mjs index 4ca5abb89..e8355aaed 100644 --- a/client/eslint.config.mjs +++ b/client/eslint.config.mjs @@ -71,6 +71,11 @@ export default [ group: 'internal', position: 'after', }, + { + pattern: '@HDesign/*', + group: 'internal', + position: 'after', + }, { pattern: '@utils/*', group: 'internal', diff --git a/client/jest.config.ts b/client/jest.config.ts index a75677a5a..51f170e38 100644 --- a/client/jest.config.ts +++ b/client/jest.config.ts @@ -6,6 +6,7 @@ const config: Config = { testEnvironment: 'jsdom', // 브라우저 내에서의 JavaScript 동작을 모방하여, DOM 조작, 이벤트 핸들링, 브라우저 관련 API 호출 transform: { '^.+\\.ts?$': 'ts-jest', + '^.+\\.svg$': '<rootDir>/src/mocks/svgMock.ts', }, collectCoverage: true, coverageReporters: ['text'], @@ -30,6 +31,7 @@ const config: Config = { moduleNameMapper: { '@/(.*)$': '<rootDir>/src/$1', // path alias를 적용하기 위함 '^@apis/(.*)$': '<rootDir>/src/apis/$1', + '^@assets/(.*)$': '<rootDir>/src/assets/$1', '^@constants/(.*)$': '<rootDir>/src/constants/$1', '^@components/(.*)$': '<rootDir>/src/components/$1', '^@hooks/(.*)$': '<rootDir>/src/hooks/$1', @@ -39,6 +41,13 @@ const config: Config = { '^@errors/(.*)$': '<rootDir>/src/errors/$1', '^@mocks/(.*)$': '<rootDir>/src/mocks/$1', '^@store/(.*)$': '<rootDir>/src/store/$1', + '^@HDesign/(.*)$': '<rootDir>/src/components/Design/$1', + '^@HDcomponents/(.*)$': '<rootDir>/src/components/Design/components/$1', + '^@HDutils/(.*)$': '<rootDir>/src/components/Design/utils/$1', + '^@token/(.*)$': '<rootDir>/src/components/Design/token/$1', + '^@theme/(.*)$': '<rootDir>/src/components/Design/theme/$1', + '^@layouts/(.*)$': '<rootDir>/src/components/Design/layouts/$1', + '^@type/(.*)$': '<rootDir>/src/components/Design/type/$1', '\\.svg$': '<rootDir>/src/mocks/svg.ts', }, testEnvironmentOptions: { diff --git a/client/package-lock.json b/client/package-lock.json index 6625b0479..553386ba4 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,8 +12,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.82", - "jest-canvas-mock": "^2.5.2", + "lottie-react": "^2.4.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -22,10 +21,20 @@ "zustand": "^4.5.5" }, "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", "@jest/types": "^29.6.3", "@sentry/webpack-plugin": "^2.22.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", + "@storybook/test": "^8.2.2", "@svgr/webpack": "^8.1.0", "@tanstack/react-query-devtools": "^5.52.0", "@testing-library/dom": "^10.4.0", @@ -53,11 +62,15 @@ "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", "jest": "^29.7.0", + "jest-canvas-mock": "^2.5.2", "jest-environment-jsdom": "^29.7.0", + "jest-transform-stub": "^2.0.0", "jsdom": "^24.1.1", "modify-source-webpack-plugin": "^4.1.0", "msw": "^2.3.5", "prettier": "3.3.2", + "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", "ts-jest": "^29.2.4", "ts-loader": "^9.5.1", "ts-node": "^10.9.2", @@ -84,6 +97,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" @@ -108,6 +122,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -116,6 +131,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", @@ -144,7 +160,8 @@ "node_modules/@babel/core/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==" + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true }, "node_modules/@babel/generator": { "version": "7.25.0", @@ -164,6 +181,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -175,6 +193,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -187,6 +206,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-validator-option": "^7.24.8", @@ -202,6 +222,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.0.tgz", "integrity": "sha512-GYM6BxeQsETc9mnct+nIIpf63SAyzvyYN7UB/IlTyd+MBg06afFGp0mIeUqGyWgS2mxad6vqbMrHVlaL3m70sQ==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-member-expression-to-functions": "^7.24.8", @@ -222,6 +243,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "regexpu-core": "^5.3.1", @@ -238,6 +260,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -253,6 +276,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "dev": true, "dependencies": { "@babel/traverse": "^7.24.8", "@babel/types": "^7.24.8" @@ -277,6 +301,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz", "integrity": "sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==", + "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-simple-access": "^7.24.7", @@ -294,6 +319,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "dev": true, "dependencies": { "@babel/types": "^7.24.7" }, @@ -305,6 +331,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -313,6 +340,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-wrap-function": "^7.25.0", @@ -329,6 +357,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz", "integrity": "sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg==", + "dev": true, "dependencies": { "@babel/helper-member-expression-to-functions": "^7.24.8", "@babel/helper-optimise-call-expression": "^7.24.7", @@ -345,6 +374,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -357,6 +387,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "dev": true, "dependencies": { "@babel/traverse": "^7.24.7", "@babel/types": "^7.24.7" @@ -385,6 +416,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -393,6 +425,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "dev": true, "dependencies": { "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.0", @@ -406,6 +439,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", + "dev": true, "dependencies": { "@babel/template": "^7.25.0", "@babel/types": "^7.25.0" @@ -446,6 +480,7 @@ "version": "7.25.3", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.3" @@ -461,6 +496,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -475,6 +511,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -489,6 +526,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -505,6 +543,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/traverse": "^7.25.0" @@ -520,6 +559,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, "engines": { "node": ">=6.9.0" }, @@ -531,6 +571,7 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -554,6 +595,7 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -565,6 +607,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -579,6 +622,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -590,6 +634,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, @@ -597,10 +642,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -615,6 +676,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -629,6 +691,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -640,6 +703,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -651,6 +715,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -665,6 +730,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -676,6 +742,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -687,6 +754,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -698,6 +766,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -709,6 +778,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -720,6 +790,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -731,6 +802,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -745,6 +817,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -759,6 +832,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -773,6 +847,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -788,6 +863,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -802,6 +878,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-remap-async-to-generator": "^7.25.0", @@ -819,6 +896,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -835,6 +913,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -849,6 +928,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -863,6 +943,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -878,6 +959,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -894,6 +976,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.0.tgz", "integrity": "sha512-xyi6qjr/fYU304fiRwFbekzkqVJZ6A7hOjWZd+89FVcBqPV3S9Wuozz82xdpLspckeaafntbzglaW4pqpzvtSw==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-compilation-targets": "^7.24.8", @@ -913,6 +996,7 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, "engines": { "node": ">=4" } @@ -921,6 +1005,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/template": "^7.24.7" @@ -936,6 +1021,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -950,6 +1036,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -965,6 +1052,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -979,6 +1067,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8" @@ -994,6 +1083,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3" @@ -1009,6 +1099,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "dev": true, "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1024,6 +1115,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" @@ -1035,10 +1127,27 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.2.tgz", + "integrity": "sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-flow": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1054,6 +1163,7 @@ "version": "7.25.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -1070,6 +1180,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-json-strings": "^7.8.3" @@ -1085,6 +1196,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1099,6 +1211,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" @@ -1114,6 +1227,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1128,6 +1242,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1143,6 +1258,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.8", "@babel/helper-plugin-utils": "^7.24.8", @@ -1159,6 +1275,7 @@ "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.25.0", "@babel/helper-plugin-utils": "^7.24.8", @@ -1176,6 +1293,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1191,6 +1309,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1206,6 +1325,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1220,6 +1340,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" @@ -1235,6 +1356,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-numeric-separator": "^7.10.4" @@ -1250,6 +1372,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", @@ -1267,6 +1390,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-replace-supers": "^7.24.7" @@ -1282,6 +1406,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" @@ -1297,6 +1422,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", @@ -1313,6 +1439,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1327,6 +1454,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1342,6 +1470,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.24.7", @@ -1359,6 +1488,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1373,6 +1503,7 @@ "version": "7.25.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.1.tgz", "integrity": "sha512-SLV/giH/V4SmloZ6Dt40HjTGTAIkxn33TVIHxNGNvo8ezMhrxBkzisj4op1KZYPIOHFLqhv60OHvX+YRu4xbmQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1387,6 +1518,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1401,6 +1533,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz", "integrity": "sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-module-imports": "^7.24.7", @@ -1419,6 +1552,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "dev": true, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.24.7" }, @@ -1433,6 +1567,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1448,6 +1583,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "regenerator-transform": "^0.15.2" @@ -1463,6 +1599,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1477,6 +1614,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1491,6 +1629,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" @@ -1506,6 +1645,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1520,6 +1660,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1534,6 +1675,7 @@ "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.8" }, @@ -1548,6 +1690,7 @@ "version": "7.25.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.2.tgz", "integrity": "sha512-lBwRvjSmqiMYe/pS0+1gggjJleUJi7NzjvQ1Fkqtt69hBa/0t1YuW/MLQMAPixfwaQOHUXsd6jeU3Z+vdGv3+A==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.24.7", "@babel/helper-create-class-features-plugin": "^7.25.0", @@ -1566,6 +1709,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7" }, @@ -1580,6 +1724,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1595,6 +1740,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1610,6 +1756,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7" @@ -1625,6 +1772,7 @@ "version": "7.25.3", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.25.2", "@babel/helper-compilation-targets": "^7.25.2", @@ -1717,10 +1865,28 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-flow": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.24.7.tgz", + "integrity": "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-flow-strip-types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -1734,6 +1900,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -1753,6 +1920,7 @@ "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", @@ -1767,10 +1935,148 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/register": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.24.6.tgz", + "integrity": "sha512-WSuFCc2wCqMeXkz/i3yfAAsxwWflEgbVkZzivgAmXl/MxrXeoYFZOOPllbC8R8WTF7u61wSRQtDVZ1879cdu6w==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/register/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/register/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/@babel/register/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/@babel/regjsgen": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true }, "node_modules/@babel/runtime": { "version": "7.25.0", @@ -1834,6 +2140,12 @@ "node": ">=6.9.0" } }, + "node_modules/@base2/pretty-print-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", + "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", + "dev": true + }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -1877,22 +2189,66 @@ "tough-cookie": "^4.1.4" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "node_modules/@chromatic-com/storybook": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-1.8.0.tgz", + "integrity": "sha512-vkB9dPVmM2Yvqc/0DJ4MYwOGY1MOjd/KbB9TXTMGN+qshaEyiZtSOgbz9u0ExFALEgDKLmtUnWyUtoGb0pCzUg==", "dev": true, - "optional": true, + "dependencies": { + "chromatic": "^11.4.0", + "filesize": "^10.0.12", + "jsonfile": "^6.1.0", + "react-confetti": "^6.1.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=0.1.90" + "node": ">=16.0.0", + "yarn": ">=1.22.18" } }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { + "node_modules/@chromatic-com/storybook/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@chromatic-com/storybook/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, "engines": { @@ -2084,532 +2440,606 @@ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=12" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=12" } }, - "node_modules/@eslint/compat": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", - "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@eslint/config-array": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", - "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@eslint/object-schema": "^2.1.4", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/@eslint/js": { - "version": "9.8.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", - "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=12" } }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=14" + "node": ">=12" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=12" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=12" } }, - "node_modules/@inquirer/confirm": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", - "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@inquirer/core": "^9.0.10", - "@inquirer/type": "^1.5.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@inquirer/core": { - "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.10.tgz", - "integrity": "sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.2", - "@types/mute-stream": "^0.0.4", - "@types/node": "^22.1.0", - "@types/wrap-ansi": "^3.0.0", - "ansi-escapes": "^4.3.2", - "cli-spinners": "^2.9.2", - "cli-width": "^4.1.0", - "mute-stream": "^1.0.0", - "signal-exit": "^4.1.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=7.0.0" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@inquirer/core/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@inquirer/core/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@inquirer/core/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/@inquirer/figures": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", - "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=18" + "node": ">=12" } }, - "node_modules/@inquirer/type": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.2.tgz", - "integrity": "sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "dependencies": { - "mute-stream": "^1.0.0" + "eslint-visitor-keys": "^3.3.0" }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, "engines": { - "node": ">=12" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/@eslint/compat": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", + "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@eslint/config-array": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.17.1.tgz", + "integrity": "sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@eslint/js": { + "version": "9.8.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.8.0.tgz", + "integrity": "sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=14" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/confirm": { + "version": "3.1.22", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", + "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "@inquirer/core": "^9.0.10", + "@inquirer/type": "^1.5.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@inquirer/core": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.10.tgz", + "integrity": "sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.2", + "@types/mute-stream": "^0.0.4", + "@types/node": "^22.1.0", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=18" } }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/console/node_modules/color-convert": { + "node_modules/@inquirer/core/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -2621,252 +3051,361 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/console/node_modules/color-name": { + "node_modules/@inquirer/core/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + "node": ">=8" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", + "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.2.tgz", + "integrity": "sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA==", + "dev": true, + "dependencies": { + "mute-stream": "^1.0.0" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "engines": { + "node": ">=18" } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jest/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" } }, - "node_modules/@jest/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "p-locate": "^4.1.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "dependencies": { - "jest-get-type": "^29.6.3" + "p-try": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "p-limit": "^2.2.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/@jest/reporters": { + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2880,232 +3419,1643 @@ } } }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/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/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", + "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "dev": true, + "dependencies": { + "@jsonjoy.com/base64": "^1.1.1", + "@jsonjoy.com/util": "^1.1.2", + "hyperdyperid": "^1.2.0", + "thingies": "^1.20.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", + "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "dev": true, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "dev": true, + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", + "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "dev": true, + "dependencies": { + "@open-draft/deferred-promise": "^2.2.0", + "@open-draft/logger": "^0.3.0", + "@open-draft/until": "^2.0.0", + "is-node-process": "^1.2.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "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", + "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "dev": true + }, + "node_modules/@open-draft/logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", + "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "dev": true, + "dependencies": { + "is-node-process": "^1.2.0", + "outvariant": "^1.4.0" + } + }, + "node_modules/@open-draft/until": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", + "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "dev": true + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@remix-run/router": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", + "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sentry-internal/browser-utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", + "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", + "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", + "dependencies": { + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", + "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", + "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", + "dependencies": { + "@sentry-internal/replay": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", + "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", + "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", + "dependencies": { + "@sentry-internal/browser-utils": "8.25.0", + "@sentry-internal/feedback": "8.25.0", + "@sentry-internal/replay": "8.25.0", + "@sentry-internal/replay-canvas": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", + "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "2.22.0", + "@sentry/cli": "^2.33.1", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/cli": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", + "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.33.1", + "@sentry/cli-linux-arm": "2.33.1", + "@sentry/cli-linux-arm64": "2.33.1", + "@sentry/cli-linux-i686": "2.33.1", + "@sentry/cli-linux-x64": "2.33.1", + "@sentry/cli-win32-i686": "2.33.1", + "@sentry/cli-win32-x64": "2.33.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", + "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", + "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", + "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", + "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", + "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux", + "freebsd" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", + "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", + "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", + "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", + "dependencies": { + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/react": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", + "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "dependencies": { + "@sentry/browser": "8.25.0", + "@sentry/core": "8.25.0", + "@sentry/types": "8.25.0", + "@sentry/utils": "8.25.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/types": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", + "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/utils": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", + "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", + "dependencies": { + "@sentry/types": "8.25.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/@sentry/webpack-plugin": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", + "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "dev": true, + "dependencies": { + "@sentry/bundler-plugin-core": "2.22.0", + "unplugin": "1.0.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "webpack": ">=4.40.0" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@storybook/addon-actions": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.2.9.tgz", + "integrity": "sha512-eh2teOqjga7aoClDVV+/b1gHJqsPwjiU1t+Hg/l4i2CkaBUNdYMEL90nR6fgReOdvvL5YhcPwJ8w38f9TrQcoQ==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.2.9.tgz", + "integrity": "sha512-eGmZAd742ORBbQ6JepzBCko/in62T4Xg9j9LVa+Cvz/7L1C/RQSuU6sUwbRAsXaz+PMVDksPDCUUNsXl3zUL7w==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-controls": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.2.9.tgz", + "integrity": "sha512-vaSE78KOE7SO0GrW4e+mdQphSNpvCX/FGybIRxyaKX9h8smoyUwRNHVyCS3ROHTwH324QWu7GDzsOVrnyXOv0A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.2.9.tgz", + "integrity": "sha512-flDOxFIGmXg+6lVdwTLMOKsGob1WrT7rG98mn1SNW0Nxhg3Wg+9pQuq1GLxEzKtAgSflmu+xcBRfYhsogyDXkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.2.9", + "@storybook/csf-plugin": "8.2.9", + "@storybook/global": "^5.0.0", + "@storybook/react-dom-shim": "8.2.9", + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "fs-extra": "^11.1.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-docs/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=14.14" } }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@storybook/addon-essentials": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.2.9.tgz", + "integrity": "sha512-B2d3eznGZvPIyCVtYX0UhrYcEfK+3Y2sACmEWpSwtk8KXomFEsZnD95m397BYDRw3/X6qeSLWxqgMfqDTEDeMA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@storybook/addon-actions": "8.2.9", + "@storybook/addon-backgrounds": "8.2.9", + "@storybook/addon-controls": "8.2.9", + "@storybook/addon-docs": "8.2.9", + "@storybook/addon-highlight": "8.2.9", + "@storybook/addon-measure": "8.2.9", + "@storybook/addon-outline": "8.2.9", + "@storybook/addon-toolbars": "8.2.9", + "@storybook/addon-viewport": "8.2.9", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@storybook/addon-highlight": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.2.9.tgz", + "integrity": "sha512-qdcazeNQoo9QKIq+LJJZZXvFZoLn+i4uhbt1Uf9WtW6oU/c1qxORGVD7jc3zsxbQN9nROVPbJ76sfthogxeqWA==", "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "@storybook/global": "^5.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@jest/reporters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@storybook/addon-interactions": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.2.9.tgz", + "integrity": "sha512-oSxBkqpmp1Vm9v/G8mZeFNXD8k6T1NMgzUWzAx7R5m31rfObhoi5Fo1bKQT5BAhSSsdjjd7owTAFKdhwSotSKg==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.2.9", + "@storybook/test": "8.2.9", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@jest/reporters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/@storybook/addon-links": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-8.2.9.tgz", + "integrity": "sha512-RhJzUNdDb7lbliwXb64HMwieIeJ+OQ2Ditue1vmSox6NsSd+pshR+okHpAyoP1+fW+dahNENwAS2Kt2QiI78FA==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } } }, - "node_modules/@jest/reporters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@storybook/addon-measure": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.2.9.tgz", + "integrity": "sha512-XUfQtYRKWB2dfbPRmHuos816wt1JrLbtRld5ZC8J8ljeqZ4hFBPTQcgI5GAzZqjQuclLC0KuhlA/0bKxdxMMGA==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@jest/reporters/node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "node_modules/@storybook/addon-onboarding": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-onboarding/-/addon-onboarding-8.2.9.tgz", + "integrity": "sha512-9FAWwlnF4JqxOdaZCqe4HeEDj95rqQmITPugPUV3Ra8aJuukPWzlFZgfYubI50TTrnJDAFc8kYeatbxFvoagNQ==", "dev": true, "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "react-confetti": "^6.1.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@jest/reporters/node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/@storybook/addon-outline": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.2.9.tgz", + "integrity": "sha512-p22kI4W7MT0YJOCmg/FfhfH+NpZEDA5tgwstjazSg4ertyhaxziMwWZWiK2JCg0gOAfRJjoYjHz+6/u56iXwgQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" }, - "engines": { - "node": ">=10" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/addon-toolbars": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.2.9.tgz", + "integrity": "sha512-9LMZZ2jRD86Jh6KXedDbAYs4eHj9HtJA9VhSEE2wiqMGwXozpySi7B1GWniNzmFfcgMQ4JHfmD/OrBVTK7Ca/w==", + "dev": true, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@storybook/addon-viewport": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.2.9.tgz", + "integrity": "sha512-lyM24+DJEt8R0YZkJKee34NQWv0REACU6lYDalqJNdKS1sEwzLGWxg1hZXnw2JFdBID9NGVvyYU2w6LDozOB0g==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "memoizerific": "^1.11.3" }, - "engines": { - "node": "*" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@storybook/addon-webpack5-compiler-swc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", + "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@swc/core": "^1.7.3", + "swc-loader": "^0.2.3" }, "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@storybook/blocks": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.2.9.tgz", + "integrity": "sha512-5276q/s/UL8arwftuBXovUNHqYo/HPQFMGXEmjVVAMXUyFjzEAfKj3+xU897J6AuL+7XVZG32WnqA+X6LJMrcQ==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@storybook/csf": "0.1.11", + "@storybook/global": "^5.0.0", + "@storybook/icons": "^1.2.5", + "@types/lodash": "^4.14.167", + "color-convert": "^2.0.1", + "dequal": "^2.0.2", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.4.5", + "memoizerific": "^1.11.3", + "polished": "^4.2.2", + "react-colorful": "^5.1.2", + "telejson": "^7.2.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/@storybook/blocks/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "color-name": "~1.1.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=7.0.0" } }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/@storybook/blocks/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.2.9.tgz", + "integrity": "sha512-D3oYk4LkteWZ3QLcdUTu/0rUvVNUp/bWwEKAycZDr2uFCOhv8VoS2/l/TaHjn3wpyWpVVKS6GgdP72K++YVufg==", + "dev": true, + "dependencies": { + "@storybook/core-webpack": "8.2.9", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "browser-assert": "^1.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "cjs-module-lexer": "^1.2.3", + "constants-browserify": "^1.0.0", + "css-loader": "^6.7.1", + "es-module-lexer": "^1.5.0", + "express": "^4.19.2", + "fork-ts-checker-webpack-plugin": "^8.0.0", + "fs-extra": "^11.1.0", + "html-webpack-plugin": "^5.5.0", + "magic-string": "^0.30.5", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "semver": "^7.3.7", + "style-loader": "^3.3.1", + "terser-webpack-plugin": "^5.3.1", + "ts-dedent": "^2.0.0", + "url": "^0.11.0", + "util": "^0.12.4", + "util-deprecate": "^1.0.2", + "webpack": "5", + "webpack-dev-middleware": "^6.1.2", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.6.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "undici-types": "~5.26.4" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/@storybook/builder-webpack5/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "fast-deep-equal": "^3.1.3" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/@jest/transform/node_modules/ansi-styles": { + "node_modules/@storybook/builder-webpack5/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", @@ -3120,7 +5070,17 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/chalk": { + "node_modules/@storybook/builder-webpack5/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", @@ -3136,7 +5096,7 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@jest/transform/node_modules/color-convert": { + "node_modules/@storybook/builder-webpack5/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", @@ -3148,115 +5108,124 @@ "node": ">=7.0.0" } }, - "node_modules/@jest/transform/node_modules/color-name": { + "node_modules/@storybook/builder-webpack5/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/transform/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/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@storybook/builder-webpack5/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", + "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^7.0.1", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" }, "engines": { - "node": ">=8" + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12" } }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=14.14" } }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@storybook/builder-webpack5/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=8" } }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=7.0.0" + "node": "*" } }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@storybook/builder-webpack5/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, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/@jest/types/node_modules/supports-color": { + "node_modules/@storybook/builder-webpack5/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", @@ -3268,627 +5237,937 @@ "node": ">=8" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@storybook/builder-webpack5/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", + "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", + "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } + "node_modules/@storybook/builder-webpack5/node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "node_modules/@storybook/codemod": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-8.2.9.tgz", + "integrity": "sha512-3yRx1lFMm1FXWVv+CKDiYM4gOQPEfpcZAQrjfcumxSDUrB091pnU1PeI92Prj3vCdi4+0oPNuN4yDGNUYTMP/A==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/core": "8.2.9", + "@storybook/csf": "0.1.11", + "@types/cross-spawn": "^6.0.2", + "cross-spawn": "^7.0.3", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "lodash": "^4.17.21", + "prettier": "^3.1.1", + "recast": "^0.23.5", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@storybook/codemod/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@jsonjoy.com/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "node_modules/@storybook/codemod/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "engines": { - "node": ">=10.0" + "node": ">=12" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/codemod/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/components": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.2.9.tgz", + "integrity": "sha512-OkkcZ/f/6o3GdFEEK9ZHKIGHWUHmavZUYs5xaSgU64bOrA2aqEFtfeWWitZYTv3Euhk8MVLWfyEMDfez0AlvDg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/core": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.2.9.tgz", + "integrity": "sha512-wSER8FpA6Il/jPyDfKm3yohxDtuhisNPTonMVzd3ulNWR4zERLddyO3HrHJJwdqYHLNk4SBFzwMGpQZVws1y0w==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.11", + "@types/express": "^4.17.21", + "@types/node": "^18.0.0", + "browser-assert": "^1.2.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0", + "esbuild-register": "^3.5.0", + "express": "^4.19.2", + "process": "^0.11.10", + "recast": "^0.23.5", + "util": "^0.12.4", + "ws": "^8.2.3" }, - "peerDependencies": { - "tslib": "2" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" } }, - "node_modules/@jsonjoy.com/json-pack": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.0.4.tgz", - "integrity": "sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==", + "node_modules/@storybook/core-webpack": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.2.9.tgz", + "integrity": "sha512-6yL1su+d8IOTU+UkZqM9SeBcVc/G6vUHLsMdlWNyVtRus2JTMmT0K0/ll56jrm/ym0y98cxUOA1jsImkBubP2Q==", "dev": true, "dependencies": { - "@jsonjoy.com/base64": "^1.1.1", - "@jsonjoy.com/util": "^1.1.2", - "hyperdyperid": "^1.2.0", - "thingies": "^1.20.0" - }, - "engines": { - "node": ">=10.0" + "@types/node": "^18.0.0", + "ts-dedent": "^2.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "type": "opencollective", + "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "tslib": "2" + "storybook": "^8.2.9" } }, - "node_modules/@jsonjoy.com/util": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.3.0.tgz", - "integrity": "sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==", + "node_modules/@storybook/core-webpack/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" + "dependencies": { + "undici-types": "~5.26.4" } }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "node_modules/@storybook/core-webpack/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, - "node_modules/@mswjs/interceptors": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.29.1.tgz", - "integrity": "sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==", + "node_modules/@storybook/core/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, "dependencies": { - "@open-draft/deferred-promise": "^2.2.0", - "@open-draft/logger": "^0.3.0", - "@open-draft/until": "^2.0.0", - "is-node-process": "^1.2.0", - "outvariant": "^1.2.1", - "strict-event-emitter": "^0.5.1" - }, - "engines": { - "node": ">=18" + "undici-types": "~5.26.4" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@storybook/core/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/csf": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", + "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" + "type-fest": "^2.19.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@storybook/csf-plugin": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.2.9.tgz", + "integrity": "sha512-QQCFb3g12VQQEraDV1UfCmniGhQZKyT6oEt1Im6dzzPJj9NQk+6BjWoDep33CZhBHWoLryrMQd2fjuHxnFRNEA==", "dev": true, - "engines": { - "node": ">= 8" + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@storybook/csf-plugin/node_modules/unplugin": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.13.1.tgz", + "integrity": "sha512-6Kq1iSSwg7KyjcThRUks9LuqDAKvtnioxbL9iEtB9ctTyBA5OmrB8gZd/d225VJu1w3UpUsKV7eGrvf59J7+VA==", "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "acorn": "^8.12.1", + "webpack-virtual-modules": "^0.6.2" }, "engines": { - "node": ">= 8" + "node": ">=14.0.0" + }, + "peerDependencies": { + "webpack-sources": "^3" + }, + "peerDependenciesMeta": { + "webpack-sources": { + "optional": true + } } }, - "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", - "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==", + "node_modules/@storybook/csf-plugin/node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", "dev": true }, - "node_modules/@open-draft/logger": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz", - "integrity": "sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==", + "node_modules/@storybook/csf/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "dependencies": { - "is-node-process": "^1.2.0", - "outvariant": "^1.4.0" + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@open-draft/until": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz", - "integrity": "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==", + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", "dev": true }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@storybook/icons": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.2.10.tgz", + "integrity": "sha512-310apKdDcjbbX2VSLWPwhEwAgjxTzVagrwucVZIdGPErwiAppX8KvBuWZgPo+rQLVrtH8S+pw1dbUwjcE6d7og==", "dev": true, - "optional": true, "engines": { - "node": ">=14" + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "node_modules/@storybook/instrumenter": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.2.9.tgz", + "integrity": "sha512-+DNjTbsMzlDggsvkhRuOy7aGvQJ4oLCPgunP5Se/3yBjG+M2bYDa0EmC5jC2nwZ3ffpuvbzaVe7fWf7R8W9F2Q==", "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "dependencies": { + "@storybook/global": "^5.0.0", + "@vitest/utils": "^1.3.1", + "util": "^0.12.4" }, "funding": { - "url": "https://opencollective.com/unts" + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@remix-run/router": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", - "integrity": "sha512-zDICCLKEwbVYTS6TjYaWtHXxkdoUvD/QXvyVZjGCsWz5vyH7aFeONlPffPdW+Y/t6KT0MgXb2Mfjun9YpWN1dA==", - "engines": { - "node": ">=14.0.0" + "node_modules/@storybook/manager-api": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.2.9.tgz", + "integrity": "sha512-mkYvUlfqDw+0WbxIynh5TcrotmoXlumEsOA4+45zuNea8XpEgj5cNBUCnmfEO6yQ85swqkS8YYbMpg1cZyu/Vw==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, - "node_modules/@sentry-internal/browser-utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.25.0.tgz", - "integrity": "sha512-nlWgp1lVhNQOTUplW85G3qm0fOIgAhJ/sl/31OIuScVrITYhYDF2bO+Zv/jQ8YsdUBAUXqY1tPT9wwPJklnPhw==", + "node_modules/@storybook/preset-react-webpack": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.2.9.tgz", + "integrity": "sha512-uBLsUfwymWXGmfN/0vB7gLCC0CWDHc778605SWxakqFx7wGF1FZUW4R46qbDFrHTaKh+bundseRdy5/uklksLQ==", + "dev": true, "dependencies": { - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "@storybook/core-webpack": "8.2.9", + "@storybook/react": "8.2.9", + "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", + "@types/node": "^18.0.0", + "@types/semver": "^7.3.4", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "magic-string": "^0.30.5", + "react-docgen": "^7.0.0", + "resolve": "^1.22.8", + "semver": "^7.3.7", + "tsconfig-paths": "^4.2.0", + "webpack": "5" }, "engines": { - "node": ">=14.18" + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@sentry-internal/feedback": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.25.0.tgz", - "integrity": "sha512-327I5XJAFrsgjc5qUKxZ9rff3WNCfGvf1fIii70LQ2YQhQgG4XHZILmkD06ETEyXb+H1tkrNQQEJ1/d4ai+q5g==", + "node_modules/@storybook/preset-react-webpack/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", + "dev": true, "dependencies": { - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=14.18" + "node": ">=14.14" } }, - "node_modules/@sentry-internal/replay": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.25.0.tgz", - "integrity": "sha512-3f7x8EYthyj157uV9V8vBjun+1gJnHhh2+i0qxYLhMGx7N2Fq0J3Bvvo1rosSg+fYh5HzPNZDufwIRdg5C/MQw==", - "dependencies": { - "@sentry-internal/browser-utils": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "node_modules/@storybook/preset-react-webpack/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, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=14.18" + "node": ">=10" } }, - "node_modules/@sentry-internal/replay-canvas": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.25.0.tgz", - "integrity": "sha512-dPXlkAbkFL1DBum8rGTaHS+apJKaXEZJF9gLcBBKTruhTCizrugFLxajzIfVSiFVuwNKuJWa2fzhzbeQM0ee7w==", + "node_modules/@storybook/preset-react-webpack/node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, "dependencies": { - "@sentry-internal/replay": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">=14.18" + "node": ">=6" } }, - "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.0.tgz", - "integrity": "sha512-UzH+NNhgnOo6UFku3C4TEz+pO/yDcIA5FKTJvLbJ7lQwAjsqLs3DZWm4cCA08skICb8mULArF6S/dn5/butVCA==", + "node_modules/@storybook/preset-react-webpack/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/preview-api": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.2.9.tgz", + "integrity": "sha512-D8/t+a78OJqQAcT/ABa1C4YM/OaLGQ9IvCsp3Q9ruUqDCwuZBj8bG3D4477dlY4owX2ycC0rWYu3VvuK0EmJjA==", "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/react": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.2.9.tgz", + "integrity": "sha512-F2xZcTDxxjpbqt7eP8rEHmlksiKmE/qtPusEWEY4N4jK01kN+ncxSl8gkJpUohMEmAnVC5t/1v/sU57xv1DYpg==", + "dev": true, + "dependencies": { + "@storybook/components": "^8.2.9", + "@storybook/global": "^5.0.0", + "@storybook/manager-api": "^8.2.9", + "@storybook/preview-api": "^8.2.9", + "@storybook/react-dom-shim": "8.2.9", + "@storybook/theming": "^8.2.9", + "@types/escodegen": "^0.0.6", + "@types/estree": "^0.0.51", + "@types/node": "^18.0.0", + "acorn": "^7.4.1", + "acorn-jsx": "^5.3.1", + "acorn-walk": "^7.2.0", + "escodegen": "^2.1.0", + "html-tags": "^3.1.0", + "lodash": "^4.17.21", + "prop-types": "^15.7.2", + "react-element-to-jsx-string": "^15.0.0", + "semver": "^7.3.7", + "ts-dedent": "^2.0.0", + "type-fest": "~2.19", + "util-deprecate": "^1.0.2" + }, "engines": { - "node": ">= 14" + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@sentry/browser": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.25.0.tgz", - "integrity": "sha512-51bdVGXjyooqVGzaSGsnExqRTt9NvZ1zGFsxbbCSXi5UoEFN6zdMUz6jKYsL2K80eeELP2VKOVlobHlEzeJQfw==", + "node_modules/@storybook/react-docgen-typescript-plugin": { + "version": "1.0.6--canary.9.0c3f3b7.0", + "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", + "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", + "dev": true, "dependencies": { - "@sentry-internal/browser-utils": "8.25.0", - "@sentry-internal/feedback": "8.25.0", - "@sentry-internal/replay": "8.25.0", - "@sentry-internal/replay-canvas": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "debug": "^4.1.1", + "endent": "^2.0.1", + "find-cache-dir": "^3.3.1", + "flat-cache": "^3.0.4", + "micromatch": "^4.0.2", + "react-docgen-typescript": "^2.2.2", + "tslib": "^2.0.0" }, - "engines": { - "node": ">=14.18" + "peerDependencies": { + "typescript": ">= 4.x", + "webpack": ">= 4" + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@sentry/bundler-plugin-core": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.22.0.tgz", - "integrity": "sha512-/xXN8o7565WMsewBnQFfjm0E5wqhYsegg++HJ5RjrY/cTM4qcd/ven44GEMxqGFJitZizvkk3NHszaHylzcRUw==", + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "@babel/core": "^7.18.5", - "@sentry/babel-plugin-component-annotate": "2.22.0", - "@sentry/cli": "^2.33.1", - "dotenv": "^16.3.1", - "find-up": "^5.0.0", - "glob": "^9.3.2", - "magic-string": "0.30.8", - "unplugin": "1.0.1" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "engines": { - "node": ">= 14" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "*" + } + }, + "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "node_modules/@storybook/react-dom-shim": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.2.9.tgz", + "integrity": "sha512-uCAjSQEsNk8somVn1j/I1G9G/uUax5byHseIIV0Eq3gVXttGd7gaWcP+TDHtqIaenWHx4l+hCSuCesxiLWmx4Q==", "dev": true, - "engines": { - "node": ">=8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9" } }, - "node_modules/@sentry/cli": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.33.1.tgz", - "integrity": "sha512-dUlZ4EFh98VFRPJ+f6OW3JEYQ7VvqGNMa0AMcmvk07ePNeK/GicAWmSQE4ZfJTTl80ul6HZw1kY01fGQOQlVRA==", + "node_modules/@storybook/react-webpack5": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.2.9.tgz", + "integrity": "sha512-c5udaEIFFlBfOQJlPsJvrhyK02B3ltZ86SS0j5bhOa6UgqYOo+KtKaVyegXWgsRw8vVO9ZdmXCfwVvFsHkgJdA==", "dev": true, - "hasInstallScript": true, "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.7", - "progress": "^2.0.3", - "proxy-from-env": "^1.1.0", - "which": "^2.0.2" - }, - "bin": { - "sentry-cli": "bin/sentry-cli" + "@storybook/builder-webpack5": "8.2.9", + "@storybook/preset-react-webpack": "8.2.9", + "@storybook/react": "8.2.9", + "@types/node": "^18.0.0" }, "engines": { - "node": ">= 10" + "node": ">=18.0.0" }, - "optionalDependencies": { - "@sentry/cli-darwin": "2.33.1", - "@sentry/cli-linux-arm": "2.33.1", - "@sentry/cli-linux-arm64": "2.33.1", - "@sentry/cli-linux-i686": "2.33.1", - "@sentry/cli-linux-x64": "2.33.1", - "@sentry/cli-win32-i686": "2.33.1", - "@sentry/cli-win32-x64": "2.33.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.2.9", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/@sentry/cli-darwin": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.33.1.tgz", - "integrity": "sha512-+4/VIx/E1L2hChj5nGf5MHyEPHUNHJ/HoG5RY+B+vyEutGily1c1+DM2bum7RbD0xs6wKLIyup5F02guzSzG8A==", + "node_modules/@storybook/react-webpack5/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" + "dependencies": { + "undici-types": "~5.26.4" } }, - "node_modules/@sentry/cli-linux-arm": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.33.1.tgz", - "integrity": "sha512-zbxEvQju+tgNvzTOt635le4kS/Fbm2XC2RtYbCTs034Vb8xjrAxLnK0z1bQnStUV8BkeBHtsNVrG+NSQDym2wg==", - "cpu": [ - "arm" - ], + "node_modules/@storybook/react-webpack5/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/react/node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@storybook/react/node_modules/@types/node": { + "version": "18.19.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz", + "integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@storybook/react/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">=10" + "node": ">=0.4.0" } }, - "node_modules/@sentry/cli-linux-arm64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.33.1.tgz", - "integrity": "sha512-DbGV56PRKOLsAZJX27Jt2uZ11QfQEMmWB4cIvxkKcFVE+LJP4MVA+MGGRUL6p+Bs1R9ZUuGbpKGtj0JiG6CoXw==", - "cpu": [ - "arm64" - ], + "node_modules/@storybook/react/node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], "engines": { - "node": ">=10" + "node": ">=0.4.0" } }, - "node_modules/@sentry/cli-linux-i686": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.33.1.tgz", - "integrity": "sha512-g2LS4oPXkPWOfKWukKzYp4FnXVRRSwBxhuQ9eSw2peeb58ZIObr4YKGOA/8HJRGkooBJIKGaAR2mH2Pk1TKaiA==", - "cpu": [ - "x86", - "ia32" - ], + "node_modules/@storybook/react/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, - "optional": true, - "os": [ - "linux", - "freebsd" - ], + "bin": { + "semver": "bin/semver.js" + }, "engines": { "node": ">=10" } }, - "node_modules/@sentry/cli-linux-x64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.33.1.tgz", - "integrity": "sha512-IV3dcYV/ZcvO+VGu9U6kuxSdbsV2kzxaBwWUQxtzxJ+cOa7J8Hn1t0koKGtU53JVZNBa06qJWIcqgl4/pCuKIg==", - "cpu": [ - "x64" - ], + "node_modules/@storybook/react/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "optional": true, - "os": [ - "linux", - "freebsd" - ], "engines": { - "node": ">=10" + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@sentry/cli-win32-i686": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.33.1.tgz", - "integrity": "sha512-F7cJySvkpzIu7fnLKNHYwBzZYYwlhoDbAUnaFX0UZCN+5DNp/5LwTp37a5TWOsmCaHMZT4i9IO4SIsnNw16/zQ==", - "cpu": [ - "x86", - "ia32" - ], + "node_modules/@storybook/react/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/@storybook/test": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.2.9.tgz", + "integrity": "sha512-O5JZ5S8UVVR7V0ru5AiF/uRO+srAVwji0Iik7ihy8gw3V91WQNMmJh2KkdhG0R1enYeBsYZlipOm+AW7f/MmOA==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@storybook/csf": "0.1.11", + "@storybook/instrumenter": "8.2.9", + "@testing-library/dom": "10.1.0", + "@testing-library/jest-dom": "6.4.5", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "1.6.0", + "@vitest/spy": "1.6.0", + "util": "^0.12.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" + } + }, + "node_modules/@storybook/test/node_modules/@testing-library/dom": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", + "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/@sentry/cli-win32-x64": { - "version": "2.33.1", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.33.1.tgz", - "integrity": "sha512-8VyRoJqtb2uQ8/bFRKNuACYZt7r+Xx0k2wXRGTyH05lCjAiVIXn7DiS2BxHFty7M1QEWUCMNsb/UC/x/Cu2wuA==", - "cpu": [ - "x64" - ], + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", + "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } } }, - "node_modules/@sentry/core": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.25.0.tgz", - "integrity": "sha512-7KtglbrW1eX4DOHkf6i4rRIExEf2CgtQ99qZ8gn5FUaAmNMg0rK7bb1yZMx0RZtp5G1TSz/S0jQQgxHWebaEig==", + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, "dependencies": { - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14.18" + "node": ">=8" } }, - "node_modules/@sentry/react": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.25.0.tgz", - "integrity": "sha512-A3QeSCJEa+lpo5nh0kxKeqsmnuW2nycKNN/0bpXPv5T5jiEfExSmEBVM0zutrQpf+J0WRIl1AGunUYGPO+GPQg==", + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@storybook/test/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "@sentry/browser": "8.25.0", - "@sentry/core": "8.25.0", - "@sentry/types": "8.25.0", - "@sentry/utils": "8.25.0", - "hoist-non-react-statics": "^3.3.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=14.18" + "node": ">=8" }, - "peerDependencies": { - "react": "^16.14.0 || 17.x || 18.x || 19.x" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@sentry/types": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.25.0.tgz", - "integrity": "sha512-ojim0gDcRhGJPguYrtms4FsprX4xZz3LGNk9Z0hwTbSVEdlhQIInsQ7CYcdM3sjUs+qT7kfpxTRZGUeZNRRJcA==", - "engines": { - "node": ">=14.18" + "node_modules/@storybook/test/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" } }, - "node_modules/@sentry/utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.25.0.tgz", - "integrity": "sha512-mVlkV7S62ZZ2jM38/kOwWx2xoW8fUv2cjw2IwFKoAIPyLBh3mo1WJtvfdtN/rXGjQWZJBKW53EWaWnD00rkjyA==", + "node_modules/@storybook/test/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "@sentry/types": "8.25.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=14.18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@sentry/webpack-plugin": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.22.0.tgz", - "integrity": "sha512-u2brctki0AMCoZksdAConQSYE6PokRVeZ4YYsbnJYkAi0KuaQnczsRwS9e2L0bK2CmZ7QdyYcrjaXHNlXaFDbQ==", + "node_modules/@storybook/test/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "@sentry/bundler-plugin-core": "2.22.0", - "unplugin": "1.0.1", - "uuid": "^9.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "webpack": ">=4.40.0" + "node": ">=7.0.0" } }, - "node_modules/@sentry/webpack-plugin/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "node_modules/@storybook/test/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@storybook/test/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">=8" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "node_modules/@storybook/test/node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/@storybook/test/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@storybook/addon-webpack5-compiler-swc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-swc/-/addon-webpack5-compiler-swc-1.0.5.tgz", - "integrity": "sha512-1NlM3noit2vA22OyWb8Ma2lhcEKCS1Snv2kr+EkaVABUqNDfVc9AD/GgYQhF7F/2CoF5N2JU7uzXDzFHd5TzZg==", + "node_modules/@storybook/test/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/@storybook/test/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "@swc/core": "^1.7.3", - "swc-loader": "^0.2.3" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=8" + } + }, + "node_modules/@storybook/theming": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.2.9.tgz", + "integrity": "sha512-OL0NFvowPX85N5zIYdgeKKaFm7V4Vgtci093vL3cDZT13LGH6GuEzJKkUFGuUGNPFlJc+EgTj0o6PYKrOLyQ6w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.9" } }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, "engines": { "node": ">=14" }, @@ -3904,6 +6183,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, "engines": { "node": ">=14" }, @@ -3919,6 +6199,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, "engines": { "node": ">=14" }, @@ -3934,6 +6215,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, "engines": { "node": ">=14" }, @@ -3949,6 +6231,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, "engines": { "node": ">=14" }, @@ -3964,6 +6247,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, "engines": { "node": ">=14" }, @@ -3979,6 +6263,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, "engines": { "node": ">=14" }, @@ -3994,6 +6279,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, "engines": { "node": ">=12" }, @@ -4009,6 +6295,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, "dependencies": { "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", @@ -4034,6 +6321,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4053,6 +6341,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, "dependencies": { "@babel/types": "^7.21.3", "entities": "^4.4.0" @@ -4069,6 +6358,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4090,6 +6380,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dev": true, "dependencies": { "cosmiconfig": "^8.1.3", "deepmerge": "^4.3.1", @@ -4110,6 +6401,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dev": true, "dependencies": { "@babel/core": "^7.21.3", "@babel/plugin-transform-react-constant-elements": "^7.21.3", @@ -4132,6 +6424,7 @@ "version": "1.7.14", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.14.tgz", "integrity": "sha512-9aeXeifnyuvc2pcuuhPQgVUwdpGEzZ+9nJu0W8/hNl/aESFsJGR5i9uQJRGu0atoNr01gK092fvmqMmQAPcKow==", + "dev": true, "hasInstallScript": true, "dependencies": { "@swc/counter": "^0.1.3", @@ -4172,6 +6465,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -4187,6 +6481,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -4202,6 +6497,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4217,6 +6513,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4232,6 +6529,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4247,6 +6545,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4262,6 +6561,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -4277,6 +6577,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -4292,6 +6593,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -4307,6 +6609,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -4318,12 +6621,14 @@ "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true }, "node_modules/@swc/types": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "dev": true, "dependencies": { "@swc/counter": "^0.1.3" } @@ -4630,6 +6935,19 @@ } } }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -4643,6 +6961,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, "engines": { "node": ">=10.13.0" } @@ -4762,6 +7081,21 @@ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", "dev": true }, + "node_modules/@types/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/@types/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/doctrine": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", + "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", + "dev": true + }, "node_modules/@types/dotenv-webpack": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/dotenv-webpack/-/dotenv-webpack-7.0.7.tgz", @@ -4773,6 +7107,18 @@ "webpack": "^5" } }, + "node_modules/@types/emscripten": { + "version": "1.39.13", + "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", + "integrity": "sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==", + "dev": true + }, + "node_modules/@types/escodegen": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/escodegen/-/escodegen-0.0.6.tgz", + "integrity": "sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==", + "dev": true + }, "node_modules/@types/eslint": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", @@ -4832,6 +7178,15 @@ "@types/node": "*" } }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -4910,6 +7265,18 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", + "dev": true + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "dev": true + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -4994,12 +7361,24 @@ "@types/react": "*" } }, + "node_modules/@types/resolve": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", + "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", + "dev": true + }, "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true + }, "node_modules/@types/send": { "version": "0.17.4", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", @@ -5079,6 +7458,18 @@ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", "dev": true }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@types/wrap-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", @@ -5312,8 +7703,55 @@ "node": "^18.18.0 || >=20.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitest/expect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", + "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "1.6.0", + "@vitest/utils": "1.6.0", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", + "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "dev": true, + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, "node_modules/@webassemblyjs/ast": { @@ -5518,6 +7956,44 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "node_modules/@yarnpkg/fslib": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@yarnpkg/fslib/-/fslib-2.10.3.tgz", + "integrity": "sha512-41H+Ga78xT9sHvWLlFOZLIhtU6mTGZ20pZ29EiZa97vnxdohJD2AF42rCoAoWfqUz486xY6fhjMH+DYEM9r14A==", + "dev": true, + "dependencies": { + "@yarnpkg/libzip": "^2.3.0", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/fslib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@yarnpkg/libzip": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/libzip/-/libzip-2.3.0.tgz", + "integrity": "sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==", + "dev": true, + "dependencies": { + "@types/emscripten": "^1.39.6", + "tslib": "^1.13.0" + }, + "engines": { + "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0" + } + }, + "node_modules/@yarnpkg/libzip/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/abab": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", @@ -5789,7 +8265,8 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/aria-query": { "version": "5.1.3", @@ -5983,6 +8460,27 @@ "node": ">=0.8" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -6067,6 +8565,15 @@ "deep-equal": "^2.0.5" } }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -6238,6 +8745,7 @@ "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.2", @@ -6251,6 +8759,7 @@ "version": "0.10.6", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2", "core-js-compat": "^3.38.0" @@ -6263,6 +8772,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2" }, @@ -6371,6 +8881,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/blob-util": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", @@ -6444,7 +8965,8 @@ "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true }, "node_modules/brace-expansion": { "version": "2.0.1", @@ -6467,10 +8989,17 @@ "node": ">=8" } }, + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, "node_modules/browserslist": { "version": "4.23.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "dev": true, "funding": [ { "type": "opencollective", @@ -6632,6 +9161,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { "node": ">=10" }, @@ -6643,6 +9173,7 @@ "version": "1.0.30001649", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001649.tgz", "integrity": "sha512-fJegqZZ0ZX8HOWr6rcafGr72+xcgJKI9oWfDW5DrD7ExUtgZC7a7R7ZYmZqplh7XDocFdGeIFn7roAxhOeYrPQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -6658,12 +9189,48 @@ } ] }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -6694,6 +9261,18 @@ "node": ">=10" } }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/check-more-types": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", @@ -6739,6 +9318,38 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromatic": { + "version": "11.7.1", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-11.7.1.tgz", + "integrity": "sha512-LvgPimdQdnQB07ZDxLEC2KtxgYeqTw0X71GA7fi3zhgtKLxZcE+BSZ/5I9rrQp1V8ydmfElfw0ZwnUH4fVgUAQ==", + "dev": true, + "bin": { + "chroma": "dist/bin.js", + "chromatic": "dist/bin.js", + "chromatic-cli": "dist/bin.js" + }, + "peerDependencies": { + "@chromatic-com/cypress": "^0.*.* || ^1.0.0", + "@chromatic-com/playwright": "^0.*.* || ^1.0.0" + }, + "peerDependenciesMeta": { + "@chromatic-com/cypress": { + "optional": true + }, + "@chromatic-com/playwright": { + "optional": true + } + } + }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", @@ -6763,6 +9374,15 @@ "node": ">=8" } }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "dependencies": { + "consola": "^3.2.3" + } + }, "node_modules/cjs-module-lexer": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", @@ -6987,6 +9607,15 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -7066,6 +9695,18 @@ "node": ">=4.0.0" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "dev": true + }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -7123,6 +9764,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/confbox": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", + "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", + "dev": true + }, "node_modules/connect-history-api-fallback": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", @@ -7132,6 +9779,21 @@ "node": ">=0.8" } }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -7185,6 +9847,7 @@ "version": "3.38.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.0.tgz", "integrity": "sha512-75LAicdLa4OJVwFxFbQR3NdnZjNgX6ILpVcVzcC4T2smerB5lELMrJQQQoWV6TiuC/vlaFqgU2tKQx9w5s0e0A==", + "dev": true, "dependencies": { "browserslist": "^4.23.3" }, @@ -7203,6 +9866,7 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -7335,6 +9999,80 @@ "node": ">= 8" } }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -7355,6 +10093,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -7367,6 +10106,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, "engines": { "node": ">= 6" }, @@ -7380,15 +10120,29 @@ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", "dev": true }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cssfontparser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/cssfontparser/-/cssfontparser-1.2.1.tgz", - "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==" + "integrity": "sha512-6tun4LoZnj7VN6YeegOVb67KBX/7JJsqvj+pv3ZA7F878/eN33AbGa5b/S/wXxS/tcp8nc40xRUrsPlxIyNUPg==", + "dev": true }, "node_modules/csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, "dependencies": { "css-tree": "~2.2.0" }, @@ -7401,6 +10155,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" @@ -7413,7 +10168,8 @@ "node_modules/csso/node_modules/mdn-data": { "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true }, "node_modules/cssom": { "version": "0.5.0", @@ -7833,6 +10589,18 @@ } } }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-equal": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", @@ -7875,6 +10643,7 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -7919,6 +10688,18 @@ "node": ">= 10" } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -7965,6 +10746,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -8002,6 +10789,15 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -8113,6 +10909,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, "funding": [ { "type": "github", @@ -8175,6 +10972,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -8265,7 +11063,8 @@ "node_modules/electron-to-chromium": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.4.tgz", - "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==" + "integrity": "sha512-orzA81VqLyIGUEA77YkVA1D+N+nNfl2isJVjjmOyrlxuooZ19ynb+dOlaDTqd/idKRS9lDCSBmtzM+kyCsMnkA==", + "dev": true }, "node_modules/emittery": { "version": "0.13.1", @@ -8312,6 +11111,23 @@ "once": "^1.4.0" } }, + "node_modules/endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dev": true, + "dependencies": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, + "node_modules/endent/node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", @@ -8342,6 +11158,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, "engines": { "node": ">=0.12" }, @@ -8549,14 +11366,65 @@ "engines": { "node": ">= 0.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/esbuild-register": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz", + "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" } }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, "engines": { "node": ">=6" } @@ -9165,10 +12033,20 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -9410,6 +12288,12 @@ "node": ">= 6" } }, + "node_modules/fast-json-parse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", + "dev": true + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -9467,6 +12351,15 @@ "bser": "2.1.1" } }, + "node_modules/fd-package-json": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fd-package-json/-/fd-package-json-1.2.0.tgz", + "integrity": "sha512-45LSPmWf+gC5tdCQMNH4s9Sr00bIkiD9aN7dc5hqkrEw1geRYyDQS1v1oMHAW3ysfxfndqGsrDREHHjNNbKUfA==", + "dev": true, + "dependencies": { + "walk-up-path": "^3.0.1" + } + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -9533,6 +12426,15 @@ "node": ">=10" } }, + "node_modules/filesize": { + "version": "10.1.6", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", + "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", + "dev": true, + "engines": { + "node": ">= 10.4.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -9578,6 +12480,38 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "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", @@ -9627,6 +12561,15 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/flow-parser": { + "version": "0.245.2", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.245.2.tgz", + "integrity": "sha512-FU4yuqC1j2IeWWicpzG0YJrXHJgKjK/AU8QKK/7MvQaNhcoGisDoE7FJLGCtbvnifzsgDWdm9/jtTF7Mp+PJXQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", @@ -9871,6 +12814,36 @@ "node": ">=12" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/fs-monkey": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", @@ -9936,6 +12909,7 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -9949,6 +12923,15 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -10036,6 +13019,31 @@ "assert-plus": "^1.0.0" } }, + "node_modules/giget": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz", + "integrity": "sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.3", + "nypm": "^0.3.8", + "ohash": "^1.1.3", + "pathe": "^1.1.2", + "tar": "^6.2.0" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -10170,24 +13178,6 @@ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, - "node_modules/haengdong-design": { - "version": "0.1.82", - "resolved": "https://registry.npmjs.org/haengdong-design/-/haengdong-design-0.1.82.tgz", - "integrity": "sha512-AjVvLle+7N71d8cDkSTHyyYTCuANhlppcBaS3qwv4wTnJJrn68mpWUKQ1Lt2lUt8WMRmZuoF2Bql7t0LHMyodQ==", - "dependencies": { - "@emotion/react": "^11.11.4", - "@storybook/addon-webpack5-compiler-swc": "^1.0.5", - "@svgr/webpack": "^8.1.0", - "lottie-react": "^2.4.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-router-dom": "^6.24.1" - }, - "engines": { - "node": ">=20.15.1", - "npm": ">=10.7.0" - } - }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -10273,6 +13263,45 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-heading-rank": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", + "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.0.tgz", + "integrity": "sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -10419,6 +13448,18 @@ "node": "^14.13.1 || >=16.0.0" } }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/html-webpack-plugin": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", @@ -10657,6 +13698,18 @@ "node": ">=0.10.0" } }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -10796,6 +13849,18 @@ "node": ">= 10" } }, + "node_modules/is-absolute-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", + "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -11071,6 +14136,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", @@ -11652,6 +14726,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jest-canvas-mock/-/jest-canvas-mock-2.5.2.tgz", "integrity": "sha512-vgnpPupjOL6+L5oJXzxTxFrlGEIbHdZqFU+LFNdtLxZ3lRDCl17FlTMM7IatoRQkrcyOTMlDinjUguqmQ6bR2A==", + "dev": true, "dependencies": { "cssfontparser": "^1.2.1", "moo-color": "^1.0.2" @@ -13288,6 +16363,12 @@ "node": ">=8" } }, + "node_modules/jest-transform-stub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jest-transform-stub/-/jest-transform-stub-2.0.0.tgz", + "integrity": "sha512-lspHaCRx/mBbnm3h4uMMS3R5aZzMwyNpNIJLXj4cEsV0mIUtS4IjYJLSoyjRCtnxb6RIGJ4NL2quZzfIeNhbkg==", + "dev": true + }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -13557,15 +16638,150 @@ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "node_modules/jscodeshift": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.2.tgz", + "integrity": "sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.23.0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", + "@babel/plugin-transform-optional-chaining": "^7.23.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/preset-flow": "^7.22.15", + "@babel/preset-typescript": "^7.23.0", + "@babel/register": "^7.22.15", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.23.3", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + }, + "peerDependenciesMeta": { + "@babel/preset-env": { + "optional": true + } + } + }, + "node_modules/jscodeshift/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jscodeshift/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jscodeshift/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" }, "engines": { - "node": ">= 10.13.0" + "node": ">=7.0.0" } }, - "node_modules/jest-worker/node_modules/has-flag": { + "node_modules/jscodeshift/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jscodeshift/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", @@ -13574,43 +16790,29 @@ "node": ">=8" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/jscodeshift/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=8" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/jscodeshift/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, "node_modules/jsdom": { "version": "24.1.1", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.1.tgz", @@ -13774,6 +16976,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -14059,7 +17262,8 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true }, "node_modules/lodash.memoize": { "version": "4.1.2", @@ -14295,10 +17499,20 @@ "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -14307,6 +17521,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "dependencies": { "yallist": "^3.0.2" } @@ -14374,10 +17589,29 @@ "tmpl": "1.0.5" } }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true + }, + "node_modules/markdown-to-jsx": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.5.0.tgz", + "integrity": "sha512-RrBNcMHiFPcz/iqIj0n3wclzHXjwS7mzjBNWecKKVhNTIxQepIix6Il/wZCn2Cg5Y1ow2Qi84+eJrryFRWBEWw==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true }, "node_modules/media-typer": { "version": "0.3.0", @@ -14400,6 +17634,15 @@ "node": ">= 4.0.0" } }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -14533,6 +17776,61 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mlly": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", + "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", + "dev": true, + "dependencies": { + "acorn": "^8.11.3", + "pathe": "^1.1.2", + "pkg-types": "^1.1.1", + "ufo": "^1.5.3" + } + }, "node_modules/modify-source-webpack-plugin": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/modify-source-webpack-plugin/-/modify-source-webpack-plugin-4.1.0.tgz", @@ -14603,6 +17901,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/moo-color/-/moo-color-1.0.3.tgz", "integrity": "sha512-i/+ZKXMDf6aqYtBhuOcej71YSlbjT3wCO/4H1j8rPvxDJEifdwgg5MaFyu6iYAT8GBZJg2z0dkgK4YMzvURALQ==", + "dev": true, "dependencies": { "color-name": "^1.1.4" } @@ -14610,7 +17909,8 @@ "node_modules/moo-color/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/ms": { "version": "2.1.2", @@ -14758,6 +18058,24 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -14783,6 +18101,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -14794,6 +18113,40 @@ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-dir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-dir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -14814,6 +18167,12 @@ } } }, + "node_modules/node-fetch-native": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.4.tgz", + "integrity": "sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==", + "dev": true + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -14832,7 +18191,8 @@ "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true }, "node_modules/normalize-path": { "version": "3.0.0", @@ -14852,26 +18212,181 @@ "path-key": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.12", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", + "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", + "dev": true + }, + "node_modules/nypm": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.3.11.tgz", + "integrity": "sha512-E5GqaAYSnbb6n1qZyik2wjPDZON43FqOJO59+3OkWrnmQtjggrMOVnsyzfjxp/tS6nlYJBA4zRA5jSM2YaadMg==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.2.3", + "execa": "^8.0.1", + "pathe": "^1.1.2", + "pkg-types": "^1.2.0", + "ufo": "^1.5.4" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/nypm/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/nypm/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/nypm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nypm/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" + "node_modules/nypm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" }, "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nwsapi": { - "version": "2.2.12", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", - "integrity": "sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w==", - "dev": true - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -14998,12 +18513,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/objectorarray": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", + "dev": true + }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "node_modules/ohash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.3.tgz", + "integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==", + "dev": true + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -15084,6 +18611,99 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ospath": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", @@ -15242,6 +18862,12 @@ "tslib": "^2.0.3" } }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -15310,6 +18936,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -15421,6 +19062,29 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.0.tgz", + "integrity": "sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==", + "dev": true, + "dependencies": { + "confbox": "^0.1.7", + "mlly": "^1.7.1", + "pathe": "^1.1.2" + } + }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, "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", @@ -15430,6 +19094,112 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.4.45", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", + "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -15695,51 +19465,133 @@ "node": ">= 0.6" } }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-colorful": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", + "integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-confetti": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/react-confetti/-/react-confetti-6.1.0.tgz", + "integrity": "sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==", + "dev": true, + "dependencies": { + "tween-functions": "^1.2.0" + }, + "engines": { + "node": ">=10.18" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-copy-to-clipboard": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", + "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "dependencies": { + "copy-to-clipboard": "^3.3.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": "^15.3.0 || 16 || 17 || 18" + } + }, + "node_modules/react-docgen": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.0.3.tgz", + "integrity": "sha512-i8aF1nyKInZnANZ4uZrH49qn1paRgBZ7wZiCNBMnenlPzEv0mRl+ShpTVEI6wZNl8sSc79xZkivtgLKQArcanQ==", "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "@babel/core": "^7.18.9", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9", + "@types/babel__core": "^7.18.0", + "@types/babel__traverse": "^7.18.0", + "@types/doctrine": "^0.0.9", + "@types/resolve": "^1.20.2", + "doctrine": "^3.0.0", + "resolve": "^1.22.1", + "strip-indent": "^4.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=16.14.0" } }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/react-docgen-typescript": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", + "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", "dev": true, - "engines": { - "node": ">= 0.8" + "peerDependencies": { + "typescript": ">= 4.3.x" } }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "node_modules/react-docgen/node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "dependencies": { - "loose-envify": "^1.1.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/react-copy-to-clipboard": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz", - "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==", + "node_modules/react-docgen/node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, "dependencies": { - "copy-to-clipboard": "^3.3.1", - "prop-types": "^15.8.1" + "min-indent": "^1.0.1" }, - "peerDependencies": { - "react": "^15.3.0 || 16 || 17 || 18" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/react-dom": { @@ -15754,6 +19606,36 @@ "react": "^18.3.1" } }, + "node_modules/react-element-to-jsx-string": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", + "integrity": "sha512-UDg4lXB6BzlobN60P8fHWVPX3Kyw8ORrTeBtClmIlGdkOOE+GYQSFvmEU5iLLpwp/6v42DINwNcwOhOLfQ//FQ==", + "dev": true, + "dependencies": { + "@base2/pretty-print-object": "1.0.1", + "is-plain-object": "5.0.0", + "react-is": "18.1.0" + }, + "peerDependencies": { + "react": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0", + "react-dom": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/react-is": { + "version": "18.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.1.0.tgz", + "integrity": "sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==", + "dev": true + }, "node_modules/react-error-boundary": { "version": "4.0.13", "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.0.13.tgz", @@ -15765,6 +19647,15 @@ "react": ">=16.13.1" } }, + "node_modules/react-inspector": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.2.tgz", + "integrity": "sha512-x+b7LxhmHXjHoU/VrFAzw5iutsILRoYyDq97EDYdFpPLcvqtEzk4ZSZSQjnFPbr5T57tLXnHcqFYoN1pI6u8uQ==", + "dev": true, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -15826,6 +19717,31 @@ "node": ">=8.10.0" } }, + "node_modules/recast": { + "version": "0.23.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.9.tgz", + "integrity": "sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==", + "dev": true, + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/recast/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -15875,12 +19791,14 @@ "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true }, "node_modules/regenerate-unicode-properties": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -15897,6 +19815,7 @@ "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" } @@ -15923,6 +19842,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, "dependencies": { "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", @@ -15939,6 +19859,7 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, "dependencies": { "jsesc": "~0.5.0" }, @@ -15950,10 +19871,46 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, "bin": { "jsesc": "bin/jsesc" } }, + "node_modules/rehype-external-links": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", + "integrity": "sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-is-element": "^3.0.0", + "is-absolute-url": "^4.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", + "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -16297,6 +20254,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -16618,6 +20576,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -16646,6 +20605,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -16669,6 +20629,16 @@ "node": ">=0.10.0" } }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/spdy": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", @@ -16760,16 +20730,241 @@ "node": ">= 0.8" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/storybook": { + "version": "8.2.9", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.2.9.tgz", + "integrity": "sha512-S7Q/Yt4A+nu1O23rg39lQvBqL2Vg+PKXbserDWUR4LFJtfmoZ2xGO8oFIhJmvvhjUBvolw1q7QDeswPq2i0sGw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/types": "^7.24.0", + "@storybook/codemod": "8.2.9", + "@storybook/core": "8.2.9", + "@types/semver": "^7.3.4", + "@yarnpkg/fslib": "2.10.3", + "@yarnpkg/libzip": "2.3.0", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "cross-spawn": "^7.0.3", + "detect-indent": "^6.1.0", + "envinfo": "^7.7.3", + "execa": "^5.0.0", + "fd-package-json": "^1.2.0", + "find-up": "^5.0.0", + "fs-extra": "^11.1.0", + "giget": "^1.0.0", + "globby": "^14.0.1", + "jscodeshift": "^0.15.1", + "leven": "^3.1.0", + "ora": "^5.4.1", + "prettier": "^3.1.1", + "prompts": "^2.4.0", + "semver": "^7.3.7", + "strip-json-comments": "^3.0.1", + "tempy": "^3.1.0", + "tiny-invariant": "^1.3.1", + "ts-dedent": "^2.0.0" + }, + "bin": { + "getstorybook": "bin/index.cjs", + "sb": "bin/index.cjs", + "storybook": "bin/index.cjs" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/storybook-addon-react-router-v6": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/storybook-addon-react-router-v6/-/storybook-addon-react-router-v6-2.0.15.tgz", + "integrity": "sha512-4vOYIQwehlQLyXaCT9K0Iu0po2Z+pANGsqkfm/BQuAEjE9MoN7vrsrQLHINhKbmQVtNMmuS/oBR3GGNbqQ1gew==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "compare-versions": "^6.0.0", + "react-inspector": "6.0.2" + }, + "peerDependencies": { + "@storybook/blocks": "^7.0.0", + "@storybook/channels": "^7.0.0", + "@storybook/components": "^7.0.0", + "@storybook/core-events": "^7.0.0", + "@storybook/manager-api": "^7.0.0", + "@storybook/preview-api": "^7.0.0", + "@storybook/theming": "^7.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-router-dom": "^6.4.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/storybook/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/storybook/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/storybook/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/storybook/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/storybook/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/storybook/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/storybook/node_modules/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/storybook/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/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, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/storybook/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/storybook/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "internal-slot": "^1.0.4" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, "node_modules/strict-event-emitter": { @@ -17027,6 +21222,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-loader": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -17057,12 +21268,14 @@ "node_modules/svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true }, "node_modules/svgo": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", @@ -17087,6 +21300,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, "engines": { "node": ">= 10" } @@ -17095,6 +21309,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", @@ -17110,6 +21325,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", @@ -17123,6 +21339,7 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, "dependencies": { "domelementtype": "^2.3.0" }, @@ -17137,6 +21354,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", @@ -17150,6 +21368,7 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.6.tgz", "integrity": "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==", + "dev": true, "dependencies": { "@swc/counter": "^0.1.3" }, @@ -17189,6 +21408,166 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/telejson": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.2.0.tgz", + "integrity": "sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==", + "dev": true, + "dependencies": { + "memoizerific": "^1.11.3" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/temp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/temp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/temp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/terser": { "version": "5.31.3", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", @@ -17343,6 +21722,21 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -17450,6 +21844,15 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "engines": { + "node": ">=6.10" + } + }, "node_modules/ts-jest": { "version": "29.2.4", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", @@ -17691,7 +22094,8 @@ "node_modules/tslib": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -17705,6 +22109,12 @@ "node": "*" } }, + "node_modules/tween-functions": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tween-functions/-/tween-functions-1.2.0.tgz", + "integrity": "sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==", + "dev": true + }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -17869,6 +22279,12 @@ } } }, + "node_modules/ufo": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", + "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -17906,6 +22322,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, "engines": { "node": ">=4" } @@ -17914,6 +22331,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -17926,6 +22344,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, "engines": { "node": ">=4" } @@ -17934,10 +22353,80 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, "engines": { "node": ">=4" } }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -17981,6 +22470,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -18015,6 +22505,19 @@ "punycode": "^2.1.0" } }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -18025,6 +22528,27 @@ "requires-port": "^1.0.0" } }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/url/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", @@ -18033,6 +22557,19 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -18130,6 +22667,12 @@ "node": ">=18" } }, + "node_modules/walk-up-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-3.0.1.tgz", + "integrity": "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA==", + "dev": true + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -18161,6 +22704,15 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -18486,6 +23038,17 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/webpack-hot-middleware": { + "version": "2.26.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", + "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", + "dev": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "strip-ansi": "^6.0.0" + } + }, "node_modules/webpack-merge": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", @@ -18906,7 +23469,8 @@ "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yaml": { "version": "1.10.2", diff --git a/client/package.json b/client/package.json index bd117af40..d4d501217 100644 --- a/client/package.json +++ b/client/package.json @@ -8,6 +8,8 @@ "dev": "NODE_ENV=development webpack server --open --config webpack.dev.mjs", "build": "NODE_ENV=production webpack --config webpack.prod.mjs", "build-dev": "NODE_ENV=development webpack --config webpack.dev.mjs", + "build-storybook": "storybook build", + "storybook": "storybook dev -p 6006", "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\"", "format": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", "cypress-open": "cypress open", @@ -18,10 +20,20 @@ "author": "", "license": "ISC", "devDependencies": { + "@chromatic-com/storybook": "^1.6.1", "@eslint/compat": "^1.1.0", "@eslint/js": "^9.6.0", "@jest/types": "^29.6.3", "@sentry/webpack-plugin": "^2.22.0", + "@storybook/addon-essentials": "^8.2.2", + "@storybook/addon-interactions": "^8.2.2", + "@storybook/addon-links": "^8.2.2", + "@storybook/addon-onboarding": "^8.2.2", + "@storybook/addon-webpack5-compiler-swc": "^1.0.5", + "@storybook/blocks": "^8.2.2", + "@storybook/react": "^8.2.2", + "@storybook/react-webpack5": "^8.2.3", + "@storybook/test": "^8.2.2", "@svgr/webpack": "^8.1.0", "@tanstack/react-query-devtools": "^5.52.0", "@testing-library/dom": "^10.4.0", @@ -49,11 +61,15 @@ "html-loader": "^5.0.0", "html-webpack-plugin": "^5.6.0", "jest": "^29.7.0", + "jest-canvas-mock": "^2.5.2", "jest-environment-jsdom": "^29.7.0", + "jest-transform-stub": "^2.0.0", "jsdom": "^24.1.1", "modify-source-webpack-plugin": "^4.1.0", "msw": "^2.3.5", "prettier": "3.3.2", + "storybook": "^8.2.2", + "storybook-addon-react-router-v6": "^2.0.15", "ts-jest": "^29.2.4", "ts-loader": "^9.5.1", "ts-node": "^10.9.2", @@ -69,8 +85,7 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "haengdong-design": "^0.1.82", - "jest-canvas-mock": "^2.5.2", + "lottie-react": "^2.4.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/App.tsx b/client/src/App.tsx index 4e9ce39e1..c3815ad2a 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,5 +1,4 @@ import {Outlet} from 'react-router-dom'; -import {HDesignProvider} from 'haengdong-design'; import {Global} from '@emotion/react'; import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; @@ -7,6 +6,8 @@ import {ToastProvider} from '@hooks/useToast/ToastProvider'; import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; import ErrorCatcher from '@components/AppErrorBoundary/ErrorCatcher'; +import {HDesignProvider} from '@HDesign/index'; + import {GlobalStyle} from './GlobalStyle'; import UnhandledErrorBoundary from './UnhandledErrorBoundary'; diff --git a/client/src/UnhandledErrorBoundary.tsx b/client/src/UnhandledErrorBoundary.tsx index 78d017344..3e1f4378f 100644 --- a/client/src/UnhandledErrorBoundary.tsx +++ b/client/src/UnhandledErrorBoundary.tsx @@ -1,6 +1,6 @@ -import {StrictPropsWithChildren} from 'haengdong-design/dist/type/strictPropsWithChildren'; import {ErrorBoundary} from 'react-error-boundary'; +import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; const UnhandledErrorBoundary = ({children}: StrictPropsWithChildren) => { diff --git a/HDesign/src/assets/buljusa.svg b/client/src/assets/image/buljusa.svg similarity index 100% rename from HDesign/src/assets/buljusa.svg rename to client/src/assets/image/buljusa.svg diff --git a/HDesign/src/assets/confirm.svg b/client/src/assets/image/confirm.svg similarity index 100% rename from HDesign/src/assets/confirm.svg rename to client/src/assets/image/confirm.svg diff --git a/HDesign/src/assets/error.svg b/client/src/assets/image/error.svg similarity index 100% rename from HDesign/src/assets/error.svg rename to client/src/assets/image/error.svg diff --git a/HDesign/src/assets/inputDelete.svg b/client/src/assets/image/inputDelete.svg similarity index 100% rename from HDesign/src/assets/inputDelete.svg rename to client/src/assets/image/inputDelete.svg diff --git a/HDesign/src/assets/loadingAnimation.json b/client/src/assets/image/loadingAnimation.json similarity index 100% rename from HDesign/src/assets/loadingAnimation.json rename to client/src/assets/image/loadingAnimation.json diff --git a/HDesign/src/assets/rightChevron.svg b/client/src/assets/image/rightChevron.svg similarity index 100% rename from HDesign/src/assets/rightChevron.svg rename to client/src/assets/image/rightChevron.svg diff --git a/HDesign/src/assets/search.svg b/client/src/assets/image/search.svg similarity index 100% rename from HDesign/src/assets/search.svg rename to client/src/assets/image/search.svg diff --git a/HDesign/src/assets/trash.svg b/client/src/assets/image/trash.svg similarity index 100% rename from HDesign/src/assets/trash.svg rename to client/src/assets/image/trash.svg diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx index 8d7946b8a..9a802df14 100644 --- a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx @@ -1,13 +1,14 @@ import {render, screen, waitFor} from '@testing-library/react'; import {act, ReactNode} from 'react'; import {MemoryRouter} from 'react-router-dom'; -import {HDesignProvider} from 'haengdong-design'; import FetchError from '@errors/FetchError'; import {ToastProvider} from '@hooks/useToast/ToastProvider'; import {useAppErrorStore} from '@store/appErrorStore'; +import {HDesignProvider} from '@HDesign/index'; + import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; diff --git a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx b/client/src/components/Design/components/BottomSheet/BottomSheet.stories.tsx similarity index 86% rename from HDesign/src/components/BottomSheet/BottomSheet.stories.tsx rename to client/src/components/Design/components/BottomSheet/BottomSheet.stories.tsx index 67d4cdb37..107f96c1f 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.stories.tsx +++ b/client/src/components/Design/components/BottomSheet/BottomSheet.stories.tsx @@ -3,8 +3,8 @@ import type {Meta, StoryObj} from '@storybook/react'; import {useState} from 'react'; -import Button from '@components/Button/Button'; -import BottomSheet from '@components/BottomSheet/BottomSheet'; +import Button from '@HDcomponents/Button/Button'; +import BottomSheet from '@HDcomponents/BottomSheet/BottomSheet'; const meta = { title: 'Components/BottomSheet', diff --git a/HDesign/src/components/BottomSheet/BottomSheet.style.ts b/client/src/components/Design/components/BottomSheet/BottomSheet.style.ts similarity index 100% rename from HDesign/src/components/BottomSheet/BottomSheet.style.ts rename to client/src/components/Design/components/BottomSheet/BottomSheet.style.ts diff --git a/HDesign/src/components/BottomSheet/BottomSheet.tsx b/client/src/components/Design/components/BottomSheet/BottomSheet.tsx similarity index 94% rename from HDesign/src/components/BottomSheet/BottomSheet.tsx rename to client/src/components/Design/components/BottomSheet/BottomSheet.tsx index 3ffadc323..48d388625 100644 --- a/HDesign/src/components/BottomSheet/BottomSheet.tsx +++ b/client/src/components/Design/components/BottomSheet/BottomSheet.tsx @@ -1,11 +1,10 @@ /** @jsxImportSource @emotion/react */ import {createPortal} from 'react-dom'; -import {BottomSheetProps} from '@components/BottomSheet/BottomSheet.type'; - import {useTheme} from '@theme/HDesignProvider'; import {useBottomSheet} from './useBottomSheet'; +import {BottomSheetProps} from './BottomSheet.type'; import { bottomSheetContainerStyle, dimmedLayerStyle, diff --git a/HDesign/src/components/BottomSheet/BottomSheet.type.ts b/client/src/components/Design/components/BottomSheet/BottomSheet.type.ts similarity index 100% rename from HDesign/src/components/BottomSheet/BottomSheet.type.ts rename to client/src/components/Design/components/BottomSheet/BottomSheet.type.ts diff --git a/HDesign/src/components/BottomSheet/useBottomSheet.ts b/client/src/components/Design/components/BottomSheet/useBottomSheet.ts similarity index 99% rename from HDesign/src/components/BottomSheet/useBottomSheet.ts rename to client/src/components/Design/components/BottomSheet/useBottomSheet.ts index 3e2564550..e9a901c14 100644 --- a/HDesign/src/components/BottomSheet/useBottomSheet.ts +++ b/client/src/components/Design/components/BottomSheet/useBottomSheet.ts @@ -22,6 +22,8 @@ export const useBottomSheet = ({isOpened, onClose, onOpen}: UseBottomSheetProps) return () => clearTimeout(timer); } + + return; }, [opened]); useEffect(() => { diff --git a/HDesign/src/components/Button/Button.stories.tsx b/client/src/components/Design/components/Button/Button.stories.tsx similarity index 100% rename from HDesign/src/components/Button/Button.stories.tsx rename to client/src/components/Design/components/Button/Button.stories.tsx diff --git a/HDesign/src/components/Button/Button.style.ts b/client/src/components/Design/components/Button/Button.style.ts similarity index 95% rename from HDesign/src/components/Button/Button.style.ts rename to client/src/components/Design/components/Button/Button.style.ts index 24c46ec5b..7b76cf789 100644 --- a/HDesign/src/components/Button/Button.style.ts +++ b/client/src/components/Design/components/Button/Button.style.ts @@ -1,8 +1,7 @@ import {css} from '@emotion/react'; -import {setDarker, setEmphasize, setLighter} from '@utils/colors'; - -import {Theme} from '../../theme/theme.type'; +import {setDarker, setEmphasize, setLighter} from '@HDutils/colors'; +import {Theme} from '@theme/theme.type'; import {ButtonStyleProps, ButtonSize, ButtonVariants} from './Button.type'; diff --git a/HDesign/src/components/Button/Button.tsx b/client/src/components/Design/components/Button/Button.tsx similarity index 83% rename from HDesign/src/components/Button/Button.tsx rename to client/src/components/Design/components/Button/Button.tsx index f0277590b..3b8896a1c 100644 --- a/HDesign/src/components/Button/Button.tsx +++ b/client/src/components/Design/components/Button/Button.tsx @@ -3,13 +3,12 @@ import React, {forwardRef} from 'react'; import Lottie from 'lottie-react'; -import {buttonStyle} from '@components/Button/Button.style'; -import {ButtonProps, ButtonSize} from '@components/Button/Button.type'; - -import loadingAnimation from '@assets/loadingAnimation.json'; - +import loadingAnimation from '@assets/image/loadingAnimation.json'; import {useTheme} from '@theme/HDesignProvider'; +import {ButtonProps, ButtonSize} from './Button.type'; +import {buttonStyle} from './Button.style'; + const animationSize = (size: ButtonSize) => { switch (size) { case 'small': diff --git a/HDesign/src/components/Button/Button.type.ts b/client/src/components/Design/components/Button/Button.type.ts similarity index 100% rename from HDesign/src/components/Button/Button.type.ts rename to client/src/components/Design/components/Button/Button.type.ts diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx b/client/src/components/Design/components/DragHandleItem/DragHandleItem.stories.tsx similarity index 94% rename from HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx rename to client/src/components/Design/components/DragHandleItem/DragHandleItem.stories.tsx index c7125d4d8..8043777b5 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.stories.tsx +++ b/client/src/components/Design/components/DragHandleItem/DragHandleItem.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import DragHandleItem from '@HDcomponents/DragHandleItem/DragHandleItem'; const meta = { title: 'Components/DragHandleItem', diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts b/client/src/components/Design/components/DragHandleItem/DragHandleItem.style.ts similarity index 99% rename from HDesign/src/components/DragHandleItem/DragHandleItem.style.ts rename to client/src/components/Design/components/DragHandleItem/DragHandleItem.style.ts index b641c5fb3..7136e7b3c 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.style.ts +++ b/client/src/components/Design/components/DragHandleItem/DragHandleItem.style.ts @@ -1,7 +1,6 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export const dragHandleItemStyle = (theme: Theme, hasDragHandle: boolean, backgroundColor: ColorKeys) => diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx b/client/src/components/Design/components/DragHandleItem/DragHandleItem.tsx similarity index 85% rename from HDesign/src/components/DragHandleItem/DragHandleItem.tsx rename to client/src/components/Design/components/DragHandleItem/DragHandleItem.tsx index 9acf38084..4cca73a4f 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.tsx +++ b/client/src/components/Design/components/DragHandleItem/DragHandleItem.tsx @@ -1,9 +1,8 @@ /** @jsxImportSource @emotion/react */ -import Icon from '@components/Icon/Icon'; -import Flex from '@components/Flex/Flex'; -import Text from '@components/Text/Text'; -import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; - +import Icon from '@HDcomponents/Icon/Icon'; +import Flex from '@HDcomponents/Flex/Flex'; +import Text from '@HDcomponents/Text/Text'; +import IsFixedIcon from '@HDcomponents/IsFixedIcon/IsFixedIcon'; import {useTheme} from '@theme/HDesignProvider'; import IconButton from '../IconButton/IconButton'; diff --git a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts b/client/src/components/Design/components/DragHandleItem/DragHandleItem.type.ts similarity index 99% rename from HDesign/src/components/DragHandleItem/DragHandleItem.type.ts rename to client/src/components/Design/components/DragHandleItem/DragHandleItem.type.ts index fc0a1f520..8b62dd374 100644 --- a/HDesign/src/components/DragHandleItem/DragHandleItem.type.ts +++ b/client/src/components/Design/components/DragHandleItem/DragHandleItem.type.ts @@ -1,5 +1,4 @@ import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export interface DragHandleItemStyleProps { diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx similarity index 92% rename from HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx rename to client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx index 46c3db8a2..1e215ca9d 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx +++ b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.stories.tsx @@ -1,8 +1,8 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; -import DragHandleItemContainer from '@components/DragHandleItemContainer/DragHandleItemContainer'; -import DragHandleItem from '@components/DragHandleItem/DragHandleItem'; +import DragHandleItemContainer from '@HDcomponents/DragHandleItemContainer/DragHandleItemContainer'; +import DragHandleItem from '@HDcomponents/DragHandleItem/DragHandleItem'; const meta = { title: 'Components/DragHandleItemContainer', diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.style.ts similarity index 99% rename from HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts rename to client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.style.ts index b5bab9422..db2ada615 100644 --- a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.style.ts +++ b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.style.ts @@ -1,7 +1,6 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export const containerStyle = (theme: Theme, backgroundColor: ColorKeys) => diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.tsx similarity index 100% rename from HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.tsx rename to client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.tsx diff --git a/HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts b/client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.type.ts similarity index 100% rename from HDesign/src/components/DragHandleItemContainer/DragHandleItemContainer.type.ts rename to client/src/components/Design/components/DragHandleItemContainer/DragHandleItemContainer.type.ts diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts b/client/src/components/Design/components/EditableItem/EditableItem.Input.style.ts similarity index 97% rename from HDesign/src/components/EditableItem/EditableItem.Input.style.ts rename to client/src/components/Design/components/EditableItem/EditableItem.Input.style.ts index eadff482e..eeefb44ca 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.style.ts +++ b/client/src/components/Design/components/EditableItem/EditableItem.Input.style.ts @@ -1,8 +1,7 @@ import {css} from '@emotion/react'; -import {TextSize} from '@components/Text/Text.type'; +import {TextSize} from '@HDcomponents/Text/Text.type'; import {WithTheme} from '@type/withTheme'; - import TYPOGRAPHY from '@token/typography'; type UnderlineProps = { diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.tsx b/client/src/components/Design/components/EditableItem/EditableItem.Input.tsx similarity index 91% rename from HDesign/src/components/EditableItem/EditableItem.Input.tsx rename to client/src/components/Design/components/EditableItem/EditableItem.Input.tsx index 87dd187e6..bc7d6ca6a 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.tsx +++ b/client/src/components/Design/components/EditableItem/EditableItem.Input.tsx @@ -1,10 +1,9 @@ /** @jsxImportSource @emotion/react */ import {forwardRef, useEffect, useImperativeHandle, useRef} from 'react'; -import Flex from '@components/Flex/Flex'; -import Text from '@components/Text/Text'; -import IsFixedIcon from '@components/IsFixedIcon/IsFixedIcon'; - +import Flex from '@HDcomponents/Flex/Flex'; +import Text from '@HDcomponents/Text/Text'; +import IsFixedIcon from '@HDcomponents/IsFixedIcon/IsFixedIcon'; import {useTheme} from '@theme/HDesignProvider'; import {editingContainerStyle, inputStyle, inputWrapperStyle, underlineStyle} from './EditableItem.Input.style'; diff --git a/HDesign/src/components/EditableItem/EditableItem.Input.type.ts b/client/src/components/Design/components/EditableItem/EditableItem.Input.type.ts similarity index 89% rename from HDesign/src/components/EditableItem/EditableItem.Input.type.ts rename to client/src/components/Design/components/EditableItem/EditableItem.Input.type.ts index 8fdd3d64a..e0f110990 100644 --- a/HDesign/src/components/EditableItem/EditableItem.Input.type.ts +++ b/client/src/components/Design/components/EditableItem/EditableItem.Input.type.ts @@ -1,5 +1,4 @@ -import {TextSize} from '@components/Text/Text.type'; - +import {TextSize} from '@HDcomponents/Text/Text.type'; import {Theme} from '@theme/theme.type'; export interface InputStyleProps { diff --git a/HDesign/src/components/EditableItem/EditableItem.context.tsx b/client/src/components/Design/components/EditableItem/EditableItem.context.tsx similarity index 100% rename from HDesign/src/components/EditableItem/EditableItem.context.tsx rename to client/src/components/Design/components/EditableItem/EditableItem.context.tsx diff --git a/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx b/client/src/components/Design/components/EditableItem/EditableItem.input.stories.tsx similarity index 92% rename from HDesign/src/components/EditableItem/EditableItem.input.stories.tsx rename to client/src/components/Design/components/EditableItem/EditableItem.input.stories.tsx index 370d07c89..1ef7b9a9e 100644 --- a/HDesign/src/components/EditableItem/EditableItem.input.stories.tsx +++ b/client/src/components/Design/components/EditableItem/EditableItem.input.stories.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; -import EditableItemInput from '@components/EditableItem/EditableItem.Input'; +import EditableItemInput from '@HDcomponents/EditableItem/EditableItem.Input'; import EditableItem from './EditableItem'; import {EditableItemProvider} from './EditableItem.context'; diff --git a/HDesign/src/components/EditableItem/EditableItem.stories.tsx b/client/src/components/Design/components/EditableItem/EditableItem.stories.tsx similarity index 98% rename from HDesign/src/components/EditableItem/EditableItem.stories.tsx rename to client/src/components/Design/components/EditableItem/EditableItem.stories.tsx index 38406727e..08b14f9e8 100644 --- a/HDesign/src/components/EditableItem/EditableItem.stories.tsx +++ b/client/src/components/Design/components/EditableItem/EditableItem.stories.tsx @@ -3,9 +3,9 @@ import type {Meta, StoryObj} from '@storybook/react'; import {useState} from 'react'; -import EditableItem from '@components/EditableItem/EditableItem'; -import Flex from '@components/Flex/Flex'; -import Text from '@components/Text/Text'; +import EditableItem from '@HDcomponents/EditableItem/EditableItem'; +import Flex from '@HDcomponents/Flex/Flex'; +import Text from '@HDcomponents/Text/Text'; const meta = { title: 'Components/EditableItem', diff --git a/HDesign/src/components/EditableItem/EditableItem.style.ts b/client/src/components/Design/components/EditableItem/EditableItem.style.ts similarity index 99% rename from HDesign/src/components/EditableItem/EditableItem.style.ts rename to client/src/components/Design/components/EditableItem/EditableItem.style.ts index 97142f2d8..bda09a8c9 100644 --- a/HDesign/src/components/EditableItem/EditableItem.style.ts +++ b/client/src/components/Design/components/EditableItem/EditableItem.style.ts @@ -1,7 +1,6 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export const editableItemStyle = (theme: Theme, backgroundColor: ColorKeys) => diff --git a/HDesign/src/components/EditableItem/EditableItem.tsx b/client/src/components/Design/components/EditableItem/EditableItem.tsx similarity index 93% rename from HDesign/src/components/EditableItem/EditableItem.tsx rename to client/src/components/Design/components/EditableItem/EditableItem.tsx index f8b9ca434..97a295ccb 100644 --- a/HDesign/src/components/EditableItem/EditableItem.tsx +++ b/client/src/components/Design/components/EditableItem/EditableItem.tsx @@ -1,7 +1,6 @@ /** @jsxImportSource @emotion/react */ -import Text from '@components/Text/Text'; -import Flex from '@components/Flex/Flex'; - +import Text from '@HDcomponents/Text/Text'; +import Flex from '@HDcomponents/Flex/Flex'; import {useTheme} from '@theme/HDesignProvider'; import {editableItemStyle, labelTextStyle} from './EditableItem.style'; diff --git a/HDesign/src/components/EditableItem/EditableItem.type.ts b/client/src/components/Design/components/EditableItem/EditableItem.type.ts similarity index 99% rename from HDesign/src/components/EditableItem/EditableItem.type.ts rename to client/src/components/Design/components/EditableItem/EditableItem.type.ts index a56835855..e28114308 100644 --- a/HDesign/src/components/EditableItem/EditableItem.type.ts +++ b/client/src/components/Design/components/EditableItem/EditableItem.type.ts @@ -1,5 +1,4 @@ import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export interface EditableItemStyleProps { diff --git a/HDesign/src/components/EditableItem/useEditableItem.ts b/client/src/components/Design/components/EditableItem/useEditableItem.ts similarity index 100% rename from HDesign/src/components/EditableItem/useEditableItem.ts rename to client/src/components/Design/components/EditableItem/useEditableItem.ts diff --git a/HDesign/src/components/EditableItem/useEditableItemInput.ts b/client/src/components/Design/components/EditableItem/useEditableItemInput.ts similarity index 98% rename from HDesign/src/components/EditableItem/useEditableItemInput.ts rename to client/src/components/Design/components/EditableItem/useEditableItemInput.ts index 3253ad0ea..c9899a211 100644 --- a/HDesign/src/components/EditableItem/useEditableItemInput.ts +++ b/client/src/components/Design/components/EditableItem/useEditableItemInput.ts @@ -32,6 +32,8 @@ const useEditableItemInput = ({inputRef}: UseEditableItemInputProps) => { input.removeEventListener('blur', handleBlur); }; } + + return; }, [handleFocus, handleBlur, inputRef]); useEffect(() => { diff --git a/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx similarity index 90% rename from HDesign/src/components/ExpenseList/ExpenseList.stories.tsx rename to client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx index ccf8e28de..6d6bd339b 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.stories.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; -import ExpenseList from '@components/ExpenseList/ExpenseList'; +import ExpenseList from '@HDcomponents/ExpenseList/ExpenseList'; const meta = { title: 'Components/ExpenseList', diff --git a/HDesign/src/components/ExpenseList/ExpenseList.style.ts b/client/src/components/Design/components/ExpenseList/ExpenseList.style.ts similarity index 100% rename from HDesign/src/components/ExpenseList/ExpenseList.style.ts rename to client/src/components/Design/components/ExpenseList/ExpenseList.style.ts diff --git a/HDesign/src/components/ExpenseList/ExpenseList.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx similarity index 92% rename from HDesign/src/components/ExpenseList/ExpenseList.tsx rename to client/src/components/Design/components/ExpenseList/ExpenseList.tsx index 1f57810e5..74d06c86b 100644 --- a/HDesign/src/components/ExpenseList/ExpenseList.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx @@ -1,8 +1,7 @@ /** @jsxImportSource @emotion/react */ -import Text from '@components/Text/Text'; -import Icon from '@components/Icon/Icon'; - +import Text from '@HDcomponents/Text/Text'; +import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; diff --git a/HDesign/src/components/ExpenseList/ExpenseList.type.ts b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts similarity index 100% rename from HDesign/src/components/ExpenseList/ExpenseList.type.ts rename to client/src/components/Design/components/ExpenseList/ExpenseList.type.ts diff --git a/HDesign/src/components/FixedButton/FixedButton.stories.tsx b/client/src/components/Design/components/FixedButton/FixedButton.stories.tsx similarity index 93% rename from HDesign/src/components/FixedButton/FixedButton.stories.tsx rename to client/src/components/Design/components/FixedButton/FixedButton.stories.tsx index 47485f851..ad5a98ee9 100644 --- a/HDesign/src/components/FixedButton/FixedButton.stories.tsx +++ b/client/src/components/Design/components/FixedButton/FixedButton.stories.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; -import FixedButton from '@components/FixedButton/FixedButton'; +import FixedButton from '@HDcomponents/FixedButton/FixedButton'; const meta = { title: 'Components/FixedButton', diff --git a/HDesign/src/components/FixedButton/FixedButton.style.ts b/client/src/components/Design/components/FixedButton/FixedButton.style.ts similarity index 93% rename from HDesign/src/components/FixedButton/FixedButton.style.ts rename to client/src/components/Design/components/FixedButton/FixedButton.style.ts index 2e774918d..a0128a3ee 100644 --- a/HDesign/src/components/FixedButton/FixedButton.style.ts +++ b/client/src/components/Design/components/FixedButton/FixedButton.style.ts @@ -1,11 +1,9 @@ import {css} from '@emotion/react'; -import {ButtonVariants} from '@components/Button/Button.type'; -import {FixedButtonStyleProps} from '@components/FixedButton/FixedButton.type'; - +import {ButtonVariants} from '@HDcomponents/Button/Button.type'; +import {FixedButtonStyleProps} from '@HDcomponents/FixedButton/FixedButton.type'; import {Theme} from '@theme/theme.type'; - -import {setDarker, setLighter} from '@utils/colors'; +import {setDarker, setLighter} from '@HDutils/colors'; export const fixedButtonContainerStyle = (theme: Theme) => css({ diff --git a/HDesign/src/components/FixedButton/FixedButton.tsx b/client/src/components/Design/components/FixedButton/FixedButton.tsx similarity index 80% rename from HDesign/src/components/FixedButton/FixedButton.tsx rename to client/src/components/Design/components/FixedButton/FixedButton.tsx index 4430016d6..3114bb9ce 100644 --- a/HDesign/src/components/FixedButton/FixedButton.tsx +++ b/client/src/components/Design/components/FixedButton/FixedButton.tsx @@ -2,17 +2,15 @@ import {forwardRef} from 'react'; import Lottie from 'lottie-react'; +import loadingAnimation from '@assets/image/loadingAnimation.json'; import { fixedButtonContainerStyle, fixedButtonStyle, buttonContainerStyle, -} from '@components/FixedButton/FixedButton.style'; -import {FixedButtonProps} from '@components/FixedButton/FixedButton.type'; -import IconButton from '@components/IconButton/IconButton'; -import Icon from '@components/Icon/Icon'; - -import loadingAnimation from '@assets/loadingAnimation.json'; - +} from '@HDcomponents/FixedButton/FixedButton.style'; +import {FixedButtonProps} from '@HDcomponents/FixedButton/FixedButton.type'; +import IconButton from '@HDcomponents/IconButton/IconButton'; +import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElement, FixedButtonProps>(function Button( diff --git a/HDesign/src/components/FixedButton/FixedButton.type.ts b/client/src/components/Design/components/FixedButton/FixedButton.type.ts similarity index 85% rename from HDesign/src/components/FixedButton/FixedButton.type.ts rename to client/src/components/Design/components/FixedButton/FixedButton.type.ts index 1e8c55144..4d4f74a08 100644 --- a/HDesign/src/components/FixedButton/FixedButton.type.ts +++ b/client/src/components/Design/components/FixedButton/FixedButton.type.ts @@ -1,5 +1,4 @@ -import {ButtonVariants} from '@components/Button/Button.type'; - +import {ButtonVariants} from '@HDcomponents/Button/Button.type'; import {Theme} from '@theme/theme.type'; export interface FixedButtonStyleProps { diff --git a/HDesign/src/components/Flex/Flex.style.ts b/client/src/components/Design/components/Flex/Flex.style.ts similarity index 94% rename from HDesign/src/components/Flex/Flex.style.ts rename to client/src/components/Design/components/Flex/Flex.style.ts index 672cf2dd6..548a37654 100644 --- a/HDesign/src/components/Flex/Flex.style.ts +++ b/client/src/components/Design/components/Flex/Flex.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {changeCamelCaseToKebabCase} from '@utils/changeCamelCaseToKebabCase'; +import {changeCamelCaseToKebabCase} from '../../utils/changeCamelCaseToKebabCase'; import {FlexDirectionStrictType, FlexProps} from './Flex.type'; diff --git a/HDesign/src/components/Flex/Flex.tsx b/client/src/components/Design/components/Flex/Flex.tsx similarity index 91% rename from HDesign/src/components/Flex/Flex.tsx rename to client/src/components/Design/components/Flex/Flex.tsx index 26ce953f7..08709701a 100644 --- a/HDesign/src/components/Flex/Flex.tsx +++ b/client/src/components/Design/components/Flex/Flex.tsx @@ -3,7 +3,7 @@ import {css} from '@emotion/react'; import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; -import {useTheme} from '@theme/HDesignProvider'; +import {useTheme} from '../../index'; import {FlexProps} from './Flex.type'; import {flexStyle} from './Flex.style'; diff --git a/HDesign/src/components/Flex/Flex.type.ts b/client/src/components/Design/components/Flex/Flex.type.ts similarity index 93% rename from HDesign/src/components/Flex/Flex.type.ts rename to client/src/components/Design/components/Flex/Flex.type.ts index e70fb4c21..d3db7b414 100644 --- a/HDesign/src/components/Flex/Flex.type.ts +++ b/client/src/components/Design/components/Flex/Flex.type.ts @@ -1,4 +1,4 @@ -import {Theme} from '@theme/theme.type'; +import {Theme} from '../../theme/theme.type'; export type FlexDirectionType = 'row' | 'column' | 'rowReverse' | 'columnReverse'; export type FlexDirectionStrictType = 'row' | 'column' | 'row-reverse' | 'column-reverse'; diff --git a/HDesign/src/components/Icon/Icon.stories.tsx b/client/src/components/Design/components/Icon/Icon.stories.tsx similarity index 92% rename from HDesign/src/components/Icon/Icon.stories.tsx rename to client/src/components/Design/components/Icon/Icon.stories.tsx index 3d2ef4aae..ee111a2f9 100644 --- a/HDesign/src/components/Icon/Icon.stories.tsx +++ b/client/src/components/Design/components/Icon/Icon.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import Icon from '@components/Icon/Icon'; +import Icon from '@HDcomponents/Icon/Icon'; const meta = { title: 'Components/Icon', diff --git a/HDesign/src/components/Icon/Icon.style.ts b/client/src/components/Design/components/Icon/Icon.style.ts similarity index 99% rename from HDesign/src/components/Icon/Icon.style.ts rename to client/src/components/Design/components/Icon/Icon.style.ts index b19601da6..f0ac3db04 100644 --- a/HDesign/src/components/Icon/Icon.style.ts +++ b/client/src/components/Design/components/Icon/Icon.style.ts @@ -1,7 +1,6 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; import {IconColor, IconStylePropsWithTheme, IconType} from './Icon.type'; diff --git a/HDesign/src/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx similarity index 59% rename from HDesign/src/components/Icon/Icon.tsx rename to client/src/components/Design/components/Icon/Icon.tsx index 13d8e7835..cfe22a786 100644 --- a/HDesign/src/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -1,8 +1,13 @@ /** @jsxImportSource @emotion/react */ -import {IconProps} from '@components/Icon/Icon.type'; -import {InputDelete, Buljusa, RightChevron, Search, Trash, Confirm, Error} from '@assets'; - +import InputDelete from '@assets/image/inputDelete.svg'; +import Buljusa from '@assets/image/buljusa.svg'; +import Error from '@assets/image/error.svg'; +import Confirm from '@assets/image/confirm.svg'; +import Trash from '@assets/image/trash.svg'; +import Search from '@assets/image/search.svg'; +import RightChevron from '@assets/image/rightChevron.svg'; +import {IconProps} from '@HDcomponents/Icon/Icon.type'; import {useTheme} from '@theme/HDesignProvider'; import {iconStyle} from './Icon.style'; diff --git a/HDesign/src/components/Icon/Icon.type.ts b/client/src/components/Design/components/Icon/Icon.type.ts similarity index 99% rename from HDesign/src/components/Icon/Icon.type.ts rename to client/src/components/Design/components/Icon/Icon.type.ts index 57fc25cfb..f07679cf0 100644 --- a/HDesign/src/components/Icon/Icon.type.ts +++ b/client/src/components/Design/components/Icon/Icon.type.ts @@ -1,5 +1,4 @@ import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export type IconType = 'inputDelete' | 'buljusa' | 'rightChevron' | 'search' | 'error' | 'confirm' | 'trash'; diff --git a/HDesign/src/components/IconButton/IconButton.stories.tsx b/client/src/components/Design/components/IconButton/IconButton.stories.tsx similarity index 92% rename from HDesign/src/components/IconButton/IconButton.stories.tsx rename to client/src/components/Design/components/IconButton/IconButton.stories.tsx index 6cc2b5f3d..336d9925f 100644 --- a/HDesign/src/components/IconButton/IconButton.stories.tsx +++ b/client/src/components/Design/components/IconButton/IconButton.stories.tsx @@ -1,8 +1,8 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; -import IconButton from '@components/IconButton/IconButton'; -import Icon from '@components/Icon/Icon'; +import IconButton from '@HDcomponents/IconButton/IconButton'; +import Icon from '@HDcomponents/Icon/Icon'; const meta = { title: 'Components/IconButton', diff --git a/HDesign/src/components/IconButton/IconButton.style.ts b/client/src/components/Design/components/IconButton/IconButton.style.ts similarity index 97% rename from HDesign/src/components/IconButton/IconButton.style.ts rename to client/src/components/Design/components/IconButton/IconButton.style.ts index 53036eb68..26b2e0c90 100644 --- a/HDesign/src/components/IconButton/IconButton.style.ts +++ b/client/src/components/Design/components/IconButton/IconButton.style.ts @@ -2,8 +2,7 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; - -import {setDarker, setLighter} from '@utils/colors'; +import {setDarker, setLighter} from '@HDutils/colors'; import { IconButtonSize, diff --git a/HDesign/src/components/IconButton/IconButton.tsx b/client/src/components/Design/components/IconButton/IconButton.tsx similarity index 88% rename from HDesign/src/components/IconButton/IconButton.tsx rename to client/src/components/Design/components/IconButton/IconButton.tsx index bc704db67..084e920d6 100644 --- a/HDesign/src/components/IconButton/IconButton.tsx +++ b/client/src/components/Design/components/IconButton/IconButton.tsx @@ -1,8 +1,7 @@ /** @jsxImportSource @emotion/react */ import {forwardRef} from 'react'; -import {IconButtonProps} from '@components/IconButton/IconButton.type'; - +import {IconButtonProps} from '@HDcomponents/IconButton/IconButton.type'; import {useTheme} from '@theme/HDesignProvider'; import {iconButtonStyle} from './IconButton.style'; diff --git a/HDesign/src/components/IconButton/IconButton.type.ts b/client/src/components/Design/components/IconButton/IconButton.type.ts similarity index 100% rename from HDesign/src/components/IconButton/IconButton.type.ts rename to client/src/components/Design/components/IconButton/IconButton.type.ts diff --git a/HDesign/src/components/Input/Input.stories.tsx b/client/src/components/Design/components/Input/Input.stories.tsx similarity index 90% rename from HDesign/src/components/Input/Input.stories.tsx rename to client/src/components/Design/components/Input/Input.stories.tsx index dc46e022f..9b99700c5 100644 --- a/HDesign/src/components/Input/Input.stories.tsx +++ b/client/src/components/Design/components/Input/Input.stories.tsx @@ -2,9 +2,9 @@ import type {Meta, StoryObj} from '@storybook/react'; import React, {useEffect, useState} from 'react'; -import Input from '@components/Input/Input'; -import Flex from '@components/Flex/Flex'; -import Button from '@components/Button/Button'; +import Input from '@HDcomponents/Input/Input'; +import Flex from '@HDcomponents/Flex/Flex'; +import Button from '@HDcomponents/Button/Button'; const meta = { title: 'Components/Input', diff --git a/HDesign/src/components/Input/Input.style.ts b/client/src/components/Design/components/Input/Input.style.ts similarity index 100% rename from HDesign/src/components/Input/Input.style.ts rename to client/src/components/Design/components/Input/Input.style.ts diff --git a/HDesign/src/components/Input/Input.tsx b/client/src/components/Design/components/Input/Input.tsx similarity index 82% rename from HDesign/src/components/Input/Input.tsx rename to client/src/components/Design/components/Input/Input.tsx index 37945e434..111b42f1c 100644 --- a/HDesign/src/components/Input/Input.tsx +++ b/client/src/components/Design/components/Input/Input.tsx @@ -1,12 +1,11 @@ /** @jsxImportSource @emotion/react */ import React, {forwardRef, useImperativeHandle, useRef} from 'react'; -import IconButton from '@components/IconButton/IconButton'; -import {InputProps} from '@components/Input/Input.type'; -import {inputBoxStyle, inputStyle} from '@components/Input/Input.style'; -import {useInput} from '@components/Input/useInput'; -import Icon from '@components/Icon/Icon'; - +import IconButton from '@HDcomponents/IconButton/IconButton'; +import {InputProps} from '@HDcomponents/Input/Input.type'; +import {inputBoxStyle, inputStyle} from '@HDcomponents/Input/Input.style'; +import {useInput} from '@HDcomponents/Input/useInput'; +import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( diff --git a/HDesign/src/components/Input/Input.type.ts b/client/src/components/Design/components/Input/Input.type.ts similarity index 100% rename from HDesign/src/components/Input/Input.type.ts rename to client/src/components/Design/components/Input/Input.type.ts diff --git a/HDesign/src/components/Input/useInput.ts b/client/src/components/Design/components/Input/useInput.ts similarity index 100% rename from HDesign/src/components/Input/useInput.ts rename to client/src/components/Design/components/Input/useInput.ts diff --git a/HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts b/client/src/components/Design/components/IsFixedIcon/IsFixedIcon.style.ts similarity index 100% rename from HDesign/src/components/IsFixedIcon/IsFixedIcon.style.ts rename to client/src/components/Design/components/IsFixedIcon/IsFixedIcon.style.ts diff --git a/HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx b/client/src/components/Design/components/IsFixedIcon/IsFixedIcon.tsx similarity index 100% rename from HDesign/src/components/IsFixedIcon/IsFixedIcon.tsx rename to client/src/components/Design/components/IsFixedIcon/IsFixedIcon.tsx diff --git a/HDesign/src/components/LabelGroupInput/Element.tsx b/client/src/components/Design/components/LabelGroupInput/Element.tsx similarity index 100% rename from HDesign/src/components/LabelGroupInput/Element.tsx rename to client/src/components/Design/components/LabelGroupInput/Element.tsx diff --git a/HDesign/src/components/LabelGroupInput/Element.type.ts b/client/src/components/Design/components/LabelGroupInput/Element.type.ts similarity index 100% rename from HDesign/src/components/LabelGroupInput/Element.type.ts rename to client/src/components/Design/components/LabelGroupInput/Element.type.ts diff --git a/HDesign/src/components/LabelGroupInput/GroupInputContext.tsx b/client/src/components/Design/components/LabelGroupInput/GroupInputContext.tsx similarity index 100% rename from HDesign/src/components/LabelGroupInput/GroupInputContext.tsx rename to client/src/components/Design/components/LabelGroupInput/GroupInputContext.tsx diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.stories.tsx similarity index 96% rename from HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx rename to client/src/components/Design/components/LabelGroupInput/LabelGroupInput.stories.tsx index 4eec9634f..a2b873060 100644 --- a/HDesign/src/components/LabelGroupInput/LabelGroupInput.stories.tsx +++ b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.stories.tsx @@ -3,7 +3,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import {useState} from 'react'; -import LabelGroupInput from '@components/LabelGroupInput/LabelGroupInput'; +import LabelGroupInput from '@HDcomponents/LabelGroupInput/LabelGroupInput'; const meta = { title: 'Components/LabelGroupInput', diff --git a/HDesign/src/components/LabelInput/LabelInput.style.ts b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.style.ts similarity index 100% rename from HDesign/src/components/LabelInput/LabelInput.style.ts rename to client/src/components/Design/components/LabelGroupInput/LabelGroupInput.style.ts diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.tsx similarity index 97% rename from HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx rename to client/src/components/Design/components/LabelGroupInput/LabelGroupInput.tsx index 33d1d447d..3c60e14a6 100644 --- a/HDesign/src/components/LabelGroupInput/LabelGroupInput.tsx +++ b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.tsx @@ -1,7 +1,6 @@ /** @jsxImportSource @emotion/react */ -import Text from '@components/Text/Text'; - +import Text from '@HDcomponents/Text/Text'; import {useTheme} from '@theme/HDesignProvider'; import Flex from '../Flex/Flex'; diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.type.ts similarity index 100% rename from HDesign/src/components/LabelGroupInput/LabelGroupInput.type.ts rename to client/src/components/Design/components/LabelGroupInput/LabelGroupInput.type.ts diff --git a/HDesign/src/components/LabelGroupInput/index.ts b/client/src/components/Design/components/LabelGroupInput/index.ts similarity index 100% rename from HDesign/src/components/LabelGroupInput/index.ts rename to client/src/components/Design/components/LabelGroupInput/index.ts diff --git a/HDesign/src/components/LabelInput/LabelInput.stories.tsx b/client/src/components/Design/components/LabelInput/LabelInput.stories.tsx similarity index 95% rename from HDesign/src/components/LabelInput/LabelInput.stories.tsx rename to client/src/components/Design/components/LabelInput/LabelInput.stories.tsx index a272037a4..9bff764ef 100644 --- a/HDesign/src/components/LabelInput/LabelInput.stories.tsx +++ b/client/src/components/Design/components/LabelInput/LabelInput.stories.tsx @@ -3,7 +3,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import {useEffect, useState} from 'react'; -import LabelInput from '@components/LabelInput/LabelInput'; +import LabelInput from '@HDcomponents/LabelInput/LabelInput'; const meta = { title: 'Components/LabelInput', diff --git a/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts b/client/src/components/Design/components/LabelInput/LabelInput.style.ts similarity index 93% rename from HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts rename to client/src/components/Design/components/LabelInput/LabelInput.style.ts index 8339ef4a4..df64636e9 100644 --- a/HDesign/src/components/LabelGroupInput/LabelGroupInput.style.ts +++ b/client/src/components/Design/components/LabelInput/LabelInput.style.ts @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Theme} from '@/theme/theme.type'; +import {Theme} from '@theme/theme.type'; export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => css({ diff --git a/HDesign/src/components/LabelInput/LabelInput.tsx b/client/src/components/Design/components/LabelInput/LabelInput.tsx similarity index 96% rename from HDesign/src/components/LabelInput/LabelInput.tsx rename to client/src/components/Design/components/LabelInput/LabelInput.tsx index 43f60c220..f3228cde2 100644 --- a/HDesign/src/components/LabelInput/LabelInput.tsx +++ b/client/src/components/Design/components/LabelInput/LabelInput.tsx @@ -2,8 +2,7 @@ import {forwardRef, useImperativeHandle, useRef} from 'react'; -import Text from '@components/Text/Text'; - +import Text from '@HDcomponents/Text/Text'; import {useTheme} from '@theme/HDesignProvider'; import Input from '../Input/Input'; diff --git a/HDesign/src/components/LabelInput/LabelInput.type.ts b/client/src/components/Design/components/LabelInput/LabelInput.type.ts similarity index 100% rename from HDesign/src/components/LabelInput/LabelInput.type.ts rename to client/src/components/Design/components/LabelInput/LabelInput.type.ts diff --git a/HDesign/src/components/LabelInput/useLabelInput.ts b/client/src/components/Design/components/LabelInput/useLabelInput.ts similarity index 100% rename from HDesign/src/components/LabelInput/useLabelInput.ts rename to client/src/components/Design/components/LabelInput/useLabelInput.ts diff --git a/HDesign/src/components/ListButton/ListButton.stories.tsx b/client/src/components/Design/components/ListButton/ListButton.stories.tsx similarity index 90% rename from HDesign/src/components/ListButton/ListButton.stories.tsx rename to client/src/components/Design/components/ListButton/ListButton.stories.tsx index 27f7744d1..1e15d22f7 100644 --- a/HDesign/src/components/ListButton/ListButton.stories.tsx +++ b/client/src/components/Design/components/ListButton/ListButton.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import ListButton from '@components/ListButton/ListButton'; +import ListButton from '@HDcomponents/ListButton/ListButton'; const meta = { title: 'Components/ListButton', diff --git a/HDesign/src/components/ListButton/ListButton.style.ts b/client/src/components/Design/components/ListButton/ListButton.style.ts similarity index 100% rename from HDesign/src/components/ListButton/ListButton.style.ts rename to client/src/components/Design/components/ListButton/ListButton.style.ts diff --git a/HDesign/src/components/ListButton/ListButton.tsx b/client/src/components/Design/components/ListButton/ListButton.tsx similarity index 82% rename from HDesign/src/components/ListButton/ListButton.tsx rename to client/src/components/Design/components/ListButton/ListButton.tsx index 10c417310..7249a4aa7 100644 --- a/HDesign/src/components/ListButton/ListButton.tsx +++ b/client/src/components/Design/components/ListButton/ListButton.tsx @@ -1,11 +1,10 @@ /** @jsxImportSource @emotion/react */ import React, {forwardRef} from 'react'; -import Text from '@components/Text/Text'; -import IconButton from '@components/IconButton/IconButton'; -import Flex from '@components/Flex/Flex'; -import Icon from '@components/Icon/Icon'; - +import Text from '@HDcomponents/Text/Text'; +import IconButton from '@HDcomponents/IconButton/IconButton'; +import Flex from '@HDcomponents/Flex/Flex'; +import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; import {ListButtonProps} from './ListButton.type'; diff --git a/HDesign/src/components/ListButton/ListButton.type.ts b/client/src/components/Design/components/ListButton/ListButton.type.ts similarity index 100% rename from HDesign/src/components/ListButton/ListButton.type.ts rename to client/src/components/Design/components/ListButton/ListButton.type.ts diff --git a/HDesign/src/components/Search/Search.stories.tsx b/client/src/components/Design/components/Search/Search.stories.tsx similarity index 92% rename from HDesign/src/components/Search/Search.stories.tsx rename to client/src/components/Design/components/Search/Search.stories.tsx index 6b5d821cd..c1cba856d 100644 --- a/HDesign/src/components/Search/Search.stories.tsx +++ b/client/src/components/Design/components/Search/Search.stories.tsx @@ -2,7 +2,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import React from 'react'; -import Search from '@components/Search/Search'; +import Search from '@HDcomponents/Search/Search'; const meta = { title: 'Components/Search', diff --git a/HDesign/src/components/Search/Search.style.ts b/client/src/components/Design/components/Search/Search.style.ts similarity index 100% rename from HDesign/src/components/Search/Search.style.ts rename to client/src/components/Design/components/Search/Search.style.ts diff --git a/HDesign/src/components/Search/Search.tsx b/client/src/components/Design/components/Search/Search.tsx similarity index 96% rename from HDesign/src/components/Search/Search.tsx rename to client/src/components/Design/components/Search/Search.tsx index 58c292cc4..aa1fa8a4c 100644 --- a/HDesign/src/components/Search/Search.tsx +++ b/client/src/components/Design/components/Search/Search.tsx @@ -1,6 +1,5 @@ /** @jsxImportSource @emotion/react */ -import Flex from '@components/Flex/Flex'; - +import Flex from '@HDcomponents/Flex/Flex'; import {useTheme} from '@theme/HDesignProvider'; import {searchStyle, searchTermsStyle, searchTermStyle} from './Search.style'; diff --git a/HDesign/src/components/Switch/Switch.stories.tsx b/client/src/components/Design/components/Switch/Switch.stories.tsx similarity index 92% rename from HDesign/src/components/Switch/Switch.stories.tsx rename to client/src/components/Design/components/Switch/Switch.stories.tsx index a3558754a..870783682 100644 --- a/HDesign/src/components/Switch/Switch.stories.tsx +++ b/client/src/components/Design/components/Switch/Switch.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import Switch from '@components/Switch/Switch'; +import Switch from '@HDcomponents/Switch/Switch'; const meta = { title: 'Components/Switch', diff --git a/HDesign/src/components/Switch/Switch.style.ts b/client/src/components/Design/components/Switch/Switch.style.ts similarity index 100% rename from HDesign/src/components/Switch/Switch.style.ts rename to client/src/components/Design/components/Switch/Switch.style.ts diff --git a/HDesign/src/components/Switch/Switch.tsx b/client/src/components/Design/components/Switch/Switch.tsx similarity index 100% rename from HDesign/src/components/Switch/Switch.tsx rename to client/src/components/Design/components/Switch/Switch.tsx diff --git a/HDesign/src/components/Switch/Switch.type.ts b/client/src/components/Design/components/Switch/Switch.type.ts similarity index 100% rename from HDesign/src/components/Switch/Switch.type.ts rename to client/src/components/Design/components/Switch/Switch.type.ts diff --git a/HDesign/src/components/Tabs/Tab.tsx b/client/src/components/Design/components/Tabs/Tab.tsx similarity index 100% rename from HDesign/src/components/Tabs/Tab.tsx rename to client/src/components/Design/components/Tabs/Tab.tsx diff --git a/HDesign/src/components/Tabs/Tab.type.ts b/client/src/components/Design/components/Tabs/Tab.type.ts similarity index 100% rename from HDesign/src/components/Tabs/Tab.type.ts rename to client/src/components/Design/components/Tabs/Tab.type.ts diff --git a/HDesign/src/components/Tabs/Tabs.stories.tsx b/client/src/components/Design/components/Tabs/Tabs.stories.tsx similarity index 93% rename from HDesign/src/components/Tabs/Tabs.stories.tsx rename to client/src/components/Design/components/Tabs/Tabs.stories.tsx index a40e60b07..b5767e40b 100644 --- a/HDesign/src/components/Tabs/Tabs.stories.tsx +++ b/client/src/components/Design/components/Tabs/Tabs.stories.tsx @@ -2,7 +2,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import React from 'react'; -import Tabs from '@components/Tabs/Tabs'; +import Tabs from '@HDcomponents/Tabs/Tabs'; import Tab from './Tab'; diff --git a/HDesign/src/components/Tabs/Tabs.style.ts b/client/src/components/Design/components/Tabs/Tabs.style.ts similarity index 100% rename from HDesign/src/components/Tabs/Tabs.style.ts rename to client/src/components/Design/components/Tabs/Tabs.style.ts diff --git a/HDesign/src/components/Tabs/Tabs.tsx b/client/src/components/Design/components/Tabs/Tabs.tsx similarity index 100% rename from HDesign/src/components/Tabs/Tabs.tsx rename to client/src/components/Design/components/Tabs/Tabs.tsx diff --git a/HDesign/src/components/Text/Text.stories.tsx b/client/src/components/Design/components/Text/Text.stories.tsx similarity index 93% rename from HDesign/src/components/Text/Text.stories.tsx rename to client/src/components/Design/components/Text/Text.stories.tsx index 5e5ec2287..9007b4756 100644 --- a/HDesign/src/components/Text/Text.stories.tsx +++ b/client/src/components/Design/components/Text/Text.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import Text from '@components/Text/Text'; +import Text from '@HDcomponents/Text/Text'; const meta = { title: 'Components/Text', diff --git a/HDesign/src/components/Text/Text.style.ts b/client/src/components/Design/components/Text/Text.style.ts similarity index 100% rename from HDesign/src/components/Text/Text.style.ts rename to client/src/components/Design/components/Text/Text.style.ts diff --git a/HDesign/src/components/Text/Text.tsx b/client/src/components/Design/components/Text/Text.tsx similarity index 87% rename from HDesign/src/components/Text/Text.tsx rename to client/src/components/Design/components/Text/Text.tsx index 9b7853aa8..e8b28c19e 100644 --- a/HDesign/src/components/Text/Text.tsx +++ b/client/src/components/Design/components/Text/Text.tsx @@ -1,5 +1,5 @@ /** @jsxImportSource @emotion/react */ -import type {TextProps} from '@components/Text/Text.type'; +import type {TextProps} from '@HDcomponents/Text/Text.type'; import React from 'react'; diff --git a/HDesign/src/components/Text/Text.type.ts b/client/src/components/Design/components/Text/Text.type.ts similarity index 99% rename from HDesign/src/components/Text/Text.type.ts rename to client/src/components/Design/components/Text/Text.type.ts index 157591abf..d67a3618d 100644 --- a/HDesign/src/components/Text/Text.type.ts +++ b/client/src/components/Design/components/Text/Text.type.ts @@ -1,5 +1,4 @@ import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; export type TextSize = diff --git a/HDesign/src/components/TextButton/TextButton.stories.tsx b/client/src/components/Design/components/TextButton/TextButton.stories.tsx similarity index 93% rename from HDesign/src/components/TextButton/TextButton.stories.tsx rename to client/src/components/Design/components/TextButton/TextButton.stories.tsx index 9873df3f4..a996d19e6 100644 --- a/HDesign/src/components/TextButton/TextButton.stories.tsx +++ b/client/src/components/Design/components/TextButton/TextButton.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import TextButton from '@components/TextButton/TextButton'; +import TextButton from '@HDcomponents/TextButton/TextButton'; const meta = { title: 'Components/TextButton', diff --git a/HDesign/src/components/TextButton/TextButton.style.ts b/client/src/components/Design/components/TextButton/TextButton.style.ts similarity index 99% rename from HDesign/src/components/TextButton/TextButton.style.ts rename to client/src/components/Design/components/TextButton/TextButton.style.ts index c8d8738fe..5edc50919 100644 --- a/HDesign/src/components/TextButton/TextButton.style.ts +++ b/client/src/components/Design/components/TextButton/TextButton.style.ts @@ -1,7 +1,6 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; - import {ColorKeys} from '@token/colors'; interface TextButtonStyleProps { diff --git a/HDesign/src/components/TextButton/TextButton.tsx b/client/src/components/Design/components/TextButton/TextButton.tsx similarity index 100% rename from HDesign/src/components/TextButton/TextButton.tsx rename to client/src/components/Design/components/TextButton/TextButton.tsx diff --git a/HDesign/src/components/TextButton/TextButton.type.ts b/client/src/components/Design/components/TextButton/TextButton.type.ts similarity index 100% rename from HDesign/src/components/TextButton/TextButton.type.ts rename to client/src/components/Design/components/TextButton/TextButton.type.ts diff --git a/HDesign/src/components/Title/Title.stories.tsx b/client/src/components/Design/components/Title/Title.stories.tsx similarity index 94% rename from HDesign/src/components/Title/Title.stories.tsx rename to client/src/components/Design/components/Title/Title.stories.tsx index 2c91287b4..4eab2d5c8 100644 --- a/HDesign/src/components/Title/Title.stories.tsx +++ b/client/src/components/Design/components/Title/Title.stories.tsx @@ -1,6 +1,6 @@ import type {Meta, StoryObj} from '@storybook/react'; -import Title from '@components/Title/Title'; +import Title from '@HDcomponents/Title/Title'; const meta = { title: 'Components/Title', diff --git a/HDesign/src/components/Title/Title.style.ts b/client/src/components/Design/components/Title/Title.style.ts similarity index 100% rename from HDesign/src/components/Title/Title.style.ts rename to client/src/components/Design/components/Title/Title.style.ts diff --git a/HDesign/src/components/Title/Title.tsx b/client/src/components/Design/components/Title/Title.tsx similarity index 77% rename from HDesign/src/components/Title/Title.tsx rename to client/src/components/Design/components/Title/Title.tsx index e17de5e88..4050399ea 100644 --- a/HDesign/src/components/Title/Title.tsx +++ b/client/src/components/Design/components/Title/Title.tsx @@ -1,9 +1,8 @@ /** @jsxImportSource @emotion/react */ -import Flex from '@components/Flex/Flex'; -import Text from '@components/Text/Text'; -import {priceContainerStyle, titleContainerStyle} from '@components/Title/Title.style'; -import {TitleProps} from '@components/Title/Title.type'; - +import Flex from '@HDcomponents/Flex/Flex'; +import Text from '@HDcomponents/Text/Text'; +import {priceContainerStyle, titleContainerStyle} from '@HDcomponents/Title/Title.style'; +import {TitleProps} from '@HDcomponents/Title/Title.type'; import {useTheme} from '@theme/HDesignProvider'; export const Title: React.FC<TitleProps> = ({title, description, price}: TitleProps) => { diff --git a/HDesign/src/components/Title/Title.type.ts b/client/src/components/Design/components/Title/Title.type.ts similarity index 100% rename from HDesign/src/components/Title/Title.type.ts rename to client/src/components/Design/components/Title/Title.type.ts diff --git a/HDesign/src/components/TopNav/Back.tsx b/client/src/components/Design/components/TopNav/Back.tsx similarity index 84% rename from HDesign/src/components/TopNav/Back.tsx rename to client/src/components/Design/components/TopNav/Back.tsx index cfb55e24d..73065ebce 100644 --- a/HDesign/src/components/TopNav/Back.tsx +++ b/client/src/components/Design/components/TopNav/Back.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {useNavigate} from 'react-router-dom'; -import TextButton from '@components/TextButton/TextButton'; +import TextButton from '@HDcomponents/TextButton/TextButton'; function Back() { const navigate = useNavigate(); diff --git a/HDesign/src/components/TopNav/TopNav.stories.tsx b/client/src/components/Design/components/TopNav/TopNav.stories.tsx similarity index 95% rename from HDesign/src/components/TopNav/TopNav.stories.tsx rename to client/src/components/Design/components/TopNav/TopNav.stories.tsx index 0c96161a5..885ed4f5b 100644 --- a/HDesign/src/components/TopNav/TopNav.stories.tsx +++ b/client/src/components/Design/components/TopNav/TopNav.stories.tsx @@ -4,7 +4,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import React from 'react'; import {reactRouterParameters, withRouter} from 'storybook-addon-react-router-v6'; -import TopNav from '@components/TopNav/TopNav'; +import TopNav from '@HDcomponents/TopNav/TopNav'; import Switch from '../Switch/Switch'; diff --git a/HDesign/src/components/TopNav/TopNav.style.ts b/client/src/components/Design/components/TopNav/TopNav.style.ts similarity index 100% rename from HDesign/src/components/TopNav/TopNav.style.ts rename to client/src/components/Design/components/TopNav/TopNav.style.ts diff --git a/HDesign/src/components/TopNav/TopNav.tsx b/client/src/components/Design/components/TopNav/TopNav.tsx similarity index 92% rename from HDesign/src/components/TopNav/TopNav.tsx rename to client/src/components/Design/components/TopNav/TopNav.tsx index 643cd5e3b..1530322e9 100644 --- a/HDesign/src/components/TopNav/TopNav.tsx +++ b/client/src/components/Design/components/TopNav/TopNav.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import React from 'react'; -import Switch from '@components/Switch/Switch'; +import Switch from '@HDcomponents/Switch/Switch'; import {topNavNonStyle, topNavStyle} from './TopNav.style'; import Back from './Back'; diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx new file mode 100644 index 000000000..d6a9d2094 --- /dev/null +++ b/client/src/components/Design/index.tsx @@ -0,0 +1,56 @@ +import {MainLayout} from './layouts/MainLayout'; +import {ContentLayout} from './layouts/ContentLayout'; +import {HDesignProvider, useTheme} from './theme/HDesignProvider'; +import BottomSheet from './components/BottomSheet/BottomSheet'; +import Button from './components/Button/Button'; +import DragHandleItem from './components/DragHandleItem/DragHandleItem'; +import DragHandleItemContainer from './components/DragHandleItemContainer/DragHandleItemContainer'; +import EditableItem from './components/EditableItem/EditableItem'; +import ExpenseList from './components/ExpenseList/ExpenseList'; +import FixedButton from './components/FixedButton/FixedButton'; +import Flex from './components/Flex/Flex'; +import Icon from './components/Icon/Icon'; +import IconButton from './components/IconButton/IconButton'; +import Input from './components/Input/Input'; +import LabelInput from './components/LabelInput/LabelInput'; +import ListButton from './components/ListButton/ListButton'; +import LabelGroupInput from './components/LabelGroupInput/LabelGroupInput'; +import Search from './components/Search/Search'; +import Switch from './components/Switch/Switch'; +import Tab from './components/Tabs/Tab'; +import Tabs from './components/Tabs/Tabs'; +import Text from './components/Text/Text'; +import TextButton from './components/TextButton/TextButton'; +import Title from './components/Title/Title'; +import Back from './components/TopNav/Back'; +import TopNav from './components/TopNav/TopNav'; + +export { + BottomSheet, + Button, + DragHandleItem, + DragHandleItemContainer, + EditableItem, + ExpenseList, + FixedButton, + Flex, + Icon, + IconButton, + Input, + LabelInput, + ListButton, + LabelGroupInput, + Search, + Switch, + Tab, + Tabs, + Text, + TextButton, + Title, + TopNav, + Back, + MainLayout, + ContentLayout, + HDesignProvider, + useTheme, +}; diff --git a/HDesign/src/layouts/ContentLayout.tsx b/client/src/components/Design/layouts/ContentLayout.tsx similarity index 100% rename from HDesign/src/layouts/ContentLayout.tsx rename to client/src/components/Design/layouts/ContentLayout.tsx diff --git a/HDesign/src/layouts/MainLayout.tsx b/client/src/components/Design/layouts/MainLayout.tsx similarity index 100% rename from HDesign/src/layouts/MainLayout.tsx rename to client/src/components/Design/layouts/MainLayout.tsx diff --git a/HDesign/src/theme/GlobalStyle.ts b/client/src/components/Design/theme/GlobalStyle.ts similarity index 100% rename from HDesign/src/theme/GlobalStyle.ts rename to client/src/components/Design/theme/GlobalStyle.ts diff --git a/HDesign/src/theme/HDesignProvider.tsx b/client/src/components/Design/theme/HDesignProvider.tsx similarity index 99% rename from HDesign/src/theme/HDesignProvider.tsx rename to client/src/components/Design/theme/HDesignProvider.tsx index 6c7c571a3..e4b5312f7 100644 --- a/HDesign/src/theme/HDesignProvider.tsx +++ b/client/src/components/Design/theme/HDesignProvider.tsx @@ -3,7 +3,6 @@ import {Global} from '@emotion/react'; import {Theme} from '@theme/theme.type'; import {GlobalStyle} from '@theme/GlobalStyle'; - import {COLORS} from '@token/colors'; import {TYPOGRAPHY} from '@token/typography'; diff --git a/HDesign/src/theme/theme.type.ts b/client/src/components/Design/theme/theme.type.ts similarity index 100% rename from HDesign/src/theme/theme.type.ts rename to client/src/components/Design/theme/theme.type.ts diff --git a/HDesign/src/token/colors.ts b/client/src/components/Design/token/colors.ts similarity index 100% rename from HDesign/src/token/colors.ts rename to client/src/components/Design/token/colors.ts diff --git a/HDesign/src/token/typography.ts b/client/src/components/Design/token/typography.ts similarity index 100% rename from HDesign/src/token/typography.ts rename to client/src/components/Design/token/typography.ts diff --git a/HDesign/src/type/strictPropsWithChildren.ts b/client/src/components/Design/type/strictPropsWithChildren.ts similarity index 100% rename from HDesign/src/type/strictPropsWithChildren.ts rename to client/src/components/Design/type/strictPropsWithChildren.ts diff --git a/HDesign/src/type/withTheme.ts b/client/src/components/Design/type/withTheme.ts similarity index 100% rename from HDesign/src/type/withTheme.ts rename to client/src/components/Design/type/withTheme.ts diff --git a/HDesign/src/utils/changeCamelCaseToKebabCase.ts b/client/src/components/Design/utils/changeCamelCaseToKebabCase.ts similarity index 100% rename from HDesign/src/utils/changeCamelCaseToKebabCase.ts rename to client/src/components/Design/utils/changeCamelCaseToKebabCase.ts diff --git a/HDesign/src/utils/colors.ts b/client/src/components/Design/utils/colors.ts similarity index 100% rename from HDesign/src/utils/colors.ts rename to client/src/components/Design/utils/colors.ts diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/MemberReportList/MemberReportList.tsx index 21da76bed..bfc7cf84c 100644 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ b/client/src/components/MemberReportList/MemberReportList.tsx @@ -1,8 +1,9 @@ -import {ExpenseList, Flex, Input, Text} from 'haengdong-design'; import React, {useEffect, useState} from 'react'; import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; +import {ExpenseList, Flex, Input, Text} from '@HDesign/index'; + const MemberReportList = () => { const [name, setName] = useState(''); const {memberReportSearchList, memberReportList} = useSearchMemberReportList({name}); diff --git a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx index 645acb468..93a950084 100644 --- a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx +++ b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx @@ -1,7 +1,5 @@ import type {BillAction} from 'types/serviceType'; -import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; - import validatePurchase from '@utils/validate/validatePurchase'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; @@ -9,6 +7,8 @@ import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberRe import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; +import {BottomSheet, EditableItem, FixedButton, Flex, Text} from '@HDesign/index'; + import { bottomSheetHeaderStyle, bottomSheetStyle, diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx index e3579ab6b..f75969277 100644 --- a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx +++ b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx @@ -1,6 +1,6 @@ import type {MemberReport} from 'types/serviceType'; -import {BottomSheet, FixedButton, Flex, Text} from 'haengdong-design'; +import {BottomSheet, FixedButton, Flex, Text} from '@HDesign/index'; import {bottomSheetStyle} from './MemberListInBillStep.style'; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx index ad6e63f28..a15681e4a 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx @@ -1,12 +1,12 @@ import type {MemberType} from 'types/serviceType'; -import {FixedButton, LabelGroupInput} from 'haengdong-design'; - import validateMemberName from '@utils/validate/validateMemberName'; import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; import useDynamicInput from '@hooks/useDynamicInput'; +import {FixedButton, LabelGroupInput} from '@HDesign/index'; + import style from './AddMemberActionListModalContent.style'; import InMember from './InMember'; import OutMember from './OutMember'; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx index 5f9f9a2e0..44da530fe 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx @@ -1,7 +1,7 @@ -import {LabelGroupInput} from 'haengdong-design'; - import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; +import {LabelGroupInput} from '@HDesign/index'; + interface InMemberProps { dynamicProps: ReturnUseDynamicInput; } diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx index 9294b18ae..2ed739b60 100644 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx @@ -1,8 +1,8 @@ -import {LabelGroupInput, Search} from 'haengdong-design'; - import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; import useSearchInMemberList from '@hooks/useSearchInMemberList'; +import {LabelGroupInput, Search} from '@HDesign/index'; + interface OutMemberProps { dynamicProps: ReturnUseDynamicInput; } diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx index 04242fad1..7d6573193 100644 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx @@ -1,10 +1,10 @@ import type {MemberAction, MemberType} from 'types/serviceType'; -import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from 'haengdong-design'; - import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; import {useToast} from '@hooks/useToast/useToast'; +import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from '@HDesign/index'; + import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; type DeleteMemberActionModalProps = { diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx index de88a7128..95a72c99b 100644 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx @@ -1,6 +1,5 @@ import type {BillAction} from 'types/serviceType'; -import {BottomSheet, EditableItem, FixedButton, Flex, Text} from 'haengdong-design'; import {useEffect} from 'react'; import validatePurchase from '@utils/validate/validatePurchase'; @@ -10,6 +9,8 @@ import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberRe import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; +import {BottomSheet, EditableItem, FixedButton, Flex, Text} from '@HDesign/index'; + import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './PutAndDeltetBillActionModal.style'; type PutAndDeleteBillActionModalProps = { diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx index 862bd91e3..6550175e6 100644 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx +++ b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx @@ -1,7 +1,8 @@ import type {InOutType} from 'types/serviceType'; import {useState} from 'react'; -import {BottomSheet, Switch, Text} from 'haengdong-design'; + +import {BottomSheet, Switch, Text} from '@HDesign/index'; import {AddMemberActionListModalContent} from './AddMemberActionListModalContent'; import style from './SetActionListModal.style'; diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx index 58e86b917..62853f912 100644 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx +++ b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx @@ -1,9 +1,9 @@ -import {BottomSheet, Text, LabelGroupInput, FixedButton, IconButton, Icon} from 'haengdong-design'; - import validateMemberName from '@utils/validate/validateMemberName'; import useSetAllMemberList from '@hooks/useSetAllMemberList'; +import {BottomSheet, Text, LabelGroupInput, FixedButton, IconButton, Icon} from '@HDesign/index'; + import { allMemberListModalLabelGroupInputStyle, allMemberListModalStyle, diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx index f73f2616d..f4f2dc220 100644 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx @@ -1,10 +1,10 @@ -import {Text, BottomSheet, FixedButton, LabelGroupInput} from 'haengdong-design'; - import validateMemberName from '@utils/validate/validateMemberName'; import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; import useDynamicInput from '@hooks/useDynamicInput'; +import {Text, BottomSheet, FixedButton, LabelGroupInput} from '@HDesign/index'; + import { setInitialMemberListModalInputGroupStyle, setInitialMemberListModalStyle, diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx index 7fed9ef5c..ca5f4ee05 100644 --- a/client/src/components/StepList/BillStepItem.tsx +++ b/client/src/components/StepList/BillStepItem.tsx @@ -1,4 +1,3 @@ -import {DragHandleItem, DragHandleItemContainer, EditableItem, Flex, Text} from 'haengdong-design'; import {Fragment, useState} from 'react'; import {useOutletContext} from 'react-router-dom'; @@ -10,6 +9,8 @@ import ExpenseDetailModal from '@components/Modal/ExpenseDetailModal/ExpenseDeta import useSetBillInput from '@hooks/useSetBillInput'; +import {DragHandleItem, DragHandleItemContainer, EditableItem, Flex, Text} from '@HDesign/index'; + interface BillStepItemProps { step: BillStep; isOpenBottomSheet: boolean; diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx index ed3f5bfe7..b0ef25de2 100644 --- a/client/src/components/StepList/MemberStepItem.tsx +++ b/client/src/components/StepList/MemberStepItem.tsx @@ -1,11 +1,12 @@ import type {MemberStep} from 'types/serviceType'; -import {DragHandleItem} from 'haengdong-design'; import {useOutletContext} from 'react-router-dom'; import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMemberActionModal'; import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; +import {DragHandleItem} from '@HDesign/index'; + interface MemberStepItemProps { step: MemberStep; isOpenBottomSheet: boolean; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx index c08f1b7a3..ccdf547f0 100644 --- a/client/src/components/StepList/StepList.tsx +++ b/client/src/components/StepList/StepList.tsx @@ -1,9 +1,10 @@ -import {Flex, Text} from 'haengdong-design'; import {useEffect, useMemo, useState} from 'react'; import {BillStep, MemberStep} from 'types/serviceType'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; +import {Flex, Text} from '@HDesign/index'; + import Step from './Step'; interface StepListProps { diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx index 5bf44d6fb..d688d1395 100644 --- a/client/src/components/Toast/Toast.tsx +++ b/client/src/components/Toast/Toast.tsx @@ -1,6 +1,7 @@ import {createPortal} from 'react-dom'; import {useState, useEffect} from 'react'; -import {Button, Flex, Icon, Text} from 'haengdong-design'; + +import {Button, Flex, Icon, Text} from '@HDesign/index'; import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; import {ToastProps, ToastType} from './Toast.type'; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx index 38836f677..7168070c9 100644 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx +++ b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx @@ -1,7 +1,6 @@ import {renderHook, waitFor} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; import {act} from 'react'; -import {HDesignProvider} from 'haengdong-design'; import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; @@ -9,6 +8,8 @@ import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; import {ToastProvider} from '@hooks/useToast/ToastProvider'; +import {HDesignProvider} from '@HDesign/index'; + import stepListJson from '@mocks/stepList.json'; import invalidMemberStepListJson from '@mocks/invalidMemberStepList.json'; diff --git a/client/src/hooks/useToast/useToast.test.tsx b/client/src/hooks/useToast/useToast.test.tsx index f790ba98e..80fa7d7ab 100644 --- a/client/src/hooks/useToast/useToast.test.tsx +++ b/client/src/hooks/useToast/useToast.test.tsx @@ -1,6 +1,7 @@ import {render, renderHook, screen, waitFor} from '@testing-library/react'; import {act} from 'react'; -import {HDesignProvider} from 'haengdong-design'; + +import {HDesignProvider} from '@HDesign/index'; import {ToastProvider} from './ToastProvider'; // 위 코드에 해당하는 ToastProvider 경로 import {useToast} from './useToast'; diff --git a/client/src/mocks/svgMock.ts b/client/src/mocks/svgMock.ts new file mode 100644 index 000000000..371bb44e1 --- /dev/null +++ b/client/src/mocks/svgMock.ts @@ -0,0 +1,7 @@ +module.exports = { + process() { + return { + code: 'module.exports = "svg-mock";', + }; + }, +}; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 066165d6a..831bb1fd4 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -1,8 +1,9 @@ import {useLocation, useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, Title, TopNav} from 'haengdong-design'; import {RunningDog} from '@components/Common/Logo'; +import {FixedButton, MainLayout, Title, TopNav} from '@HDesign/index'; + import {ROUTER_URLS} from '@constants/routerUrls'; const CompleteCreateEventPage = () => { diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index ad68327d2..73fca320e 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -1,9 +1,10 @@ import {useNavigate} from 'react-router-dom'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; import {css} from '@emotion/react'; import useSetEventNamePage from '@hooks/useSetEventNamePage'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from '@HDesign/index'; + import {ROUTER_URLS} from '@constants/routerUrls'; const SetEventNamePage = () => { diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 14fcdd75b..9f6ba6a49 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -1,7 +1,7 @@ -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from 'haengdong-design'; - import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from '@HDesign/index'; + import RULE from '@constants/rule'; import {PASSWORD_LENGTH} from '@constants/password'; diff --git a/client/src/pages/ErrorPage/ErrorPage.tsx b/client/src/pages/ErrorPage/ErrorPage.tsx index 31ef8c81f..a405112e7 100644 --- a/client/src/pages/ErrorPage/ErrorPage.tsx +++ b/client/src/pages/ErrorPage/ErrorPage.tsx @@ -1,4 +1,4 @@ -import {MainLayout, Title} from 'haengdong-design'; +import {MainLayout, Title} from '@HDesign/index'; const ErrorPage = () => { return ( diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 79deeac7a..855c79058 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,5 +1,4 @@ import {useEffect, useState} from 'react'; -import {Title, FixedButton, ListButton, Button} from 'haengdong-design'; import {useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/StepList'; @@ -9,6 +8,8 @@ import useRequestPostAuthenticate from '@hooks/queries/useRequestPostAuthenticat import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; +import {Title, FixedButton, ListButton, Button} from '@HDesign/index'; + import {EventPageContextProps} from '../EventPageLayout'; import {receiptStyle, titleAndListButtonContainerStyle, buttonGroupStyle} from './AdminPage.style'; diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index 741dca3eb..d099835bc 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,7 +1,7 @@ -import {FixedButton, LabelInput, Title} from 'haengdong-design'; - import useEventLogin from '@hooks/useEventLogin'; +import {FixedButton, LabelInput, Title} from '@HDesign/index'; + import RULE from '@constants/rule'; import {PASSWORD_LENGTH} from '@constants/password'; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 6f00c23f1..e76649f43 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,4 +1,3 @@ -import {MainLayout, TopNav, Switch, Button} from 'haengdong-design'; import {Outlet, useMatch} from 'react-router-dom'; import CopyToClipboard from 'react-copy-to-clipboard'; @@ -7,6 +6,8 @@ import useRequestGetEventName from '@hooks/queries/useRequestGetEventName'; import useNavSwitch from '@hooks/useNavSwitch'; +import {MainLayout, TopNav, Switch, Button} from '@HDesign/index'; + import getEventIdByUrl from '@utils/getEventIdByUrl'; import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 72fc77cb9..0521d386b 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -1,4 +1,3 @@ -import {Tab, Tabs, Title} from 'haengdong-design'; import {useOutletContext} from 'react-router-dom'; import MemberReportList from '@components/MemberReportList/MemberReportList'; @@ -6,6 +5,8 @@ import StepList from '@components/StepList/StepList'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; +import {Tab, Tabs, Title} from '@HDesign/index'; + import {EventPageContextProps} from '../EventPageLayout'; const HomePage = () => { diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index d3a1cd079..16d710e35 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -1,4 +1,4 @@ -import {MainLayout} from 'haengdong-design'; +import {MainLayout} from '@HDesign/index'; import Nav from './Nav/Nav'; import MainSection from './Section/MainSection'; diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index ec4d745c9..5fd1ba3f8 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -1,8 +1,9 @@ -import {Button, Flex, Text} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; import Heundeut from '@assets/image/heundeut.svg'; +import {Button, Flex, Text} from '@HDesign/index'; + import {ROUTER_URLS} from '@constants/routerUrls'; import {logoStyle, navStyle} from './Nav.style'; diff --git a/client/src/pages/MainPage/Section/AddBillSection.tsx b/client/src/pages/MainPage/Section/AddBillSection.tsx index ecf7dd90d..ca2fe1f34 100644 --- a/client/src/pages/MainPage/Section/AddBillSection.tsx +++ b/client/src/pages/MainPage/Section/AddBillSection.tsx @@ -1,8 +1,9 @@ import {css} from '@emotion/react'; -import {Text} from 'haengdong-design'; import AddBillMockup from '@assets/image/addBillMockup.svg'; +import {Text} from '@HDesign/index'; + const AddBillSection = () => { return ( <div diff --git a/client/src/pages/MainPage/Section/AddMemberSection.tsx b/client/src/pages/MainPage/Section/AddMemberSection.tsx index ae6e7d1fc..a7ff92539 100644 --- a/client/src/pages/MainPage/Section/AddMemberSection.tsx +++ b/client/src/pages/MainPage/Section/AddMemberSection.tsx @@ -1,9 +1,10 @@ import {css} from '@emotion/react'; -import {Text} from 'haengdong-design'; -import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; import AddMemberMockup from '@assets/image/addMemberMockup.svg'; +import {Text} from '@HDesign/index'; +import {useTheme} from '@HDesign/index'; + const AddMemberSection = () => { const {theme} = useTheme(); return ( diff --git a/client/src/pages/MainPage/Section/DescriptionSection.tsx b/client/src/pages/MainPage/Section/DescriptionSection.tsx index 193cfe465..f53e88cf9 100644 --- a/client/src/pages/MainPage/Section/DescriptionSection.tsx +++ b/client/src/pages/MainPage/Section/DescriptionSection.tsx @@ -1,6 +1,6 @@ import {css} from '@emotion/react'; -import {Text} from 'haengdong-design'; -import {useTheme} from 'haengdong-design/dist/theme/HDesignProvider'; + +import {Text, useTheme} from '@HDesign/index'; const DescriptionSection = () => { const {theme} = useTheme(); diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx index 4bbeb7340..16bc67128 100644 --- a/client/src/pages/MainPage/Section/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -1,10 +1,11 @@ import {css, keyframes} from '@emotion/react'; -import {Button, Text} from 'haengdong-design'; import {useNavigate} from 'react-router-dom'; import {StandingDog} from '@components/Common/Logo'; import ChevronDown from '@assets/image/chevronDownLarge.svg'; +import {Button, Text} from '@HDesign/index'; + import {ROUTER_URLS} from '@constants/routerUrls'; const MainSection = () => { diff --git a/client/src/pages/MainPage/Section/MemberReportSection.tsx b/client/src/pages/MainPage/Section/MemberReportSection.tsx index 69871e1c9..6e51ae2b1 100644 --- a/client/src/pages/MainPage/Section/MemberReportSection.tsx +++ b/client/src/pages/MainPage/Section/MemberReportSection.tsx @@ -1,8 +1,9 @@ import {css} from '@emotion/react'; -import {Text} from 'haengdong-design'; import MemberReportMockup from '@assets/image/memberReportMockup.svg'; +import {Text} from '@HDesign/index'; + const MemberReportSection = () => { return ( <div diff --git a/client/tsconfig.json b/client/tsconfig.json index 84c7c054a..f68912ec3 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -44,7 +44,15 @@ "@mocks/*": ["mocks/*"], "@pages/*": ["pages/*"], "@utils/*": ["utils/*"], - "@errors/*": ["errors/*"] + "@errors/*": ["errors/*"], + + "@HDesign/*": ["components/Design/*"], + "@HDcomponents/*": ["components/Design/components/*"], + "@token/*": ["components/Design/token/*"], + "@layouts/*": ["components/Design/layouts/*"], + "@type/*": ["components/Design/type/*"], + "@theme/*": ["components/Design/theme/*"], + "@HDutils/*": ["components/Design/utils/*"] }, "outDir": "./dist" }, diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs index 160baf0ca..8b34ef1c4 100644 --- a/client/webpack.common.mjs +++ b/client/webpack.common.mjs @@ -22,6 +22,13 @@ export default { '@pages': path.resolve(__dirname, 'src/pages/'), '@utils': path.resolve(__dirname, 'src/utils/'), '@errors': path.resolve(__dirname, 'src/errors/'), + '@HDesign': path.resolve(__dirname, 'src/components/Design/'), + '@HDcomponents': path.resolve(__dirname, 'src/components/Design/components/'), + '@HDutils': path.resolve(__dirname, 'src/components/Design/utils/'), + '@token': path.resolve(__dirname, 'src/components/Design/token/'), + '@theme': path.resolve(__dirname, 'src/components/Design/theme/'), + '@layouts': path.resolve(__dirname, 'src/components/Design/layouts/'), + '@type': path.resolve(__dirname, 'src/components/Design/type/'), }, }, module: { diff --git a/server/.gitignore b/server/.gitignore deleted file mode 100644 index 671ee930b..000000000 --- a/server/.gitignore +++ /dev/null @@ -1,244 +0,0 @@ -# Created by https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux -# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij,gradle,macos,windows,linux - -### Intellij ### -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Intellij Patch ### -# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 - -# *.iml -# modules.xml -# .idea/misc.xml -# *.ipr - -# Sonarlint plugin -# https://plugins.jetbrains.com/plugin/7973-sonarlint -.idea/**/sonarlint/ - -# SonarQube Plugin -# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin -.idea/**/sonarIssues.xml - -# Markdown Navigator plugin -# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced -.idea/**/markdown-navigator.xml -.idea/**/markdown-navigator-enh.xml -.idea/**/markdown-navigator/ - -# Cache file creation bug -# See https://youtrack.jetbrains.com/issue/JBR-2257 -.idea/$CACHE_FILE$ - -# CodeStream plugin -# https://plugins.jetbrains.com/plugin/12206-codestream -.idea/codestream.xml - -# Azure Toolkit for IntelliJ plugin -# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij -.idea/**/azureSettings.xml - -### Java ### -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* - -### Linux ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### macOS Patch ### -# iCloud generated files -*.icloud - -### Windows ### -# Windows thumbnail cache files -Thumbs.db -Thumbs.db:encryptable -ehthumbs.db -ehthumbs_vista.db - -# Dump file -*.stackdump - -# Folder config file -[Dd]esktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msix -*.msm -*.msp - -# Windows shortcuts -*.lnk - -### Gradle ### -.gradle -**/build/ -!src/**/build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Avoid ignore Gradle wrappper properties -!gradle-wrapper.properties - -# Cache of project -.gradletasknamecache - -# Eclipse Gradle plugin generated files -# Eclipse Core -.project -# JDT-specific (Eclipse Java Development Tools) -.classpath - -### Gradle Patch ### -# Java heap dump -*.hprof - -# End of https://www.toptal.com/developers/gitignore/api/java,intellij,gradle,macos,windows,linux diff --git a/server/Dockerfile b/server/Dockerfile deleted file mode 100644 index df2cf44e0..000000000 --- a/server/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM openjdk:17-jdk-slim - -WORKDIR /app - -COPY /build/libs/*.jar /app/haengdong-0.0.1-SNAPSHOT.jar - -EXPOSE 8080 -ENTRYPOINT ["java"] -CMD ["-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "-Duser.timezone=Asia/Seoul", "-jar", "haengdong-0.0.1-SNAPSHOT.jar"] diff --git a/server/build.gradle b/server/build.gradle deleted file mode 100644 index 4229de130..000000000 --- a/server/build.gradle +++ /dev/null @@ -1,86 +0,0 @@ -plugins { - id 'java' - id 'org.springframework.boot' version '3.3.1' - id 'io.spring.dependency-management' version '1.1.5' - id 'org.asciidoctor.jvm.convert' version '3.3.2' -} - -group = 'server' -version = '0.0.1-SNAPSHOT' - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -configurations { - compileOnly { - extendsFrom annotationProcessor - } - asciidoctorExt -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - - implementation 'io.jsonwebtoken:jjwt:0.9.1' - implementation 'javax.xml.bind:jaxb-api:2.3.1' - - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' - - runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.mysql:mysql-connector-j' - - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - - asciidoctorExt 'org.springframework.restdocs:spring-restdocs-asciidoctor' - testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc' -} - -ext { - snippetsDir = file('build/generated-snippets') -} - -test { - useJUnitPlatform() - outputs.dir snippetsDir -} - -asciidoctor { - inputs.dir snippetsDir - configurations 'asciidoctorExt' - baseDirFollowsSourceFile() - dependsOn test -} - -tasks.resolveMainClassName { - dependsOn 'copyApiDocuments' -} - -tasks.register('copyApiDocuments', Copy) { - dependsOn asciidoctor - from file("build/docs/asciidoc") - into file("build/resources/main/static/docs") -} - -bootJar { - dependsOn copyApiDocuments -} - -jar { - enabled = false -} - -build { - dependsOn copyApiDocuments -} diff --git a/server/docs/24-08-04-erd.sql b/server/docs/24-08-04-erd.sql deleted file mode 100644 index ae2fbc4a5..000000000 --- a/server/docs/24-08-04-erd.sql +++ /dev/null @@ -1,65 +0,0 @@ --- Create tables -CREATE TABLE action -( - event_id BIGINT, - id BIGINT AUTO_INCREMENT, - sequence BIGINT, - PRIMARY KEY (id) -); - -CREATE TABLE bill_action -( - action_id BIGINT UNIQUE, - id BIGINT AUTO_INCREMENT, - price BIGINT, - title VARCHAR(30), - PRIMARY KEY (id) -); - -CREATE TABLE event -( - id BIGINT AUTO_INCREMENT, - name VARCHAR(255), - token VARCHAR(255), - PRIMARY KEY (id) -); - -CREATE TABLE event_step -( - event_id BIGINT, - id BIGINT AUTO_INCREMENT, - sequence BIGINT, - name VARCHAR(255), - PRIMARY KEY (id) -); - -CREATE TABLE member_action -( - action_id BIGINT UNIQUE, - id BIGINT AUTO_INCREMENT, - member_group_id BIGINT, - member_name VARCHAR(255), - status ENUM('IN', 'OUT'), - PRIMARY KEY (id) -); - --- Add foreign key constraints -ALTER TABLE action - ADD CONSTRAINT FKgf0qmub9va1xbe44nehny31yw - FOREIGN KEY (event_id) - REFERENCES event (id); - -ALTER TABLE bill_action - ADD CONSTRAINT FK54tx517tp0ry6453olkply4us - FOREIGN KEY (action_id) - REFERENCES action (id); - -ALTER TABLE event_step - ADD CONSTRAINT FKe3rkib91cvl0x5w9wqkshmn81 - FOREIGN KEY (event_id) - REFERENCES event (id); - -ALTER TABLE member_action - ADD CONSTRAINT FK5jna51dn8fs2ir52l4uwn517u - FOREIGN KEY (action_id) - REFERENCES action (id); diff --git a/server/docs/24-08-04-erd.svg b/server/docs/24-08-04-erd.svg deleted file mode 100644 index 5a4bac225..000000000 --- a/server/docs/24-08-04-erd.svg +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Do not edit this file with editors other than draw.io --> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1993px" height="1581px" viewBox="-0.5 -0.5 1993 1581" content="<mxfile host="app.diagrams.net" modified="2024-07-25T04:17:06.208Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" etag="gR5VLfYLO6MRu5dHcV28" version="24.7.3" type="github"> <diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1"> <mxGraphModel dx="2380" dy="2150" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> <root> <mxCell id="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="8gZzuRhjrYuwNxX9kY4q-98" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-442" y="-590" width="1992" height="1580" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-47" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=ERone;startFill=0;endArrow=ERzeroToMany;endFill=0;dashed=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-0" target="8gZzuRhjrYuwNxX9kY4q-37" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=ERone;startFill=0;endArrow=ERzeroToMany;endFill=0;dashed=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-0" target="8gZzuRhjrYuwNxX9kY4q-56" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-0" value="Event" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="40" y="40" width="280" height="120" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-1" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-2" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-3" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-137" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-1" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-7" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-8" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-9" value="token" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-138" value="varchar(20)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-7" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-4" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-0" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-5" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-6" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-139" value="varchar(255)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-4" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-37" value="Event_Step" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="40" y="240" width="280" height="150" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-38" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-39" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-40" value="event_step_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-143" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-38" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-41" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-42" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-43" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-144" value="varchar(30)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-41" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-44" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-45" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-46" value="sequence" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-145" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-44" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-48" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-37" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-49" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-50" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-146" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-48" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-77" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;startArrow=ERone;startFill=0;endArrow=ERone;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-56" target="8gZzuRhjrYuwNxX9kY4q-67" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-91" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;dashed=1;startArrow=ERone;startFill=0;endArrow=ERone;endFill=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="8gZzuRhjrYuwNxX9kY4q-56" target="8gZzuRhjrYuwNxX9kY4q-81" edge="1"> <mxGeometry relative="1" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-56" value="Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="414" y="40" width="280" height="120" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-57" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-58" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-59" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-140" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-57" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-60" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-61" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-62" value="sequence" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-141" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-60" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-63" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-56" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-64" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-65" value="event_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-142" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-63" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-67" value="Bill_Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="414" y="240" width="280" height="150" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-68" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-69" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-70" value="bill_action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-147" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-68" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-71" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-72" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-73" value="title" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-148" value="varchar(30)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-71" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-78" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-79" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-80" value="price" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-149" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-78" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-74" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-67" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-75" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-76" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-150" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-74" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-81" value="Member_Action" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="790" y="40" width="280" height="180" as="geometry"> <mxRectangle x="480" y="530" width="70" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-82" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="30" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-83" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-84" value="member_action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-151" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-82" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-85" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="60" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-86" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-87" value="member_name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-152" value="varchar(20)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-85" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-92" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="90" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-93" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-94" value="status" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-153" value="varchar(10)" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-92" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-95" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="120" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-96" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-97" value="member_group_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-154" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-95" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-88" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="8gZzuRhjrYuwNxX9kY4q-81" vertex="1"> <mxGeometry y="150" width="280" height="30" as="geometry" /> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-89" value="FK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry width="30" height="30" as="geometry"> <mxRectangle width="30" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-90" value="action_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry x="30" width="120" height="30" as="geometry"> <mxRectangle width="120" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> <mxCell id="8gZzuRhjrYuwNxX9kY4q-155" value="bigint" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="8gZzuRhjrYuwNxX9kY4q-88" vertex="1"> <mxGeometry x="150" width="130" height="30" as="geometry"> <mxRectangle width="130" height="30" as="alternateBounds" /> </mxGeometry> </mxCell> </root> </mxGraphModel> </diagram> </mxfile> " resource="https://app.diagrams.net/?src=about#Hkunsanglee%2Fcafekiosk-study%2Fmain%2Fsrc%2Fmain%2Fresources%2Fexample2.svg#%7B%22pageId%22%3A%22C5RBs43oDa-KdzZeNtuy%22%7D"><defs/><g><g data-cell-id="WIyWlLk6GJQsqaUBKTNV-0"><g data-cell-id="WIyWlLk6GJQsqaUBKTNV-1"><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-98"><g><rect x="0" y="0" width="1992" height="1580" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-47"><g><path d="M 622 750 L 622 814.5" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 626 754 L 618 754" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="622" cy="818" rx="3" ry="3" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 626 830 L 622 822 L 618 830 M 622 822 L 622 830" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-66"><g><path d="M 762 690 L 840.5 690" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 766 686 L 766 694" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="844" cy="690" rx="3" ry="3" fill="none" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 856 686 L 848 690 L 856 694 M 848 690 L 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-0"><g><path d="M 482 660 L 482 630 L 762 630 L 762 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 482 660 L 482 750 L 762 750 L 762 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 482 660 L 762 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 512 660 L 512 690 L 512 720 L 512 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 632 660 L 632 690 L 632 720 L 632 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 622px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Event</div></div></div></foreignObject><text x="622" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Event</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-1"><g><path d="M 482 660 M 762 660 M 762 690 L 482 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-2"><g><rect x="482" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 660 M 512 660 M 512 690 M 482 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="497" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-3"><g><rect x="512" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 660 M 632 660 M 632 690 M 512 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="520" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-137"><g><rect x="632" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 660 M 762 660 M 762 690 M 632 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-7"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-8"><g><rect x="482" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 690 M 512 690 M 512 720 M 482 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-9"><g><rect x="512" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 690 M 632 690 M 632 720 M 512 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">token</div></div></div></foreignObject><text x="520" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">token</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-138"><g><rect x="632" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 690 M 762 690 M 762 720 M 632 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(20)</div></div></div></foreignObject><text x="640" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(20)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-4"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-5"><g><rect x="482" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 720 M 512 720 M 512 750 M 482 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-6"><g><rect x="512" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 720 M 632 720 M 632 750 M 512 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">name</div></div></div></foreignObject><text x="520" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-139"><g><rect x="632" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 720 M 762 720 M 762 750 M 632 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(255)</div></div></div></foreignObject><text x="640" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(255)</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-37"><g><path d="M 482 860 L 482 830 L 762 830 L 762 860" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 482 860 L 482 980 L 762 980 L 762 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 482 860 L 762 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 512 860 L 512 890 L 512 920 L 512 950 L 512 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 632 860 L 632 890 L 632 920 L 632 950 L 632 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 845px; margin-left: 622px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Event_Step</div></div></div></foreignObject><text x="622" y="849" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Event_Step</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-38"><g><path d="M 482 860 M 762 860 M 762 890 L 482 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-39"><g><rect x="482" y="860" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 860 M 512 860 M 512 890 M 482 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 875px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="497" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-40"><g><rect x="512" y="860" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 860 M 632 860 M 632 890 M 512 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 875px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">event_step_id</div></div></div></foreignObject><text x="520" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">event_step_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-143"><g><rect x="632" y="860" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 860 M 762 860 M 762 890 M 632 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 875px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-41"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-42"><g><rect x="482" y="890" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 890 M 512 890 M 512 920 M 482 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-43"><g><rect x="512" y="890" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 890 M 632 890 M 632 920 M 512 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 905px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">name</div></div></div></foreignObject><text x="520" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-144"><g><rect x="632" y="890" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 890 M 762 890 M 762 920 M 632 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 905px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(30)</div></div></div></foreignObject><text x="640" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(30)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-44"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-45"><g><rect x="482" y="920" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 920 M 512 920 M 512 950 M 482 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-46"><g><rect x="512" y="920" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 920 M 632 920 M 632 950 M 512 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 935px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">sequence</div></div></div></foreignObject><text x="520" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">sequence</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-145"><g><rect x="632" y="920" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 920 M 762 920 M 762 950 M 632 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 935px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-48"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-49"><g><rect x="482" y="950" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 482 950 M 512 950 M 512 980 M 482 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 965px; margin-left: 483px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="497" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-50"><g><rect x="512" y="950" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 512 950 M 632 950 M 632 980 M 512 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 965px; margin-left: 520px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="520" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-146"><g><rect x="632" y="950" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 632 950 M 762 950 M 762 980 M 632 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 965px; margin-left: 640px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="640" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-77"><g><path d="M 996 750 L 996 830" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 1000 754 L 992 754" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 992 826 L 1000 826" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-91"><g><path d="M 1136 690 L 1184 690 L 1184 720 L 1232 720" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 1140 686 L 1140 694" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1228 724 L 1228 716" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-56"><g><path d="M 856 660 L 856 630 L 1136 630 L 1136 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 856 660 L 856 750 L 1136 750 L 1136 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 856 660 L 1136 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 886 660 L 886 690 L 886 720 L 886 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1006 660 L 1006 690 L 1006 720 L 1006 750" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 996px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Action</div></div></div></foreignObject><text x="996" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-57"><g><path d="M 856 660 M 1136 660 M 1136 690 L 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-58"><g><rect x="856" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 660 M 886 660 M 886 690 M 856 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="871" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-59"><g><rect x="886" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 660 M 1006 660 M 1006 690 M 886 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="894" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-140"><g><rect x="1006" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 660 M 1136 660 M 1136 690 M 1006 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-60"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-61"><g><rect x="856" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 690 M 886 690 M 886 720 M 856 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-62"><g><rect x="886" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 690 M 1006 690 M 1006 720 M 886 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">sequence</div></div></div></foreignObject><text x="894" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">sequence</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-141"><g><rect x="1006" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 690 M 1136 690 M 1136 720 M 1006 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-63"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-64"><g><rect x="856" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 720 M 886 720 M 886 750 M 856 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 735px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="871" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-65"><g><rect x="886" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 720 M 1006 720 M 1006 750 M 886 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">event_id</div></div></div></foreignObject><text x="894" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">event_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-142"><g><rect x="1006" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 720 M 1136 720 M 1136 750 M 1006 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-67"><g><path d="M 856 860 L 856 830 L 1136 830 L 1136 860" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 856 860 L 856 980 L 1136 980 L 1136 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 856 860 L 1136 860" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 886 860 L 886 890 L 886 920 L 886 950 L 886 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1006 860 L 1006 890 L 1006 920 L 1006 950 L 1006 980" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 845px; margin-left: 996px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Bill_Action</div></div></div></foreignObject><text x="996" y="849" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Bill_Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-68"><g><path d="M 856 860 M 1136 860 M 1136 890 L 856 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-69"><g><rect x="856" y="860" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 860 M 886 860 M 886 890 M 856 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 875px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="871" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-70"><g><rect x="886" y="860" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 860 M 1006 860 M 1006 890 M 886 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 875px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bill_action_id</div></div></div></foreignObject><text x="894" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bill_action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-147"><g><rect x="1006" y="860" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 860 M 1136 860 M 1136 890 M 1006 890" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 875px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="879" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-71"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-72"><g><rect x="856" y="890" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 890 M 886 890 M 886 920 M 856 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-73"><g><rect x="886" y="890" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 890 M 1006 890 M 1006 920 M 886 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 905px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">title</div></div></div></foreignObject><text x="894" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">title</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-148"><g><rect x="1006" y="890" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 890 M 1136 890 M 1136 920 M 1006 920" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 905px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(30)</div></div></div></foreignObject><text x="1014" y="909" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(30)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-78"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-79"><g><rect x="856" y="920" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 920 M 886 920 M 886 950 M 856 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-80"><g><rect x="886" y="920" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 920 M 1006 920 M 1006 950 M 886 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 935px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">price</div></div></div></foreignObject><text x="894" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">price</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-149"><g><rect x="1006" y="920" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 920 M 1136 920 M 1136 950 M 1006 950" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 935px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="939" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-74"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-75"><g><rect x="856" y="950" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 856 950 M 886 950 M 886 980 M 856 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 965px; margin-left: 857px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="871" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-76"><g><rect x="886" y="950" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 886 950 M 1006 950 M 1006 980 M 886 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 965px; margin-left: 894px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="894" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-150"><g><rect x="1006" y="950" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1006 950 M 1136 950 M 1136 980 M 1006 980" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 965px; margin-left: 1014px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1014" y="969" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-81"><g><path d="M 1232 660 L 1232 630 L 1512 630 L 1512 660" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 1232 660 L 1232 810 L 1512 810 L 1512 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1232 660 L 1512 660" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1262 660 L 1262 690 L 1262 720 L 1262 750 L 1262 780 L 1262 810" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/><path d="M 1382 660 L 1382 690 L 1382 720 L 1382 750 L 1382 780 L 1382 810" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="none"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 645px; margin-left: 1372px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Member_Action</div></div></div></foreignObject><text x="1372" y="649" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">Member_Action</text></switch></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-82"><g><path d="M 1232 660 M 1512 660 M 1512 690 L 1232 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="none"/></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-83"><g><rect x="1232" y="660" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 660 M 1262 660 M 1262 690 M 1232 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 675px; margin-left: 1233px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; overflow-wrap: normal;">PK</div></div></div></foreignObject><text x="1247" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle" font-weight="bold">PK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-84"><g><rect x="1262" y="660" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 660 M 1382 660 M 1382 690 M 1262 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 675px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">member_action_id</div></div></div></foreignObject><text x="1270" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">member_action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-151"><g><rect x="1382" y="660" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 660 M 1512 660 M 1512 690 M 1382 690" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 675px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; text-decoration: underline; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="679" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" font-weight="bold" text-decoration="underline">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-85"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-86"><g><rect x="1232" y="690" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 690 M 1262 690 M 1262 720 M 1232 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-87"><g><rect x="1262" y="690" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 690 M 1382 690 M 1382 720 M 1262 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 705px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">member_name</div></div></div></foreignObject><text x="1270" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">member_name</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-152"><g><rect x="1382" y="690" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 690 M 1512 690 M 1512 720 M 1382 720" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 705px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(20)</div></div></div></foreignObject><text x="1390" y="709" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(20)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-92"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-93"><g><rect x="1232" y="720" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 720 M 1262 720 M 1262 750 M 1232 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-94"><g><rect x="1262" y="720" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 720 M 1382 720 M 1382 750 M 1262 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 735px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">status</div></div></div></foreignObject><text x="1270" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">status</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-153"><g><rect x="1382" y="720" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 720 M 1512 720 M 1512 750 M 1382 750" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 735px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">varchar(10)</div></div></div></foreignObject><text x="1390" y="739" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">varchar(10)</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-95"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-96"><g><rect x="1232" y="750" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 750 M 1262 750 M 1262 780 M 1232 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-97"><g><rect x="1262" y="750" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 750 M 1382 750 M 1382 780 M 1262 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 765px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">member_group_id</div></div></div></foreignObject><text x="1270" y="769" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">member_group_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-154"><g><rect x="1382" y="750" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 750 M 1512 750 M 1512 780 M 1382 780" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 765px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="769" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-88"><g/><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-89"><g><rect x="1232" y="780" width="30" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1232 780 M 1262 780 M 1262 810 M 1232 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 28px; height: 1px; padding-top: 795px; margin-left: 1233px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">FK</div></div></div></foreignObject><text x="1247" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px" text-anchor="middle">FK</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-90"><g><rect x="1262" y="780" width="120" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1262 780 M 1382 780 M 1382 810 M 1262 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 112px; height: 1px; padding-top: 795px; margin-left: 1270px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">action_id</div></div></div></foreignObject><text x="1270" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">action_id</text></switch></g></g></g><g data-cell-id="8gZzuRhjrYuwNxX9kY4q-155"><g><rect x="1382" y="780" width="130" height="30" fill="none" stroke="none" pointer-events="all"/><path d="M 1382 780 M 1512 780 M 1512 810 M 1382 810" fill="none" stroke="rgb(0, 0, 0)" stroke-linecap="square" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 122px; height: 1px; padding-top: 795px; margin-left: 1390px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: left; max-height: 26px; overflow: hidden;"><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bigint</div></div></div></foreignObject><text x="1390" y="799" fill="rgb(0, 0, 0)" font-family=""Helvetica"" font-size="12px">bigint</text></switch></g></g></g></g></g></g></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.drawio.com/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg> \ No newline at end of file diff --git a/server/gradle/wrapper/gradle-wrapper.jar b/server/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index e6441136f3d4ba8a0da8d277868979cfbc8ad796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43453 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 UfUyy3EX0IC28@JalTrWuAK7&_a{vGU diff --git a/server/gradle/wrapper/gradle-wrapper.properties b/server/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index a4413138c..000000000 --- a/server/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/server/gradlew b/server/gradlew deleted file mode 100644 index b740cf133..000000000 --- a/server/gradlew +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/server/gradlew.bat b/server/gradlew.bat deleted file mode 100644 index 25da30dbd..000000000 --- a/server/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/server/settings.gradle b/server/settings.gradle deleted file mode 100644 index dbbee46fb..000000000 --- a/server/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'haengdong' diff --git a/server/src/docs/asciidoc/billAction.adoc b/server/src/docs/asciidoc/billAction.adoc deleted file mode 100644 index dfd7e26db..000000000 --- a/server/src/docs/asciidoc/billAction.adoc +++ /dev/null @@ -1,121 +0,0 @@ -== 지출 액션 - -=== 지출 액션 생성 - -operation::createBillActions[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"REQUEST_EMPTY", - "message":"지출 금액은 비어 있으면 안됩니다." - }, - { - "code":"REQUEST_EMPTY", - "message":"지출 내역은 비어 있으면 안됩니다." - }, - { - "code":"BILL_ACTION_TITLE_INVALID", - "message":"앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다." - }, - { - "code":"BILL_ACTION_PRICE_INVALID", - "message":"지출 금액은 10,000,000 이하의 자연수여야 합니다." - }, - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 지출 액션 수정 - -operation::updateBillAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"REQUEST_EMPTY", - "message":"지출 내역 제목은 공백일 수 없습니다." - }, - { - "code":"REQUEST_EMPTY", - "message":"지출 금액은 공백일 수 없습니다." - }, - { - "code":"BILL_ACTION_TITLE_INVALID", - "message":"앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다." - }, - { - "code":"BILL_ACTION_PRICE_INVALID", - "message":"지출 금액은 %,d 이하의 자연수여야 합니다." - }, - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"BILL_ACTION_NOT_FOUND", - "message":"존재하지 않는 지출 액션입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 지출 액션 삭제 - -operation::deleteBillAction[snippets="path-parameters,http-request,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- diff --git a/server/src/docs/asciidoc/billActionDetail.adoc b/server/src/docs/asciidoc/billActionDetail.adoc deleted file mode 100644 index a8f19f21b..000000000 --- a/server/src/docs/asciidoc/billActionDetail.adoc +++ /dev/null @@ -1,93 +0,0 @@ -== 지출 상세 - -=== 지출 상세 조회 - -operation::findBillActionDetailsTest[snippets="path-parameters,http-request,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code": "EVENT_NOT_FOUND", - "message": "존재하지 않는 행사입니다." - }, - { - "code": "BILL_ACTION_NOT_FOUND", - "message": "존재하지 않는 지출 액션입니다." - }, - { - "code": "BILL_ACTION_DETAIL_NOT_FOUND", - "message": "존재하지 않는 참여자 지출입니다." - }, - { - "code": "TOKEN_NOT_FOUND", - "message": "토큰이 존재하지 않습니다." - }, - { - "code": "TOKEN_EXPIRED", - "message": "만료된 토큰입니다." - }, - { - "code": "TOKEN_INVALID", - "message": "유효하지 않은 토큰입니다." - }, - { - "code": "FORBIDDEN", - "message": "접근할 수 없는 행사입니다." - } -] ----- - -=== 지출 상세 수정 - -operation::updateBillActionDetailsTest[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code": "REQUEST_EMPTY", - "message": "멤버 이름은 공백일 수 없습니다." - }, - { - "code": "REQUEST_EMPTY", - "message": "지출 금액은 공백일 수 없습니다." - }, - { - "code": "EVENT_NOT_FOUND", - "message": "존재하지 않는 행사입니다." - }, - { - "code": "BILL_ACTION_NOT_FOUND", - "message": "존재하지 않는 지출 액션입니다." - }, - { - "code": "BILL_ACTION_DETAIL_NOT_FOUND", - "message": "존재하지 않는 참여자 지출입니다." - }, - { - "code": "BILL_ACTION_PRICE_NOT_MATCHED", - "message": "지출 총액이 일치하지 않습니다." - }, - { - "code": "TOKEN_NOT_FOUND", - "message": "토큰이 존재하지 않습니다." - }, - { - "code": "TOKEN_EXPIRED", - "message": "만료된 토큰입니다." - }, - { - "code": "TOKEN_INVALID", - "message": "유효하지 않은 토큰입니다." - }, - { - "code": "FORBIDDEN", - "message": "접근할 수 없는 행사입니다." - } -] ----- diff --git a/server/src/docs/asciidoc/event.adoc b/server/src/docs/asciidoc/event.adoc deleted file mode 100644 index 72511b91b..000000000 --- a/server/src/docs/asciidoc/event.adoc +++ /dev/null @@ -1,205 +0,0 @@ -== 행사 - -=== 행사 생성 - -operation::createEvent[snippets="http-request,request-body,request-fields,response-body,response-fields,http-response,response-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"REQUEST_EMPTY", - "message":"행사 이름은 공백일 수 없습니다." - }, - { - "code":"EVENT_NAME_LENGTH_INVALID", - "message":"행사 이름은 2자 이상 30자 이하만 입력 가능합니다. 입력한 이름 길이 : 21" - }, - { - "code":"EVENT_NAME_MULTIPLE_BLANK", - "message":"행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : 공백 문자" - }, - { - "code":"EVENT_PASSWORD_INVALID", - "message":"비밀번호는 4자리 숫자만 가능합니다." - } -] ----- - -=== 행사 관리자 로그인 - -operation::eventLogin[snippets="path-parameters,http-request,request-body,request-fields,http-response,response-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"REQUEST_EMPTY", - "message":"비밀번호는 공백일 수 없습니다." - }, - { - "code":"PASSWORD_INVALID", - "message":"비밀번호가 일치하지 않습니다." - } -] ----- - -=== 행사 정보 조회 - -operation::getEvent[snippets="path-parameters,http-request,response-body,response-fields,http-response"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- - -=== 행사 전체 참여자 목록 조회 - -operation::findAllEventMember[snippets="path-parameters,http-request,response-body,response-fields,http-response,response-fields"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- - -=== 행사 전체 액션 이력 조회 - -operation::findActions[snippets="path-parameters,http-request,http-response,response-fields"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- - -=== 행사 참여자 이름 변경 - -operation::updateEventMemberName[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - - { - "code":"MEMBER_NAME_CHANGE_DUPLICATE", - "message":"중복된 참여 인원 이름 변경 요청이 존재합니다." - }, - { - "code":"MEMBER_NOT_EXIST", - "message":"현재 참여하고 있지 않는 인원이 존재합니다." - }, - { - "code":"REQUEST_EMPTY", - "message":"멤버 이름은 공백일 수 없습니다." - }, - { - "code":"MEMBER_NAME_LENGTH_INVALID", - "message":"멤버 이름은 1자 이상 4자 이하만 입력 가능합니다." - }, - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"MEMBER_NAME_DUPLICATE", - "message":"중복된 행사 참여 인원 이름이 존재합니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"만료된 토큰입니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 행사 참여자 삭제 (특정 참여자의 모든 참여자 액션 삭제) - -operation::deleteAllMemberActionByName[snippets="path-parameters,http-request,http-response,request-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 행사 어드민 권한 확인 - -operation::authenticateEvent[snippets="http-request,http-response,request-cookies"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code": "EVENT_NOT_FOUND", - "message": "존재하지 않는 행사입니다." - }, - { - "code": "TOKEN_NOT_FOUND", - "message": "토큰이 존재하지 않습니다." - }, - { - "code": "TOKEN_EXPIRED", - "message": "만료된 토큰입니다." - }, - { - "code": "TOKEN_INVALID", - "message": "유효하지 않은 토큰입니다." - }, - { - "code": "FORBIDDEN", - "message": "접근할 수 없는 행사입니다." - } -] ----- diff --git a/server/src/docs/asciidoc/index.adoc b/server/src/docs/asciidoc/index.adoc deleted file mode 100644 index 8e1bcd2d0..000000000 --- a/server/src/docs/asciidoc/index.adoc +++ /dev/null @@ -1,15 +0,0 @@ -ifndef::snippets[] -:snippets: ../../build/generated-snippets -endif::[] -= 행동대장 -:source-highlighter: highlightjs :hardbreaks: -:toc: left :doctype: book :icons: font :toc-title: 전체 API 목록 :toclevels: 2 :sectlinks: -:sectnums: -:sectnumlevels: 2 - - -include::{docdir}/event.adoc[] -include::{docdir}/memberBillReport.adoc[] -include::{docdir}/memberAction.adoc[] -include::{docdir}/billAction.adoc[] -include::{docdir}/billActionDetail.adoc[] diff --git a/server/src/docs/asciidoc/memberAction.adoc b/server/src/docs/asciidoc/memberAction.adoc deleted file mode 100644 index 897102c8d..000000000 --- a/server/src/docs/asciidoc/memberAction.adoc +++ /dev/null @@ -1,100 +0,0 @@ -== 참여자 액션 - -=== 참여자 액션 생성 - -operation::createMemberAction[snippets="path-parameters,http-request,request-body,request-fields,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"REQUEST_EMPTY", - "message":"멤버 액션은 공백일 수 없습니다." - }, - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"MEMBER_ACTION_STATUS_INVALID", - "message":"멤버 액션은 IN, OUT만 가능합니다. 입력한 멤버 액션: I_N" - }, - { - "code":"MEMBER_ALREADY_EXIST", - "message":"현재 참여하고 있는 인원이 존재합니다." - }, - { - "code":"MEMBER_NOT_EXIST", - "message":"현재 참여하고 있지 않는 인원이 존재합니다." - }, - { - "code":"MEMBER_NAME_DUPLICATE", - "message":"중복된 이름이 존재합니다. 입력된 이름: 이상, 이상, 감자, 백호" - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- - -=== 현재 행사에 참여 중인 (탈주 가능한) 참여자 목록 조회 - -operation::getCurrentMembers[snippets="path-parameters,http-request,http-response,response-fields"] -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- - -=== 참여자 액션 삭제 - -operation::deleteMemberAction[snippets="path-parameters,http-request,http-response,request-cookies"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - }, - { - "code":"ACTION_NOT_FOUND", - "message":"존재하지 않는 액션입니다." - }, - { - "code":"MEMBER_ACTION_NOT_FOUND", - "message":"존재하지 않는 멤버 액션입니다." - }, - { - "code":"TOKEN_NOT_FOUND", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_EXPIRED", - "message":"토큰이 존재하지 않습니다." - }, - { - "code":"TOKEN_INVALID", - "message":"유효하지 않은 토큰입니다." - } -] ----- diff --git a/server/src/docs/asciidoc/memberBillReport.adoc b/server/src/docs/asciidoc/memberBillReport.adoc deleted file mode 100644 index 18bd7d3ef..000000000 --- a/server/src/docs/asciidoc/memberBillReport.adoc +++ /dev/null @@ -1,17 +0,0 @@ -== 정산 - -=== 참여자별 정산 결과 조회 - -operation::getMemberBillReports[snippets="path-parameters,http-request,response-body,response-fields,http-response,http-request"] - -==== [.red]#Exceptions# - -[source,json,options="nowrap"] ----- -[ - { - "code":"EVENT_NOT_FOUND", - "message":"존재하지 않는 행사입니다." - } -] ----- diff --git a/server/src/main/java/server/haengdong/HaengdongApplication.java b/server/src/main/java/server/haengdong/HaengdongApplication.java deleted file mode 100644 index 4a84c6120..000000000 --- a/server/src/main/java/server/haengdong/HaengdongApplication.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@Slf4j -@SpringBootApplication -public class HaengdongApplication { - - public static void main(String[] args) { - SpringApplication.run(HaengdongApplication.class, args); - } - -} diff --git a/server/src/main/java/server/haengdong/application/ActionService.java b/server/src/main/java/server/haengdong/application/ActionService.java deleted file mode 100644 index bcf5e8b55..000000000 --- a/server/src/main/java/server/haengdong/application/ActionService.java +++ /dev/null @@ -1,39 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberBillReport; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class ActionService { - - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - private final EventRepository eventRepository; - - public List<MemberBillReportAppResponse> getMemberBillReports(String token) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - List<BillAction> billActions = billActionRepository.findByAction_Event(event); - List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event); - - MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - - return memberBillReport.getReports().entrySet().stream() - .map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue())) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/application/AuthService.java b/server/src/main/java/server/haengdong/application/AuthService.java deleted file mode 100644 index d9352ad53..000000000 --- a/server/src/main/java/server/haengdong/application/AuthService.java +++ /dev/null @@ -1,41 +0,0 @@ -package server.haengdong.application; - - -import java.util.Map; -import server.haengdong.domain.TokenProvider; -import server.haengdong.exception.AuthenticationException; -import server.haengdong.exception.HaengdongErrorCode; - -public class AuthService { - - private static final String TOKEN_NAME = "eventToken"; - private static final String CLAIM_SUB = "sub"; - - private final TokenProvider tokenProvider; - - public AuthService(TokenProvider tokenProvider) { - this.tokenProvider = tokenProvider; - } - - public String createToken(String eventId) { - Map<String, Object> payload = Map.of(CLAIM_SUB, eventId); - - return tokenProvider.createToken(payload); - } - - public String findEventIdByToken(String token) { - validateToken(token); - Map<String, Object> payload = tokenProvider.getPayload(token); - return (String) payload.get(CLAIM_SUB); - } - - private void validateToken(String token) { - if (!tokenProvider.validateToken(token)) { - throw new AuthenticationException(HaengdongErrorCode.TOKEN_INVALID); - } - } - - public String getTokenName() { - return TOKEN_NAME; - } -} diff --git a/server/src/main/java/server/haengdong/application/BillActionDetailService.java b/server/src/main/java/server/haengdong/application/BillActionDetailService.java deleted file mode 100644 index 55d39aac0..000000000 --- a/server/src/main/java/server/haengdong/application/BillActionDetailService.java +++ /dev/null @@ -1,76 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.BillActionDetailUpdateAppRequest; -import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class BillActionDetailService { - - private final BillActionRepository billActionRepository; - - public BillActionDetailsAppResponse findBillActionDetails(String token, Long actionId) { - BillAction billAction = billActionRepository.findByAction_Id(actionId) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); - validateToken(token, billAction); - - List<BillActionDetail> billActionDetails = billAction.getBillActionDetails(); - return BillActionDetailsAppResponse.of(billActionDetails); - } - - @Transactional - public void updateBillActionDetails(String token, Long actionId, BillActionDetailsUpdateAppRequest request) { - BillAction billAction = billActionRepository.findByAction_Id(actionId) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); - - List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests = request.billActionDetailUpdateAppRequests(); - - validateToken(token, billAction); - validateTotalPrice(billActionDetailUpdateAppRequests, billAction); - - List<BillActionDetail> billActionDetails = billAction.getBillActionDetails(); - - for (BillActionDetailUpdateAppRequest updateRequest : billActionDetailUpdateAppRequests) { - BillActionDetail detailToUpdate = billActionDetails.stream() - .filter(detail -> detail.isSameName(updateRequest.name())) - .findFirst() - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_DETAIL_NOT_FOUND)); - - detailToUpdate.updatePrice(updateRequest.price()); - detailToUpdate.updateIsFixed(updateRequest.isFixed()); - } - } - - private void validateToken(String token, BillAction billAction) { - Event event = billAction.getEvent(); - if (event.isTokenMismatch(token)) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND); - } - } - - private void validateTotalPrice(List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests, - BillAction billAction) { - Long requestsPriceSum = calculateUpdatePriceSum(billActionDetailUpdateAppRequests); - if (!billAction.isSamePrice(requestsPriceSum)) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_PRICE_NOT_MATCHED); - } - } - - private Long calculateUpdatePriceSum(List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests) { - return billActionDetailUpdateAppRequests.stream() - .map(BillActionDetailUpdateAppRequest::price) - .reduce(0L, Long::sum); - } -} diff --git a/server/src/main/java/server/haengdong/application/BillActionService.java b/server/src/main/java/server/haengdong/application/BillActionService.java deleted file mode 100644 index dae36a2e7..000000000 --- a/server/src/main/java/server/haengdong/application/BillActionService.java +++ /dev/null @@ -1,80 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.application.request.BillActionUpdateAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class BillActionService { - - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - private final ActionRepository actionRepository; - private final EventRepository eventRepository; - - @Transactional - public void saveAllBillAction(String eventToken, List<BillActionAppRequest> requests) { - Event event = getEvent(eventToken); - Action action = createStartAction(event); - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); - - for (BillActionAppRequest request : requests) { - BillAction billAction = request.toBillAction(action, currentMembers); - billActionRepository.save(billAction); - action = action.next(); - } - } - - private Action createStartAction(Event event) { - return actionRepository.findLastByEvent(event) - .map(Action::next) - .orElse(Action.createFirst(event)); - } - - @Transactional - public void updateBillAction(String token, Long actionId, BillActionUpdateAppRequest request) { - BillAction billAction = billActionRepository.findByAction_Id(actionId) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND)); - - validateToken(token, billAction); - - billAction.update(request.title(), request.price()); - } - - private void validateToken(String token, BillAction billAction) { - Event event = billAction.getEvent(); - if (event.isTokenMismatch(token)) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_NOT_FOUND); - } - } - - @Transactional - public void deleteBillAction(String token, Long actionId) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - - billActionRepository.deleteByAction_EventAndActionId(event, actionId); - } - - private Event getEvent(String eventToken) { - return eventRepository.findByToken(eventToken) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - } -} diff --git a/server/src/main/java/server/haengdong/application/EventService.java b/server/src/main/java/server/haengdong/application/EventService.java deleted file mode 100644 index 1aaddd0f9..000000000 --- a/server/src/main/java/server/haengdong/application/EventService.java +++ /dev/null @@ -1,170 +0,0 @@ -package server.haengdong.application; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Set; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.request.EventLoginAppRequest; -import server.haengdong.application.request.MemberNameUpdateAppRequest; -import server.haengdong.application.request.MemberNamesUpdateAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.application.response.MembersAppResponse; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetailRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.event.EventTokenProvider; -import server.haengdong.exception.AuthenticationException; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class EventService { - - private final EventRepository eventRepository; - private final EventTokenProvider eventTokenProvider; - private final BillActionRepository billActionRepository; - private final MemberActionRepository memberActionRepository; - private final BillActionDetailRepository billActionDetailRepository; - - - @Transactional - public EventAppResponse saveEvent(EventAppRequest request) { - String token = eventTokenProvider.createToken(); - Event event = request.toEvent(token); - eventRepository.save(event); - - return EventAppResponse.of(event); - } - - public EventDetailAppResponse findEvent(String token) { - Event event = getEvent(token); - - return EventDetailAppResponse.of(event); - } - - public List<ActionAppResponse> findActions(String token) { - Event event = getEvent(token); - - List<BillAction> billActions = billActionRepository.findByAction_Event(event).stream() - .sorted(Comparator.comparing(BillAction::getSequence)).toList(); - List<MemberAction> memberActions = memberActionRepository.findAllByEvent(event).stream() - .sorted(Comparator.comparing(MemberAction::getSequence)).toList(); - - return getActionAppResponses(billActions, memberActions); - } - - private List<ActionAppResponse> getActionAppResponses( - List<BillAction> billActions, - List<MemberAction> memberActions - ) { - int billActionIndex = 0; - int memberActionIndex = 0; - List<ActionAppResponse> actionAppResponses = new ArrayList<>(); - - while (billActionIndex < billActions.size() && memberActionIndex < memberActions.size()) { - BillAction billAction = billActions.get(billActionIndex); - MemberAction memberAction = memberActions.get(memberActionIndex); - if (billAction.getSequence() < memberAction.getSequence()) { - actionAppResponses.add(ActionAppResponse.of(billAction)); - billActionIndex++; - } else { - actionAppResponses.add(ActionAppResponse.of(memberAction)); - memberActionIndex++; - } - } - while (billActionIndex < billActions.size()) { - BillAction billAction = billActions.get(billActionIndex++); - actionAppResponses.add(ActionAppResponse.of(billAction)); - } - while (memberActionIndex < memberActions.size()) { - MemberAction memberAction = memberActions.get(memberActionIndex++); - actionAppResponses.add(ActionAppResponse.of(memberAction)); - } - - return actionAppResponses; - } - - public MembersAppResponse findAllMembers(String token) { - Event event = getEvent(token); - - List<String> memberNames = memberActionRepository.findAllUniqueMemberByEvent(event); - - return new MembersAppResponse(memberNames); - } - - @Transactional - public void updateMember(String token, MemberNamesUpdateAppRequest request) { - Event event = getEvent(token); - List<MemberNameUpdateAppRequest> members = request.members(); - - validateBeforeNames(members, event); - validateAfterNames(members, event); - - members.forEach(member -> updateMemberName(event, member.before(), member.after())); - } - - private void validateBeforeNames(List<MemberNameUpdateAppRequest> members, Event event) { - List<String> beforeNames = members.stream() - .map(MemberNameUpdateAppRequest::before) - .toList(); - if (beforeNames.size() != Set.copyOf(beforeNames).size()) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); - } - beforeNames.forEach(beforeName -> validateBeforeMemberNameExist(event, beforeName)); - } - - private void validateBeforeMemberNameExist(Event event, String beforeName) { - boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, beforeName); - if (!isMemberNameExist) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NOT_EXIST); - } - } - - private void validateAfterNames(List<MemberNameUpdateAppRequest> members, Event event) { - List<String> afterNames = members.stream() - .map(MemberNameUpdateAppRequest::after) - .toList(); - if (afterNames.size() != Set.copyOf(afterNames).size()) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_CHANGE_DUPLICATE); - } - afterNames.forEach(afterName -> validateAfterMemberNameNotExist(event, afterName)); - } - - private void validateAfterMemberNameNotExist(Event event, String afterName) { - boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, afterName); - if (isMemberNameExist) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); - } - } - - private void updateMemberName(Event event, String beforeName, String afterName) { - memberActionRepository.findAllByAction_EventAndMemberName(event, beforeName) - .forEach(memberAction -> memberAction.updateMemberName(afterName)); - billActionDetailRepository.findAllByBillAction_Action_EventAndMemberName(event, beforeName) - .forEach(billActionDetail -> billActionDetail.updateMemberName(afterName)); - } - - public void validatePassword(EventLoginAppRequest request) throws HaengdongException { - Event event = getEvent(request.token()); - if (event.isPasswordMismatch(request.password())) { - throw new AuthenticationException(HaengdongErrorCode.PASSWORD_INVALID); - } - } - - private Event getEvent(String token) { - return eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - } -} diff --git a/server/src/main/java/server/haengdong/application/MemberActionFactory.java b/server/src/main/java/server/haengdong/application/MemberActionFactory.java deleted file mode 100644 index c0a171642..000000000 --- a/server/src/main/java/server/haengdong/application/MemberActionFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -package server.haengdong.application; - -import java.util.ArrayList; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.action.MemberGroupIdProvider; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Component -public class MemberActionFactory { - - private final MemberGroupIdProvider memberGroupIdProvider; - - public List<MemberAction> createMemberActions( - MemberActionsSaveAppRequest request, - CurrentMembers currentMembers, - Action action - ) { - validateMemberNames(request); - validateActions(request, currentMembers); - - Long memberGroupId = memberGroupIdProvider.createGroupId(); - List<MemberAction> createdMemberActions = new ArrayList<>(); - List<MemberActionSaveAppRequest> actions = request.actions(); - for (MemberActionSaveAppRequest appRequest : actions) { - MemberAction memberAction = appRequest.toMemberAction(action, memberGroupId); - createdMemberActions.add(memberAction); - action = action.next(); - } - - return createdMemberActions; - } - - private void validateMemberNames(MemberActionsSaveAppRequest request) { - List<String> memberNames = request.actions().stream() - .map(MemberActionSaveAppRequest::name) - .toList(); - - long uniqueCount = memberNames.stream().distinct().count(); - if (uniqueCount != memberNames.size()) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_DUPLICATE); - } - } - - private void validateActions(MemberActionsSaveAppRequest request, CurrentMembers currentMembers) { - List<MemberActionSaveAppRequest> actions = request.actions(); - - for (MemberActionSaveAppRequest action : actions) { - MemberActionStatus memberActionStatus = MemberActionStatus.of(action.status()); - currentMembers.validate(action.name(), memberActionStatus); - } - } -} diff --git a/server/src/main/java/server/haengdong/application/MemberActionService.java b/server/src/main/java/server/haengdong/application/MemberActionService.java deleted file mode 100644 index 245de8cef..000000000 --- a/server/src/main/java/server/haengdong/application/MemberActionService.java +++ /dev/null @@ -1,100 +0,0 @@ -package server.haengdong.application; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.ActionRepository; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@RequiredArgsConstructor -@Transactional(readOnly = true) -@Service -public class MemberActionService { - - private final MemberActionFactory memberActionFactory; - private final MemberActionRepository memberActionRepository; - private final EventRepository eventRepository; - private final ActionRepository actionRepository; - private final BillActionRepository billActionRepository; - - @Transactional - public void saveMemberAction(String token, MemberActionsSaveAppRequest request) { - Event event = findEvent(token); - - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); - Action action = createStartAction(event); - List<MemberAction> memberActions = memberActionFactory.createMemberActions(request, currentMembers, action); - memberActionRepository.saveAll(memberActions); - } - - private Action createStartAction(Event event) { - return actionRepository.findLastByEvent(event) - .map(Action::next) - .orElse(Action.createFirst(event)); - } - - public List<CurrentMemberAppResponse> getCurrentMembers(String token) { - Event event = findEvent(token); - List<MemberAction> findMemberActions = memberActionRepository.findAllByEvent(event); - CurrentMembers currentMembers = CurrentMembers.of(findMemberActions); - - return currentMembers.getMembers() - .stream() - .map(CurrentMemberAppResponse::new) - .toList(); - } - - private Event findEvent(String token) { - return eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - } - - @Transactional - public void deleteMember(String token, String memberName) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - - memberActionRepository.deleteAllByEventAndMemberName(event, memberName); - - List<BillAction> billActions = billActionRepository.findByAction_Event(event); - billActions.forEach(billAction -> resetBillAction(event, billAction)); - } - - @Transactional - public void deleteMemberAction(String token, Long actionId) { - Event event = eventRepository.findByToken(token) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)); - Action action = actionRepository.findByIdAndEvent(actionId, event) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.ACTION_NOT_FOUND)); - MemberAction memberAction = memberActionRepository.findByAction(action) - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.MEMBER_ACTION_NOT_FOUND)); - - memberActionRepository.deleteAllByMemberNameAndMinSequence(memberAction.getMemberName(), - memberAction.getSequence()); - - List<BillAction> billActions = billActionRepository.findByEventAndGreaterThanSequence(event, - action.getSequence()); - billActions.forEach(billAction -> resetBillAction(event, billAction)); - } - - private void resetBillAction(Event event, BillAction billAction) { - List<MemberAction> memberActions = memberActionRepository.findByEventAndSequence(event, - billAction.getSequence()); - CurrentMembers currentMembers = CurrentMembers.of(memberActions); - - billAction.resetBillActionDetails(currentMembers); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java deleted file mode 100644 index 21eb17d4a..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionAppRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.CurrentMembers; - -public record BillActionAppRequest( - String title, - Long price -) { - - public BillAction toBillAction(Action action, CurrentMembers currentMembers) { - return BillAction.create(action, title, price, currentMembers); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java deleted file mode 100644 index e514aee81..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionDetailUpdateAppRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package server.haengdong.application.request; - -public record BillActionDetailUpdateAppRequest( - String name, - Long price, - boolean isFixed -) { -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java deleted file mode 100644 index 1fe19798e..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionDetailsUpdateAppRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package server.haengdong.application.request; - -import java.util.List; - -public record BillActionDetailsUpdateAppRequest( - List<BillActionDetailUpdateAppRequest> billActionDetailUpdateAppRequests -) { -} diff --git a/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java deleted file mode 100644 index a90e3dd42..000000000 --- a/server/src/main/java/server/haengdong/application/request/BillActionUpdateAppRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package server.haengdong.application.request; - -public record BillActionUpdateAppRequest( - String title, - Long price -) { -} diff --git a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventAppRequest.java deleted file mode 100644 index 20ec16d88..000000000 --- a/server/src/main/java/server/haengdong/application/request/EventAppRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.event.Event; - -public record EventAppRequest(String name, String password) { - - public Event toEvent(String token) { - return new Event(name, password, token); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java b/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java deleted file mode 100644 index 947b5ef39..000000000 --- a/server/src/main/java/server/haengdong/application/request/EventLoginAppRequest.java +++ /dev/null @@ -1,4 +0,0 @@ -package server.haengdong.application.request; - -public record EventLoginAppRequest(String token, String password) { -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java deleted file mode 100644 index f7f8d8fc2..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberActionSaveAppRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.application.request; - -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; - -public record MemberActionSaveAppRequest(String name, String status) { - - public MemberAction toMemberAction(Action action, Long memberGroupId) { - return new MemberAction(action, name, MemberActionStatus.of(status), memberGroupId); - } -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java deleted file mode 100644 index 650b908df..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberActionsSaveAppRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package server.haengdong.application.request; - -import java.util.List; - -public record MemberActionsSaveAppRequest(List<MemberActionSaveAppRequest> actions) { -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java deleted file mode 100644 index d629d3a02..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberNameUpdateAppRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package server.haengdong.application.request; - -public record MemberNameUpdateAppRequest( - String before, - String after -) { -} diff --git a/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java b/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java deleted file mode 100644 index cd0c00544..000000000 --- a/server/src/main/java/server/haengdong/application/request/MemberNamesUpdateAppRequest.java +++ /dev/null @@ -1,8 +0,0 @@ -package server.haengdong.application.request; - -import java.util.List; - -public record MemberNamesUpdateAppRequest( - List<MemberNameUpdateAppRequest> members -) { -} diff --git a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java b/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java deleted file mode 100644 index 0c2c12611..000000000 --- a/server/src/main/java/server/haengdong/application/response/ActionAppResponse.java +++ /dev/null @@ -1,61 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionStatus; - -public record ActionAppResponse( - Long actionId, - String name, - Long price, - Long sequence, - boolean isFixed, - ActionType actionType -) { - - public ActionAppResponse(Long actionId, String name, Long price, Long sequence, ActionType actionType) { - this(actionId, name, price, sequence, false, actionType); - } - - public static ActionAppResponse of(BillAction billAction) { - return new ActionAppResponse( - billAction.getAction().getId(), - billAction.getTitle(), - billAction.getPrice(), - billAction.getSequence(), - billAction.isFixed(), - ActionAppResponse.ActionType.BILL - ); - } - - public static ActionAppResponse of(MemberAction memberAction) { - MemberActionStatus status = memberAction.getStatus(); - - return new ActionAppResponse( - memberAction.getAction().getId(), - memberAction.getMemberName(), - null, - memberAction.getSequence(), - false, - ActionAppResponse.ActionType.of(status) - ); - } - - public String actionTypeName() { - return actionType.name(); - } - - public enum ActionType { - BILL, - IN, - OUT, - ; - - private static ActionType of(MemberActionStatus memberActionStatus) { - if (MemberActionStatus.IN == memberActionStatus) { - return IN; - } - return OUT; - } - } -} diff --git a/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java deleted file mode 100644 index 3efc7ac9d..000000000 --- a/server/src/main/java/server/haengdong/application/response/BillActionDetailAppResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.BillActionDetail; - -public record BillActionDetailAppResponse( - String name, - Long price, - boolean isFixed -) { - - public static BillActionDetailAppResponse of(BillActionDetail billActionDetail) { - return new BillActionDetailAppResponse( - billActionDetail.getMemberName(), - billActionDetail.getPrice(), - billActionDetail.isFixed() - ); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java b/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java deleted file mode 100644 index 061f07816..000000000 --- a/server/src/main/java/server/haengdong/application/response/BillActionDetailsAppResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.application.response; - -import java.util.List; -import java.util.stream.Collectors; -import server.haengdong.domain.action.BillActionDetail; - -public record BillActionDetailsAppResponse(List<BillActionDetailAppResponse> billActionDetailAppResponses) { - - public static BillActionDetailsAppResponse of(List<BillActionDetail> billActionDetails) { - return billActionDetails.stream() - .map(BillActionDetailAppResponse::of) - .collect(Collectors.collectingAndThen(Collectors.toList(), BillActionDetailsAppResponse::new)); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java b/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java deleted file mode 100644 index 6c682d3e9..000000000 --- a/server/src/main/java/server/haengdong/application/response/CurrentMemberAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.action.MemberAction; - -public record CurrentMemberAppResponse(String name) { - - public static CurrentMemberAppResponse of(MemberAction memberAction) { - return new CurrentMemberAppResponse(memberAction.getMemberName()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventAppResponse.java deleted file mode 100644 index f331d0011..000000000 --- a/server/src/main/java/server/haengdong/application/response/EventAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.event.Event; - -public record EventAppResponse(String token) { - - public static EventAppResponse of(Event event) { - return new EventAppResponse(event.getToken()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java b/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java deleted file mode 100644 index 6e38826d4..000000000 --- a/server/src/main/java/server/haengdong/application/response/EventDetailAppResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.application.response; - -import server.haengdong.domain.event.Event; - -public record EventDetailAppResponse(String eventName) { - - public static EventDetailAppResponse of(Event event) { - return new EventDetailAppResponse(event.getName()); - } -} diff --git a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java b/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java deleted file mode 100644 index 21b6cef56..000000000 --- a/server/src/main/java/server/haengdong/application/response/MemberBillReportAppResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package server.haengdong.application.response; - -public record MemberBillReportAppResponse(String name, Long price) { -} diff --git a/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java b/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java deleted file mode 100644 index be8378b37..000000000 --- a/server/src/main/java/server/haengdong/application/response/MembersAppResponse.java +++ /dev/null @@ -1,8 +0,0 @@ -package server.haengdong.application.response; - -import java.util.List; - -public record MembersAppResponse( - List<String> memberNames -) { -} diff --git a/server/src/main/java/server/haengdong/config/AdminInterceptor.java b/server/src/main/java/server/haengdong/config/AdminInterceptor.java deleted file mode 100644 index a0542ed46..000000000 --- a/server/src/main/java/server/haengdong/config/AdminInterceptor.java +++ /dev/null @@ -1,51 +0,0 @@ -package server.haengdong.config; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpMethod; -import org.springframework.web.servlet.HandlerInterceptor; -import server.haengdong.application.AuthService; -import server.haengdong.exception.AuthenticationException; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.infrastructure.auth.AuthenticationExtractor; - -@Slf4j -public class AdminInterceptor implements HandlerInterceptor { - - private final AuthService authService; - private final AuthenticationExtractor authenticationExtractor; - - public AdminInterceptor(AuthService authService, AuthenticationExtractor authenticationExtractor) { - this.authService = authService; - this.authenticationExtractor = authenticationExtractor; - } - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { - String requestURI = request.getRequestURI(); - - if (requestURI.endsWith("/login")) { - return true; // 요청을 계속 진행하도록 허용 - } - - HttpMethod method = HttpMethod.valueOf(request.getMethod()); - if (HttpMethod.GET.equals(method) || HttpMethod.OPTIONS.equals(method)) { - return true; - } - - validateToken(request); - - return true; - } - - private void validateToken(HttpServletRequest request) { - String token = authenticationExtractor.extract(request, authService.getTokenName()); - String tokenEventId = authService.findEventIdByToken(token); - String eventId = request.getRequestURI().split("/")[3]; - if (!tokenEventId.equals(eventId)) { - log.warn("[행사 접근 불가] Cookie EventId = {}, URL EventId = {}", tokenEventId, eventId); - throw new AuthenticationException(HaengdongErrorCode.FORBIDDEN); - } - } -} diff --git a/server/src/main/java/server/haengdong/config/RequestServletFilter.java b/server/src/main/java/server/haengdong/config/RequestServletFilter.java deleted file mode 100644 index b1afdb6f8..000000000 --- a/server/src/main/java/server/haengdong/config/RequestServletFilter.java +++ /dev/null @@ -1,23 +0,0 @@ -package server.haengdong.config; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import java.io.IOException; -import org.springframework.stereotype.Component; -import org.springframework.web.util.ContentCachingRequestWrapper; - -@Component -public class RequestServletFilter implements Filter { - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper((HttpServletRequest) request); - - chain.doFilter(wrappedRequest, response); - } -} diff --git a/server/src/main/java/server/haengdong/config/WebMvcConfig.java b/server/src/main/java/server/haengdong/config/WebMvcConfig.java deleted file mode 100644 index d1caa176f..000000000 --- a/server/src/main/java/server/haengdong/config/WebMvcConfig.java +++ /dev/null @@ -1,66 +0,0 @@ -package server.haengdong.config; - -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import server.haengdong.application.AuthService; -import server.haengdong.domain.TokenProvider; -import server.haengdong.infrastructure.auth.AuthenticationExtractor; -import server.haengdong.infrastructure.auth.JwtTokenProvider; -import server.haengdong.infrastructure.auth.TokenProperties; - -@RequiredArgsConstructor -@EnableConfigurationProperties(TokenProperties.class) -@Configuration -public class WebMvcConfig implements WebMvcConfigurer { - - private final TokenProperties tokenProperties; - - @Value("${cors.max-age}") - private Long maxAge; - - @Value("${cors.allowed-origins}") - private String[] allowedOrigins; - - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins(allowedOrigins) - .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS") - .allowedHeaders("*") - .allowCredentials(true) - .maxAge(maxAge); - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(adminInterceptor()) - .addPathPatterns("/api/**") - .excludePathPatterns("/api/events"); - } - - @Bean - public AdminInterceptor adminInterceptor() { - return new AdminInterceptor(authService(), authenticationExtractor()); - } - - @Bean - public AuthService authService() { - return new AuthService(tokenProvider()); - } - - @Bean - public TokenProvider tokenProvider() { - return new JwtTokenProvider(tokenProperties); - } - - @Bean - public AuthenticationExtractor authenticationExtractor() { - return new AuthenticationExtractor(); - } -} diff --git a/server/src/main/java/server/haengdong/domain/TokenProvider.java b/server/src/main/java/server/haengdong/domain/TokenProvider.java deleted file mode 100644 index 28e7956c3..000000000 --- a/server/src/main/java/server/haengdong/domain/TokenProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.domain; - -import java.util.Map; - -public interface TokenProvider { - - String createToken(Map<String, Object> payload); - - Map<String, Object> getPayload(String token); - - boolean validateToken(String token); -} diff --git a/server/src/main/java/server/haengdong/domain/action/Action.java b/server/src/main/java/server/haengdong/domain/action/Action.java deleted file mode 100644 index 11f91fc38..000000000 --- a/server/src/main/java/server/haengdong/domain/action/Action.java +++ /dev/null @@ -1,42 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.domain.event.Event; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Action { - - private static final long FIRST_SEQUENCE = 1L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Event event; - - private Long sequence; - - public Action(Event event, Long sequence) { - this.event = event; - this.sequence = sequence; - } - - public static Action createFirst(Event event) { - return new Action(event, FIRST_SEQUENCE); - } - - public Action next() { - return new Action(event, sequence + 1); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java b/server/src/main/java/server/haengdong/domain/action/ActionRepository.java deleted file mode 100644 index 2fde0ffa6..000000000 --- a/server/src/main/java/server/haengdong/domain/action/ActionRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface ActionRepository extends JpaRepository<Action, Long> { - - @Query(""" - SELECT a - FROM Action a - WHERE a.event = :event - ORDER BY a.sequence DESC - LIMIT 1 - """) - Optional<Action> findLastByEvent(@Param("event") Event event); - - Optional<Action> findByIdAndEvent(Long id, Event event); -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillAction.java b/server/src/main/java/server/haengdong/domain/action/BillAction.java deleted file mode 100644 index 943b40ce5..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillAction.java +++ /dev/null @@ -1,156 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class BillAction implements Comparable<BillAction> { - - public static final int MIN_TITLE_LENGTH = 1; - public static final int MAX_TITLE_LENGTH = 30; - public static final long MIN_PRICE = 1L; - public static final long MAX_PRICE = 10_000_000L; - private static final long DEFAULT_PRICE = 0L; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - private Action action; - - @Column(length = MAX_TITLE_LENGTH) - private String title; - - private Long price; - - @OneToMany(mappedBy = "billAction", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) - private List<BillActionDetail> billActionDetails = new ArrayList<>(); - - public BillAction(Action action, String title, Long price) { - validateTitle(title); - validatePrice(price); - this.action = action; - this.title = title.trim(); - this.price = price; - } - - private void validateTitle(String title) { - int titleLength = title.trim().length(); - if (titleLength < MIN_TITLE_LENGTH || titleLength > MAX_TITLE_LENGTH) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_TITLE_INVALID); - } - } - - private void validatePrice(Long price) { - if (price < MIN_PRICE || price > MAX_PRICE) { - throw new HaengdongException(HaengdongErrorCode.BILL_ACTION_PRICE_INVALID); - } - } - - public static BillAction create(Action action, String title, Long price, CurrentMembers currentMembers) { - BillAction billAction = new BillAction(action, title, price); - billAction.resetBillActionDetails(currentMembers); - return billAction; - } - - public void resetBillActionDetails(CurrentMembers currentMembers) { - this.billActionDetails.clear(); - Iterator<Long> priceIterator = distributePrice(currentMembers.size()).iterator(); - - for (String member : currentMembers.getMembers()) { - BillActionDetail billActionDetail = new BillActionDetail(this, member, priceIterator.next(), false); - this.billActionDetails.add(billActionDetail); - } - } - - private void resetBillActionDetails() { - Iterator<Long> priceIterator = distributePrice(billActionDetails.size()).iterator(); - - billActionDetails.forEach(billActionDetail -> { - billActionDetail.updatePrice(priceIterator.next()); - billActionDetail.updateIsFixed(false); - }); - } - - private List<Long> distributePrice(int memberCount) { - if (memberCount == 0) { - return new ArrayList<>(); - } - long eachPrice = price / memberCount; - long remainder = price % memberCount; - - List<Long> results = Stream.generate(() -> eachPrice) - .limit(memberCount - 1) - .collect(Collectors.toList()); - results.add(eachPrice + remainder); - return results; - } - - public void update(String title, Long price) { - validateTitle(title); - validatePrice(price); - this.title = title.trim(); - this.price = price; - resetBillActionDetails(); - } - - public void addDetails(List<BillActionDetail> billActionDetails) { - billActionDetails.forEach(this::addDetail); - } - - private void addDetail(BillActionDetail billActionDetail) { - this.billActionDetails.add(billActionDetail); - billActionDetail.setBillAction(this); - } - - public boolean isFixed() { - return billActionDetails.stream() - .anyMatch(BillActionDetail::isFixed); - } - - public boolean isSamePrice(Long price) { - return this.price.equals(price); - } - - public Long findPriceByMemberName(String memberName) { - return billActionDetails.stream() - .filter(billActionDetail -> billActionDetail.hasMemberName(memberName)) - .map(BillActionDetail::getPrice) - .findFirst() - .orElse(DEFAULT_PRICE); - } - - public Long getSequence() { - return action.getSequence(); - } - - public Event getEvent() { - return action.getEvent(); - } - - @Override - public int compareTo(BillAction o) { - return Long.compare(this.getSequence(), o.getSequence()); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java deleted file mode 100644 index ffdfe04a3..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillActionDetail.java +++ /dev/null @@ -1,61 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class BillActionDetail { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private BillAction billAction; - - private String memberName; - - private Long price; - - private boolean isFixed; - - public BillActionDetail(BillAction billAction, String memberName, Long price, boolean isFixed) { - this.billAction = billAction; - this.memberName = memberName; - this.price = price; - this.isFixed = isFixed; - } - - public void updatePrice(Long price) { - this.price = price; - } - - public void updateIsFixed(boolean isFixed) { - this.isFixed = isFixed; - } - - public void updateMemberName(String name) { - this.memberName = name; - } - - public boolean hasMemberName(String memberName) { - return this.memberName.equals(memberName); - } - - public boolean isSameName(String memberName) { - return this.memberName.equals(memberName); - } - - public void setBillAction(BillAction billAction) { - this.billAction = billAction; - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java deleted file mode 100644 index 05de55304..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillActionDetailRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface BillActionDetailRepository extends JpaRepository<BillActionDetail, Long> { - - @Query(""" - select bd - from BillActionDetail bd - where bd.billAction = :billAction - """) - List<BillActionDetail> findAllByBillAction(BillAction billAction); - - List<BillActionDetail> findAllByBillAction_Action_EventAndMemberName(Event event, String memberName); -} diff --git a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java b/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java deleted file mode 100644 index 817a63bf8..000000000 --- a/server/src/main/java/server/haengdong/domain/action/BillActionRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import java.util.Optional; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface BillActionRepository extends JpaRepository<BillAction, Long> { - - @EntityGraph(attributePaths = {"action"}) - List<BillAction> findByAction_Event(Event event); - - void deleteByAction_EventAndActionId(Event event, Long actionId); - - Optional<BillAction> findByAction_Id(Long actionId); - - @Query(""" - select ba - from BillAction ba - where ba.action.event = :event and ba.action.sequence > :sequence - """) - List<BillAction> findByEventAndGreaterThanSequence(Event event, Long sequence); -} diff --git a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java b/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java deleted file mode 100644 index ba380aae5..000000000 --- a/server/src/main/java/server/haengdong/domain/action/CurrentMembers.java +++ /dev/null @@ -1,81 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -public class CurrentMembers { - - private final Set<String> members; - - public CurrentMembers() { - this(new HashSet<>()); - } - - protected CurrentMembers(Set<String> members) { - this.members = members; - } - - public static CurrentMembers of(List<MemberAction> memberActions) { - List<MemberAction> sortedMemberActions = getSortedMemberActions(memberActions); - Set<String> members = new HashSet<>(); - for (MemberAction memberAction : sortedMemberActions) { - String member = memberAction.getMemberName(); - if (memberAction.isSameStatus(MemberActionStatus.IN)) { - members.add(member); - continue; - } - members.remove(member); - } - - return new CurrentMembers(members); - } - - private static List<MemberAction> getSortedMemberActions(List<MemberAction> memberActions) { - return memberActions.stream() - .sorted(Comparator.comparing(MemberAction::getSequence)) - .toList(); - } - - public CurrentMembers addMemberAction(MemberAction memberAction) { - String memberName = memberAction.getMemberName(); - - Set<String> currentMembers = new HashSet<>(members); - - if (memberAction.isIn()) { - currentMembers.add(memberName); - } else { - currentMembers.remove(memberName); - } - return new CurrentMembers(currentMembers); - } - - public void validate(String memberName, MemberActionStatus memberActionStatus) { - if (memberActionStatus == MemberActionStatus.IN && members.contains(memberName)) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_ALREADY_EXIST); - } - if (memberActionStatus == MemberActionStatus.OUT && !members.contains(memberName)) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NOT_EXIST); - } - } - - public boolean isEmpty() { - return members.isEmpty(); - } - - public boolean isNotEmpty() { - return !members.isEmpty(); - } - - public int size() { - return members.size(); - } - - public Set<String> getMembers() { - return Collections.unmodifiableSet(members); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberAction.java b/server/src/main/java/server/haengdong/domain/action/MemberAction.java deleted file mode 100644 index 3faf65bde..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberAction.java +++ /dev/null @@ -1,76 +0,0 @@ -package server.haengdong.domain.action; - -import jakarta.persistence.CascadeType; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class MemberAction implements Comparable<MemberAction> { - - public static final int MIN_NAME_LENGTH = 1; - public static final int MAX_NAME_LENGTH = 4; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) - private Action action; - - private String memberName; - - @Enumerated(EnumType.STRING) - private MemberActionStatus status; - - private Long memberGroupId; - - public MemberAction(Action action, String memberName, MemberActionStatus status, Long memberGroupId) { - validateMemberName(memberName); - this.action = action; - this.memberName = memberName; - this.status = status; - this.memberGroupId = memberGroupId; - } - - private void validateMemberName(String memberName) { - int memberLength = memberName.length(); - if (memberLength < MIN_NAME_LENGTH || memberLength > MAX_NAME_LENGTH) { - throw new HaengdongException(HaengdongErrorCode.MEMBER_NAME_LENGTH_INVALID); - } - } - - public void updateMemberName(String memberName) { - validateMemberName(memberName); - this.memberName = memberName; - } - - public boolean isIn() { - return status == MemberActionStatus.IN; - } - - public boolean isSameStatus(MemberActionStatus memberActionStatus) { - return status == memberActionStatus; - } - - public Long getSequence() { - return action.getSequence(); - } - - @Override - public int compareTo(MemberAction o) { - return Long.compare(this.getSequence(), o.getSequence()); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java b/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java deleted file mode 100644 index 324ff9797..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionRepository.java +++ /dev/null @@ -1,53 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.List; -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import server.haengdong.domain.event.Event; - -@Repository -public interface MemberActionRepository extends JpaRepository<MemberAction, Long> { - - @Query("select m from MemberAction m join fetch m.action where m.action.event = :event") - List<MemberAction> findAllByEvent(@Param("event") Event event); - - @Query(""" - select distinct m.memberName - from MemberAction m - where m.action.event = :event - """) - List<String> findAllUniqueMemberByEvent(Event event); - - @Modifying - @Query(""" - delete - from MemberAction m - where m.memberName = :memberName and m.action.event = :event - """) - void deleteAllByEventAndMemberName(Event event, String memberName); - - Optional<MemberAction> findByAction(Action action); - - @Modifying - @Query(""" - delete - from MemberAction m - where m.memberName = :memberName and m.action.sequence >= :sequence - """) - void deleteAllByMemberNameAndMinSequence(String memberName, Long sequence); - - List<MemberAction> findAllByAction_EventAndMemberName(Event event, String memberName); - - boolean existsByAction_EventAndMemberName(Event event, String updatedMemberName); - - @Query(""" - select ma - from MemberAction ma - where ma.action.event = :event and ma.action.sequence < :sequence - """) - List<MemberAction> findByEventAndSequence(Event event, Long sequence); -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java b/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java deleted file mode 100644 index 76c5a66d4..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberActionStatus.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.domain.action; - -import java.util.Arrays; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -public enum MemberActionStatus { - IN, - OUT, - ; - - public static MemberActionStatus of(String status) { - return Arrays.stream(MemberActionStatus.values()) - .filter(s -> s.name().equals(status)) - .findFirst() - .orElseThrow(() -> new HaengdongException(HaengdongErrorCode.MEMBER_ACTION_STATUS_INVALID, - String.format(HaengdongErrorCode.MEMBER_ACTION_STATUS_INVALID.getMessage(), status))); - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java b/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java deleted file mode 100644 index 7a707b9d8..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberBillReport.java +++ /dev/null @@ -1,75 +0,0 @@ -package server.haengdong.domain.action; - -import static java.util.stream.Collectors.toMap; - -import java.util.List; -import java.util.Map; -import java.util.PriorityQueue; -import java.util.function.Function; -import lombok.Getter; - -@Getter -public class MemberBillReport { - - private final Map<String, Long> reports; - - private MemberBillReport(Map<String, Long> reports) { - this.reports = reports; - } - - public static MemberBillReport createByActions(List<BillAction> billActions, List<MemberAction> memberActions) { - PriorityQueue<BillAction> sortedBillActions = new PriorityQueue<>(billActions); - PriorityQueue<MemberAction> sortedMemberActions = new PriorityQueue<>(memberActions); - - Map<String, Long> memberBillReports = initReports(memberActions); - CurrentMembers currentMembers = new CurrentMembers(); - while (!sortedBillActions.isEmpty() && !sortedMemberActions.isEmpty()) { - if (isMemberActionTurn(sortedMemberActions, sortedBillActions)) { - MemberAction memberAction = sortedMemberActions.poll(); - currentMembers = currentMembers.addMemberAction(memberAction); - continue; - } - addBillAction(sortedBillActions, currentMembers, memberBillReports); - } - - while (!sortedBillActions.isEmpty()) { - addBillAction(sortedBillActions, currentMembers, memberBillReports); - } - - return new MemberBillReport(memberBillReports); - } - - private static Map<String, Long> initReports(List<MemberAction> memberActions) { - return memberActions.stream() - .map(MemberAction::getMemberName) - .distinct() - .collect(toMap(Function.identity(), i -> 0L)); - } - - private static boolean isMemberActionTurn( - PriorityQueue<MemberAction> memberActions, - PriorityQueue<BillAction> billActions - ) { - MemberAction memberAction = memberActions.peek(); - BillAction billAction = billActions.peek(); - - return memberAction.getSequence() < billAction.getSequence(); - } - - private static void addBillAction( - PriorityQueue<BillAction> sortedBillActions, - CurrentMembers currentMembers, - Map<String, Long> memberBillReports - ) { - BillAction billAction = sortedBillActions.poll(); - if (currentMembers.isEmpty()) { - return; - } - - for (String currentMember : currentMembers.getMembers()) { - Long currentPrice = billAction.findPriceByMemberName(currentMember); - Long price = memberBillReports.get(currentMember) + currentPrice; - memberBillReports.put(currentMember, price); - } - } -} diff --git a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java b/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java deleted file mode 100644 index 9e32bd733..000000000 --- a/server/src/main/java/server/haengdong/domain/action/MemberGroupIdProvider.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.domain.action; - -import org.springframework.stereotype.Component; - -@Component -public class MemberGroupIdProvider { - - public Long createGroupId() { - return System.currentTimeMillis(); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/Event.java b/server/src/main/java/server/haengdong/domain/event/Event.java deleted file mode 100644 index bb5d53dbc..000000000 --- a/server/src/main/java/server/haengdong/domain/event/Event.java +++ /dev/null @@ -1,70 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.AttributeOverride; -import jakarta.persistence.Column; -import jakarta.persistence.Embedded; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class Event { - - public static final int MIN_NAME_LENGTH = 1; - public static final int MAX_NAME_LENGTH = 20; - private static final String SPACES = " "; - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - private String name; - - @Embedded - @AttributeOverride(name = "value", column = @Column(name = "password")) - private Password password; - - private String token; - - public Event(String name, String password, String token) { - validateName(name); - this.name = name; - this.password = new Password(password); - this.token = token; - } - - private void validateName(String name) { - int nameLength = name.trim().length(); - if (nameLength < MIN_NAME_LENGTH || MAX_NAME_LENGTH < nameLength) { - throw new HaengdongException(HaengdongErrorCode.EVENT_NAME_LENGTH_INVALID, - String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", - MIN_NAME_LENGTH, - MAX_NAME_LENGTH, - name.length())); - } - if (isBlankContinuous(name)) { - throw new HaengdongException(HaengdongErrorCode.EVENT_NAME_CONSECUTIVE_SPACES, - String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", name)); - } - } - - private boolean isBlankContinuous(String name) { - return name.contains(SPACES); - } - - public boolean isTokenMismatch(String token) { - return !this.token.equals(token); - } - - public boolean isPasswordMismatch(String rawPassword) { - return !password.matches(rawPassword); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventRepository.java b/server/src/main/java/server/haengdong/domain/event/EventRepository.java deleted file mode 100644 index 09526125e..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventRepository.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.domain.event; - -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface EventRepository extends JpaRepository<Event, Long> { - - Optional<Event> findByToken(String token); -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventStep.java b/server/src/main/java/server/haengdong/domain/event/EventStep.java deleted file mode 100644 index 297abdb66..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventStep.java +++ /dev/null @@ -1,28 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.ManyToOne; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Entity -public class EventStep { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - private Event event; - - private String name; - - private Long sequence; -} diff --git a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java b/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java deleted file mode 100644 index 6450f0dcf..000000000 --- a/server/src/main/java/server/haengdong/domain/event/EventTokenProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package server.haengdong.domain.event; - -import java.util.UUID; -import org.springframework.stereotype.Component; - -@Component -public class EventTokenProvider { - - public String createToken() { - return UUID.randomUUID().toString(); - } -} diff --git a/server/src/main/java/server/haengdong/domain/event/Password.java b/server/src/main/java/server/haengdong/domain/event/Password.java deleted file mode 100644 index 375849dbf..000000000 --- a/server/src/main/java/server/haengdong/domain/event/Password.java +++ /dev/null @@ -1,52 +0,0 @@ -package server.haengdong.domain.event; - -import jakarta.persistence.Embeddable; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; - -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@Embeddable -public class Password { - - public static final int PASSWORD_LENGTH = 4; - private static final Pattern PASSWORD_PATTERN = Pattern.compile(String.format("^\\d{%d}$", PASSWORD_LENGTH)); - private static final String HASH_ALGORITHM = "SHA-256"; - - private String value; - - public Password(String password) { - validatePassword(password); - this.value = encode(password); - } - - private void validatePassword(String password) { - Matcher matcher = PASSWORD_PATTERN.matcher(password); - if (!matcher.matches()) { - throw new HaengdongException(HaengdongErrorCode.EVENT_PASSWORD_FORMAT_INVALID); - } - } - - private String encode(String rawPassword) { - try { - MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM); - byte[] hashedPassword = digest.digest(rawPassword.getBytes()); - return Base64.getEncoder().encodeToString(hashedPassword); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException("해시 알고리즘이 존재하지 않습니다."); - } - } - - public boolean matches(String rawPassword) { - String hashedPassword = encode(rawPassword); - return value.equals(hashedPassword); - } -} diff --git a/server/src/main/java/server/haengdong/exception/AuthenticationException.java b/server/src/main/java/server/haengdong/exception/AuthenticationException.java deleted file mode 100644 index 2efcb16e7..000000000 --- a/server/src/main/java/server/haengdong/exception/AuthenticationException.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; - -@Getter -public class AuthenticationException extends RuntimeException { - - private final HaengdongErrorCode errorCode; - private final String message; - - public AuthenticationException(HaengdongErrorCode errorCode) { - this(errorCode, errorCode.getMessage()); - } - - public AuthenticationException(HaengdongErrorCode errorCode, String message) { - this.errorCode = errorCode; - this.message = message; - } -} diff --git a/server/src/main/java/server/haengdong/exception/ErrorResponse.java b/server/src/main/java/server/haengdong/exception/ErrorResponse.java deleted file mode 100644 index d0a2b01a0..000000000 --- a/server/src/main/java/server/haengdong/exception/ErrorResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.exception; - -public record ErrorResponse( - HaengdongErrorCode errorCode, - String message -) { - - public static ErrorResponse of(HaengdongErrorCode errorCode) { - return new ErrorResponse(errorCode, errorCode.getMessage()); - } - - public static ErrorResponse of(HaengdongErrorCode errorCode, String message) { - return new ErrorResponse(errorCode, message); - } -} diff --git a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java b/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java deleted file mode 100644 index 0cee7cb4c..000000000 --- a/server/src/main/java/server/haengdong/exception/GlobalExceptionHandler.java +++ /dev/null @@ -1,90 +0,0 @@ -package server.haengdong.exception; - -import jakarta.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.util.stream.Collectors; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.servlet.resource.NoResourceFoundException; - -@Slf4j -@RestControllerAdvice -public class GlobalExceptionHandler { - - private static final String LOG_FORMAT = """ - \n\t{ - "RequestURI": "{} {}", - "RequestBody": {}, - "ErrorMessage": "{}" - \t} - """; - - @ExceptionHandler(AuthenticationException.class) - public ResponseEntity<ErrorResponse> authenticationException(HttpServletRequest req, AuthenticationException e) { - log.warn(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED) - .body(ErrorResponse.of(e.getErrorCode())); - } - - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public ResponseEntity<ErrorResponse> noResourceException(HttpRequestMethodNotSupportedException e) { - log.warn(e.getMessage(), e); - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.REQUEST_METHOD_NOT_SUPPORTED)); - } - - @ExceptionHandler(NoResourceFoundException.class) - public ResponseEntity<ErrorResponse> noResourceException(NoResourceFoundException e) { - log.warn(e.getMessage(), e); - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.NO_RESOURCE_REQUEST)); - } - - @ExceptionHandler(HttpMessageNotReadableException.class) - public ResponseEntity<ErrorResponse> httpMessageNotReadableException(HttpMessageNotReadableException e) { - log.warn(e.getMessage(), e); - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.MESSAGE_NOT_READABLE)); - } - - @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - log.warn(e.getMessage(), e); - String errorMessage = e.getFieldErrors().stream() - .map(error -> error.getField() + " " + error.getDefaultMessage()) - .collect(Collectors.joining(", ")); - - return ResponseEntity.badRequest() - .body(ErrorResponse.of(HaengdongErrorCode.REQUEST_EMPTY, errorMessage)); - } - - @ExceptionHandler(HaengdongException.class) - public ResponseEntity<ErrorResponse> haengdongException(HttpServletRequest req, HaengdongException e) { - log.warn(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); - return ResponseEntity.badRequest() - .body(ErrorResponse.of(e.getErrorCode())); - } - - @ExceptionHandler(Exception.class) - public ResponseEntity<ErrorResponse> handleException(HttpServletRequest req, Exception e) { - log.error(LOG_FORMAT, req.getMethod(), req.getRequestURI(), getRequestBody(req), e.getMessage(), e); - return ResponseEntity.internalServerError() - .body(ErrorResponse.of(HaengdongErrorCode.INTERNAL_SERVER_ERROR)); - } - - private String getRequestBody(HttpServletRequest req) { - try (BufferedReader reader = req.getReader()) { - return reader.lines().collect(Collectors.joining(System.lineSeparator() + "\t")); - } catch (IOException e) { - log.error("Failed to read request body", e); - return ""; - } - } -} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java b/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java deleted file mode 100644 index 475d16c11..000000000 --- a/server/src/main/java/server/haengdong/exception/HaengdongErrorCode.java +++ /dev/null @@ -1,69 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.Password; - -@Getter -public enum HaengdongErrorCode { - - /* Domain */ - - EVENT_NOT_FOUND("존재하지 않는 행사입니다."), - EVENT_NAME_LENGTH_INVALID(String.format("행사 이름은 %d자 이상 %d자 이하만 입력 가능합니다.", - Event.MIN_NAME_LENGTH, - Event.MAX_NAME_LENGTH)), - EVENT_NAME_CONSECUTIVE_SPACES("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s"), - EVENT_PASSWORD_FORMAT_INVALID(String.format("비밀번호는 %d자리 숫자만 가능합니다.", Password.PASSWORD_LENGTH)), - - ACTION_NOT_FOUND("존재하지 않는 액션입니다."), - - MEMBER_NAME_LENGTH_INVALID(String.format("멤버 이름은 %d자 이상 %d자 이하만 입력 가능합니다.", - MemberAction.MIN_NAME_LENGTH, - MemberAction.MAX_NAME_LENGTH)), - MEMBER_NAME_DUPLICATE("중복된 행사 참여 인원 이름이 존재합니다."), - MEMBER_NOT_EXIST("현재 참여하고 있지 않는 인원이 존재합니다."), - MEMBER_ALREADY_EXIST("현재 참여하고 있는 인원이 존재합니다."), - MEMBER_NAME_CHANGE_DUPLICATE("중복된 참여 인원 이름 변경 요청이 존재합니다."), - - MEMBER_ACTION_NOT_FOUND("존재하지 않는 멤버 액션입니다."), - MEMBER_ACTION_STATUS_INVALID("멤버 액션은 IN, OUT만 가능합니다. 입력한 멤버 액션: %s"), - - BILL_ACTION_NOT_FOUND("존재하지 않는 지출 액션입니다."), - BILL_ACTION_TITLE_INVALID(String.format("앞뒤 공백을 제거한 지출 내역 제목은 %d ~ %d자여야 합니다.", - BillAction.MIN_TITLE_LENGTH, - BillAction.MAX_TITLE_LENGTH)), - BILL_ACTION_PRICE_INVALID(String.format("지출 금액은 %,d 이하의 자연수여야 합니다.", BillAction.MAX_PRICE)), - BILL_ACTION_DETAIL_NOT_FOUND("존재하지 않는 참여자 지출입니다."), - BILL_ACTION_PRICE_NOT_MATCHED("지출 총액이 일치하지 않습니다."), - - /* Authentication */ - - PASSWORD_INVALID("비밀번호가 일치하지 않습니다."), - - TOKEN_NOT_FOUND("토큰이 존재하지 않습니다."), - TOKEN_EXPIRED("만료된 토큰입니다."), - TOKEN_INVALID("유효하지 않은 토큰입니다."), - - FORBIDDEN("접근할 수 없는 행사입니다."), - - /* Request Validation */ - - REQUEST_EMPTY("입력 값은 공백일 수 없습니다.") - - /* System */, - - MESSAGE_NOT_READABLE("읽을 수 없는 요청입니다."), - REQUEST_METHOD_NOT_SUPPORTED("지원하지 않는 요청 메서드입니다."), - NO_RESOURCE_REQUEST("존재하지 않는 자원입니다."), - INTERNAL_SERVER_ERROR("서버 내부에서 에러가 발생했습니다."), - ; - - private final String message; - - HaengdongErrorCode(String message) { - this.message = message; - } -} diff --git a/server/src/main/java/server/haengdong/exception/HaengdongException.java b/server/src/main/java/server/haengdong/exception/HaengdongException.java deleted file mode 100644 index b86fe4ffc..000000000 --- a/server/src/main/java/server/haengdong/exception/HaengdongException.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.exception; - -import lombok.Getter; - -@Getter -public class HaengdongException extends RuntimeException { - - private final HaengdongErrorCode errorCode; - private final String message; - - public HaengdongException(HaengdongErrorCode errorCode) { - this(errorCode, errorCode.getMessage()); - } - - public HaengdongException(HaengdongErrorCode errorCode, String message) { - this.errorCode = errorCode; - this.message = message; - } -} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java b/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java deleted file mode 100644 index 4972de48a..000000000 --- a/server/src/main/java/server/haengdong/infrastructure/auth/AuthenticationExtractor.java +++ /dev/null @@ -1,23 +0,0 @@ -package server.haengdong.infrastructure.auth; - -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletRequest; -import java.util.Arrays; -import server.haengdong.exception.AuthenticationException; -import server.haengdong.exception.HaengdongErrorCode; - -public class AuthenticationExtractor { - - public String extract(HttpServletRequest request, String cookieName) { - Cookie[] cookies = request.getCookies(); - if (cookies == null) { - throw new AuthenticationException(HaengdongErrorCode.TOKEN_NOT_FOUND); - } - - return Arrays.stream(cookies) - .filter(cookie -> cookieName.equals(cookie.getName())) - .findFirst() - .orElseThrow(() -> new AuthenticationException(HaengdongErrorCode.TOKEN_NOT_FOUND)) - .getValue(); - } -} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java b/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java deleted file mode 100644 index 18f867601..000000000 --- a/server/src/main/java/server/haengdong/infrastructure/auth/CookieProperties.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.infrastructure.auth; - -import java.time.Duration; -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties("cookie") -public record CookieProperties( - boolean httpOnly, - boolean secure, - String domain, - String path, - String sameSite, - Duration maxAge -) { -} diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java b/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java deleted file mode 100644 index df9ec6a81..000000000 --- a/server/src/main/java/server/haengdong/infrastructure/auth/JwtTokenProvider.java +++ /dev/null @@ -1,54 +0,0 @@ -package server.haengdong.infrastructure.auth; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jws; -import io.jsonwebtoken.JwtException; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import server.haengdong.domain.TokenProvider; - -public class JwtTokenProvider implements TokenProvider { - - private final TokenProperties tokenProperties; - - public JwtTokenProvider(TokenProperties tokenProperties) { - this.tokenProperties = tokenProperties; - } - - @Override - public String createToken(Map<String, Object> payload) { - Claims claims = Jwts.claims(new HashMap<>(payload)); - Date now = new Date(); - Date validity = new Date(now.getTime() + tokenProperties.expireLength()); - - return Jwts.builder() - .setClaims(claims) - .setIssuedAt(now) - .setExpiration(validity) - .signWith(SignatureAlgorithm.HS256, tokenProperties.secretKey()) - .compact(); - } - - @Override - public Map<String, Object> getPayload(String token) { - return Jwts.parser() - .setSigningKey(tokenProperties.secretKey()) - .parseClaimsJws(token) - .getBody(); - } - - @Override - public boolean validateToken(String token) { - try { - Jws<Claims> claims = Jwts.parser().setSigningKey(tokenProperties.secretKey()).parseClaimsJws(token); - - return !claims.getBody().getExpiration().before(new Date()); - } catch (JwtException | IllegalArgumentException e) { - return false; - } - } -} - diff --git a/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java b/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java deleted file mode 100644 index 11dedcdbf..000000000 --- a/server/src/main/java/server/haengdong/infrastructure/auth/TokenProperties.java +++ /dev/null @@ -1,7 +0,0 @@ -package server.haengdong.infrastructure.auth; - -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties("security.jwt.token") -public record TokenProperties(String secretKey, Long expireLength) { -} diff --git a/server/src/main/java/server/haengdong/presentation/ActionController.java b/server/src/main/java/server/haengdong/presentation/ActionController.java deleted file mode 100644 index 657cb567e..000000000 --- a/server/src/main/java/server/haengdong/presentation/ActionController.java +++ /dev/null @@ -1,26 +0,0 @@ -package server.haengdong.presentation; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.ActionService; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.presentation.response.MemberBillReportsResponse; - -@RequiredArgsConstructor -@RestController -public class ActionController { - - private final ActionService actionService; - - @GetMapping("/api/events/{eventId}/actions/reports") - public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVariable("eventId") String token) { - List<MemberBillReportAppResponse> memberBillReports = actionService.getMemberBillReports(token); - - return ResponseEntity.ok() - .body(MemberBillReportsResponse.of(memberBillReports)); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionController.java b/server/src/main/java/server/haengdong/presentation/BillActionController.java deleted file mode 100644 index 56e99337d..000000000 --- a/server/src/main/java/server/haengdong/presentation/BillActionController.java +++ /dev/null @@ -1,55 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.BillActionService; -import server.haengdong.presentation.request.BillActionUpdateRequest; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -@RequiredArgsConstructor -@RestController -public class BillActionController { - - private final BillActionService billActionService; - - @PostMapping("/api/events/{eventId}/bill-actions") - public ResponseEntity<Void> saveAllBillAction( - @PathVariable("eventId") String token, - @Valid @RequestBody BillActionsSaveRequest request - ) { - billActionService.saveAllBillAction(token, request.toAppRequests()); - - return ResponseEntity.ok() - .build(); - } - - @PutMapping("/api/events/{eventId}/bill-actions/{actionId}") - public ResponseEntity<Void> updateBillAction( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId, - @Valid @RequestBody BillActionUpdateRequest request - ) { - billActionService.updateBillAction(token, actionId, request.toAppResponse()); - - return ResponseEntity.ok() - .build(); - } - - @DeleteMapping("/api/events/{eventId}/bill-actions/{actionId}") - public ResponseEntity<Void> deleteBillAction( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId - ) { - billActionService.deleteBillAction(token, actionId); - - return ResponseEntity.ok() - .build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java b/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java deleted file mode 100644 index 5602e6777..000000000 --- a/server/src/main/java/server/haengdong/presentation/BillActionDetailController.java +++ /dev/null @@ -1,42 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.BillActionDetailService; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; -import server.haengdong.presentation.response.BillActionDetailsResponse; - -@RequiredArgsConstructor -@RestController -public class BillActionDetailController { - - private final BillActionDetailService billActionDetailService; - - @GetMapping("/api/events/{eventId}/bill-actions/{actionId}/fixed") - public ResponseEntity<BillActionDetailsResponse> findBillActionDetails( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId - ) { - BillActionDetailsAppResponse appResponse = billActionDetailService.findBillActionDetails(token, actionId); - - return ResponseEntity.ok(BillActionDetailsResponse.of(appResponse)); - } - - @PutMapping("/api/events/{eventId}/bill-actions/{actionId}/fixed") - public ResponseEntity<Void> updateBillActionDetails( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId, - @Valid @RequestBody BillActionDetailsUpdateRequest request - ) { - billActionDetailService.updateBillActionDetails(token, actionId, request.toAppRequest()); - - return ResponseEntity.ok().build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/EventController.java b/server/src/main/java/server/haengdong/presentation/EventController.java deleted file mode 100644 index 34261042f..000000000 --- a/server/src/main/java/server/haengdong/presentation/EventController.java +++ /dev/null @@ -1,120 +0,0 @@ -package server.haengdong.presentation; - -import jakarta.validation.Valid; -import java.util.List; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.http.HttpHeaders; -import org.springframework.http.ResponseCookie; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.AuthService; -import server.haengdong.application.EventService; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.infrastructure.auth.CookieProperties; -import server.haengdong.presentation.request.EventLoginRequest; -import server.haengdong.presentation.request.EventSaveRequest; -import server.haengdong.presentation.request.MemberNamesUpdateRequest; -import server.haengdong.presentation.response.ActionsResponse; -import server.haengdong.presentation.response.EventDetailResponse; -import server.haengdong.presentation.response.EventResponse; -import server.haengdong.presentation.response.MembersResponse; -import server.haengdong.presentation.response.StepsResponse; - -@Slf4j -@RequiredArgsConstructor -@EnableConfigurationProperties(CookieProperties.class) -@RestController -public class EventController { - - private final EventService eventService; - private final AuthService authService; - private final CookieProperties cookieProperties; - - @PostMapping("/api/events") - public ResponseEntity<EventResponse> saveEvent(@Valid @RequestBody EventSaveRequest request) { - EventResponse eventResponse = EventResponse.of(eventService.saveEvent(request.toAppRequest())); - - String jwtToken = authService.createToken(eventResponse.eventId()); - - ResponseCookie responseCookie = createResponseCookie(jwtToken); - return ResponseEntity.ok() - .header(HttpHeaders.SET_COOKIE, responseCookie.toString()) - .body(eventResponse); - } - - @GetMapping("/api/events/{eventId}") - public ResponseEntity<EventDetailResponse> findEvent(@PathVariable("eventId") String token) { - EventDetailResponse eventDetailResponse = EventDetailResponse.of(eventService.findEvent(token)); - - return ResponseEntity.ok(eventDetailResponse); - } - - @GetMapping("/api/events/{eventId}/actions") - public ResponseEntity<StepsResponse> findActions(@PathVariable("eventId") String token) { - StepsResponse stepsResponse = StepsResponse.of(eventService.findActions(token)); - - return ResponseEntity.ok(stepsResponse); - } - - @GetMapping("/api/events/{eventId}/actions/v2") - public ResponseEntity<ActionsResponse> findActions2(@PathVariable("eventId") String token) { - List<ActionAppResponse> actions = eventService.findActions(token); - ActionsResponse actionsResponse = ActionsResponse.of(actions); - - return ResponseEntity.ok(actionsResponse); - } - - @GetMapping("/api/events/{eventId}/members") - public ResponseEntity<MembersResponse> findAllMembers(@PathVariable("eventId") String token) { - MembersResponse response = MembersResponse.of(eventService.findAllMembers(token)); - - return ResponseEntity.ok(response); - } - - @PutMapping("/api/events/{eventId}/members/nameChange") - public ResponseEntity<Void> updateMember( - @PathVariable("eventId") String token, - @Valid @RequestBody MemberNamesUpdateRequest request - ) { - eventService.updateMember(token, request.toAppRequest()); - - return ResponseEntity.ok().build(); - } - - @PostMapping("/api/events/{eventId}/login") - public ResponseEntity<Void> loginEvent( - @PathVariable("eventId") String token, - @Valid @RequestBody EventLoginRequest request - ) { - eventService.validatePassword(request.toAppRequest(token)); - String jwtToken = authService.createToken(token); - - ResponseCookie responseCookie = createResponseCookie(jwtToken); - return ResponseEntity.ok() - .header(HttpHeaders.SET_COOKIE, responseCookie.toString()) - .build(); - } - - @PostMapping("/api/events/{eventId}/auth") - public ResponseEntity<Void> authenticate(@PathVariable("eventId") String token) { - return ResponseEntity.ok().build(); - } - - private ResponseCookie createResponseCookie(String token) { - return ResponseCookie.from(authService.getTokenName(), token) - .httpOnly(cookieProperties.httpOnly()) - .secure(cookieProperties.secure()) - .domain(cookieProperties.domain()) - .path(cookieProperties.path()) - .sameSite(cookieProperties.sameSite()) - .maxAge(cookieProperties.maxAge()) - .build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/MemberActionController.java b/server/src/main/java/server/haengdong/presentation/MemberActionController.java deleted file mode 100644 index 1703245f7..000000000 --- a/server/src/main/java/server/haengdong/presentation/MemberActionController.java +++ /dev/null @@ -1,60 +0,0 @@ -package server.haengdong.presentation; - -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import server.haengdong.application.MemberActionService; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionsSaveRequest; -import server.haengdong.presentation.response.CurrentMembersResponse; - -@RequiredArgsConstructor -@RestController -public class MemberActionController { - - private final MemberActionService memberActionService; - - @PostMapping("/api/events/{eventId}/member-actions") - public ResponseEntity<Void> saveMemberAction( - @PathVariable("eventId") String token, - @RequestBody MemberActionsSaveRequest request - ) { - memberActionService.saveMemberAction(token, request.toAppRequest()); - - return ResponseEntity.ok().build(); - } - - @GetMapping("/api/events/{eventId}/members/current") - public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("eventId") String token) { - List<CurrentMemberAppResponse> currentMembers = memberActionService.getCurrentMembers(token); - - return ResponseEntity.ok() - .body(CurrentMembersResponse.of(currentMembers)); - } - - @DeleteMapping("/api/events/{eventId}/members/{memberName}") - public ResponseEntity<Void> deleteMember( - @PathVariable("eventId") String token, - @PathVariable("memberName") String memberName - ) { - memberActionService.deleteMember(token, memberName); - - return ResponseEntity.ok().build(); - } - - @DeleteMapping("/api/events/{eventId}/member-actions/{actionId}") - public ResponseEntity<Void> deleteMemberAction( - @PathVariable("eventId") String token, - @PathVariable("actionId") Long actionId - ) { - memberActionService.deleteMemberAction(token, actionId); - - return ResponseEntity.ok().build(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java deleted file mode 100644 index 21c4bd60f..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailUpdateRequest.java +++ /dev/null @@ -1,21 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import server.haengdong.application.request.BillActionDetailUpdateAppRequest; - -public record BillActionDetailUpdateRequest( - - @NotBlank(message = "맴버 이름은 공백일 수 없습니다.") - String name, - - @NotNull(message = "지출 금액은 공백일 수 없습니다.") - Long price, - - @NotNull(message = "지출 금액은 공백일 수 없습니다.") - boolean isFixed -) { - public BillActionDetailUpdateAppRequest toAppRequest() { - return new BillActionDetailUpdateAppRequest(this.name, this.price, this.isFixed); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java deleted file mode 100644 index fafbb8fd7..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionDetailsUpdateRequest.java +++ /dev/null @@ -1,16 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import java.util.List; -import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; - -public record BillActionDetailsUpdateRequest( - @Valid @NotEmpty List<BillActionDetailUpdateRequest> members -) { - public BillActionDetailsUpdateAppRequest toAppRequest() { - return new BillActionDetailsUpdateAppRequest(members.stream() - .map(BillActionDetailUpdateRequest::toAppRequest) - .toList()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java deleted file mode 100644 index a47ff8316..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionSaveRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import server.haengdong.application.request.BillActionAppRequest; - -public record BillActionSaveRequest( - - @NotBlank(message = "지출 내역 제목은 공백일 수 없습니다.") - String title, - - @NotNull(message = "지출 금액은 공백일 수 없습니다.") - Long price -) { - - public BillActionAppRequest toAppRequest() { - return new BillActionAppRequest(title, price); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java deleted file mode 100644 index 680006816..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionUpdateRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import server.haengdong.application.request.BillActionUpdateAppRequest; - -public record BillActionUpdateRequest( - - @NotBlank(message = "지출 내역 제목은 공백일 수 없습니다.") - String title, - - @NotNull(message = "지출 금액은 공백일 수 없습니다.") - Long price -) { - public BillActionUpdateAppRequest toAppResponse() { - return new BillActionUpdateAppRequest(title, price); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java deleted file mode 100644 index 6727d4cf1..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/BillActionsSaveRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import java.util.List; -import server.haengdong.application.request.BillActionAppRequest; - -public record BillActionsSaveRequest( - - @Valid @NotEmpty List<BillActionSaveRequest> actions -) { - - public List<BillActionAppRequest> toAppRequests() { - return actions.stream() - .map(BillActionSaveRequest::toAppRequest) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java deleted file mode 100644 index a1286e903..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/EventLoginRequest.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import server.haengdong.application.request.EventLoginAppRequest; - -public record EventLoginRequest( - - @NotBlank(message = "비밀번호는 공백일 수 없습니다.") - String password -) { - public EventLoginAppRequest toAppRequest(String token) { - return new EventLoginAppRequest(token, password); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java deleted file mode 100644 index 6bd7cd006..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/EventSaveRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import server.haengdong.application.request.EventAppRequest; - -public record EventSaveRequest( - - @NotBlank(message = "행사 이름은 공백일 수 없습니다.") - String eventName, - - @NotBlank(message = "비밀번호는 공백일 수 없습니다.") - String password -) { - - public EventAppRequest toAppRequest() { - return new EventAppRequest(eventName, password); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java deleted file mode 100644 index 41e95cc3c..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberActionsSaveRequest.java +++ /dev/null @@ -1,25 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import java.util.List; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; - -public record MemberActionsSaveRequest( - - @NotEmpty - List<String> members, - - @NotBlank(message = "멤버 액션은 공백일 수 없습니다.") - String status -) { - - public MemberActionsSaveAppRequest toAppRequest() { - List<MemberActionSaveAppRequest> appRequests = members.stream() - .map(name -> new MemberActionSaveAppRequest(name, status)) - .toList(); - - return new MemberActionsSaveAppRequest(appRequests); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java deleted file mode 100644 index 3cd2294ca..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberNameUpdateRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.constraints.NotBlank; -import server.haengdong.application.request.MemberNameUpdateAppRequest; - -public record MemberNameUpdateRequest( - - @NotBlank(message = "멤버 이름은 공백일 수 없습니다.") - String before, - - @NotBlank(message = "멤버 이름은 공백일 수 없습니다.") - String after -) { - - public MemberNameUpdateAppRequest toAppRequest() { - return new MemberNameUpdateAppRequest(before, after); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java b/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java deleted file mode 100644 index 872aa55de..000000000 --- a/server/src/main/java/server/haengdong/presentation/request/MemberNamesUpdateRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package server.haengdong.presentation.request; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import java.util.List; -import server.haengdong.application.request.MemberNamesUpdateAppRequest; - -public record MemberNamesUpdateRequest( - @Valid @NotEmpty List<MemberNameUpdateRequest> members -) { - - public MemberNamesUpdateAppRequest toAppRequest() { - return new MemberNamesUpdateAppRequest(members.stream() - .map(MemberNameUpdateRequest::toAppRequest) - .toList()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java deleted file mode 100644 index ea26ea769..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionResponse.java +++ /dev/null @@ -1,26 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.ActionAppResponse; - -public record ActionResponse( - Long actionId, - String name, - Long price, - Long sequence, - boolean isFixed -) { - - public ActionResponse(Long actionId, String name, Long price, Long sequence) { - this(actionId, name, price, sequence, false); - } - - public static ActionResponse of(ActionAppResponse actionAppResponse) { - return new ActionResponse( - actionAppResponse.actionId(), - actionAppResponse.name(), - actionAppResponse.price(), - actionAppResponse.sequence(), - actionAppResponse.isFixed() - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java b/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java deleted file mode 100644 index ea46c5bd9..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionResponse2.java +++ /dev/null @@ -1,22 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.ActionAppResponse; - -public record ActionResponse2( - Long actionId, - String name, - Long price, - Long sequence, - String type -) { - - public static ActionResponse2 of(ActionAppResponse actionAppResponse) { - return new ActionResponse2( - actionAppResponse.actionId(), - actionAppResponse.name(), - actionAppResponse.price(), - actionAppResponse.sequence(), - actionAppResponse.actionType().name() - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java b/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java deleted file mode 100644 index c8ae780e3..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/ActionsResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.ActionAppResponse; - -public record ActionsResponse( - List<ActionResponse2> actions -) { - public static ActionsResponse of(List<ActionAppResponse> actions) { - return new ActionsResponse(actions.stream() - .map(ActionResponse2::of) - .toList()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java deleted file mode 100644 index 10f71b82e..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.BillActionDetailAppResponse; - -public record BillActionDetailResponse( - String name, - Long price, - boolean isFixed -) { - - public static BillActionDetailResponse of(BillActionDetailAppResponse billActionDetailAppResponse) { - return new BillActionDetailResponse( - billActionDetailAppResponse.name(), - billActionDetailAppResponse.price(), - billActionDetailAppResponse.isFixed() - ); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java b/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java deleted file mode 100644 index 182e76db6..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/BillActionDetailsResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import java.util.stream.Collectors; -import server.haengdong.application.response.BillActionDetailsAppResponse; - -public record BillActionDetailsResponse( - List<BillActionDetailResponse> members -) { - - public static BillActionDetailsResponse of(BillActionDetailsAppResponse billActionDetailsAppResponse) { - return billActionDetailsAppResponse.billActionDetailAppResponses().stream() - .map(BillActionDetailResponse::of) - .collect(Collectors.collectingAndThen(Collectors.toList(), BillActionDetailsResponse::new)); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java deleted file mode 100644 index 289cca4fa..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/CurrentMembersResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.CurrentMemberAppResponse; - -public record CurrentMembersResponse(List<String> memberNames) { - - public static CurrentMembersResponse of(List<CurrentMemberAppResponse> currentMembers) { - List<String> responses = currentMembers.stream() - .map(CurrentMemberAppResponse::name) - .toList(); - - return new CurrentMembersResponse(responses); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java deleted file mode 100644 index c18694393..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/EventDetailResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.EventDetailAppResponse; - -public record EventDetailResponse(String eventName) { - - public static EventDetailResponse of(EventDetailAppResponse response) { - return new EventDetailResponse(response.eventName()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java b/server/src/main/java/server/haengdong/presentation/response/EventResponse.java deleted file mode 100644 index 506f5e814..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/EventResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.EventAppResponse; - -public record EventResponse(String eventId) { - - public static EventResponse of(EventAppResponse eventAppResponse) { - return new EventResponse(eventAppResponse.token()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java deleted file mode 100644 index 0ea409202..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package server.haengdong.presentation.response; - -import server.haengdong.application.response.MemberBillReportAppResponse; - -public record MemberBillReportResponse(String name, Long price) { - - public static MemberBillReportResponse of(MemberBillReportAppResponse memberBillReportAppResponse) { - return new MemberBillReportResponse(memberBillReportAppResponse.name(), memberBillReportAppResponse.price()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java b/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java deleted file mode 100644 index d350c4009..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MemberBillReportsResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.MemberBillReportAppResponse; - -public record MemberBillReportsResponse(List<MemberBillReportResponse> reports) { - - public static MemberBillReportsResponse of(List<MemberBillReportAppResponse> memberBillReports) { - List<MemberBillReportResponse> reports = memberBillReports.stream() - .map(MemberBillReportResponse::of) - .toList(); - - return new MemberBillReportsResponse(reports); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java b/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java deleted file mode 100644 index 0947d9e02..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/MembersResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.List; -import server.haengdong.application.response.MembersAppResponse; - -public record MembersResponse( - List<String> memberNames -) { - - public static MembersResponse of(MembersAppResponse response) { - return new MembersResponse(response.memberNames()); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepResponse.java deleted file mode 100644 index 55dd62c58..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/StepResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.ArrayList; -import java.util.List; -import server.haengdong.application.response.ActionAppResponse; - -public record StepResponse( - String stepName, - String type, - List<String> members, - List<ActionResponse> actions -) { - public static StepResponse of(String stepName, List<String> members, List<ActionAppResponse> actions) { - return new StepResponse( - stepName, - actions.get(0).actionTypeName(), - new ArrayList<>(members), - toActionsResponse(actions) - ); - } - - private static List<ActionResponse> toActionsResponse(List<ActionAppResponse> actions) { - return actions.stream() - .map(ActionResponse::of) - .toList(); - } -} diff --git a/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java b/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java deleted file mode 100644 index 5f7573d67..000000000 --- a/server/src/main/java/server/haengdong/presentation/response/StepsResponse.java +++ /dev/null @@ -1,56 +0,0 @@ -package server.haengdong.presentation.response; - -import java.util.ArrayList; -import java.util.List; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.ActionAppResponse.ActionType; - -public record StepsResponse(List<StepResponse> steps) { - - public static StepsResponse of(List<ActionAppResponse> actions) { - List<StepResponse> steps = new ArrayList<>(); - List<String> currentMembers = new ArrayList<>(); - List<List<ActionAppResponse>> groups = createGroups(actions); - - int billStepCount = 0; - for (List<ActionAppResponse> group : groups) { - changeCurrentMembers(group, currentMembers); - if (group.get(0).actionType() == ActionType.BILL) { - billStepCount++; - } - StepResponse stepResponse = StepResponse.of(billStepCount + "차", currentMembers, group); - steps.add(stepResponse); - } - return new StepsResponse(steps); - } - - private static List<List<ActionAppResponse>> createGroups(List<ActionAppResponse> actions) { - List<List<ActionAppResponse>> groups = new ArrayList<>(); - - for (ActionAppResponse action : actions) { - if (groups.isEmpty() || isActionTypeChange(action, groups)) { - groups.add(new ArrayList<>()); - } - groups.get(groups.size() - 1).add(action); - } - - return groups; - } - - private static boolean isActionTypeChange(ActionAppResponse action, List<List<ActionAppResponse>> groups) { - List<ActionAppResponse> currentGroup = groups.get(groups.size() - 1); - return currentGroup.get(0).actionType() != action.actionType(); - } - - private static void changeCurrentMembers(List<ActionAppResponse> group, List<String> currentMembers) { - for (ActionAppResponse action : group) { - if (action.actionType() == ActionType.IN) { - currentMembers.add(action.name()); - continue; - } - if (action.actionType() == ActionType.OUT) { - currentMembers.remove(action.name()); - } - } - } -} diff --git a/server/src/main/resources/application.yml b/server/src/main/resources/application.yml deleted file mode 100644 index 2ae503547..000000000 --- a/server/src/main/resources/application.yml +++ /dev/null @@ -1,66 +0,0 @@ -spring: - datasource: - driver-class-name: org.h2.Driver - url: jdbc:h2:mem:database - username: sa - password: - - h2: - console: - enabled: true - path: /h2-console - - jpa: - hibernate: - ddl-auto: create - properties: - hibernate: - format_sql: true - jdbc.time_zone: Asia/Seoul - show-sql: true - -cors: - max-age: 3600 - allowed-origins: http://localhost:3000, https://haengdong.pro, https://dev.haengdong.pro, https://app.haengdong.pro - -security: - jwt: - token: - secret-key: skdmeejEKJdkDjklDlkj123DKLJ3kDkeDkDKQMEOD1D90D8dE - expire-length: 604800000 # 1주일 - -cookie: - http-only: false - secure: false - path: / - same-site: none - max-age: 7D - -management: - endpoints: - web: - exposure: - include: health, metrics, logfile - -server: - servlet: - encoding: - charset: UTF-8 - enabled: true - force: true - ---- - -spring: - config: - import: classpath:config/application-prod.yml - activate: - on-profile: prod - ---- - -spring: - config: - import: classpath:config/application-dev.yml - activate: - on-profile: dev diff --git a/server/src/main/resources/config b/server/src/main/resources/config deleted file mode 160000 index fa4270674..000000000 --- a/server/src/main/resources/config +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fa42706743e6eb3f4fd8c34618614eff8ae94b3d diff --git a/server/src/main/resources/logback-spring.xml b/server/src/main/resources/logback-spring.xml deleted file mode 100644 index 283b966a3..000000000 --- a/server/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,97 +0,0 @@ -<configuration> - <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> - <encoder> - <!-- 콘솔에 로그 출력 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <appender name="ERROR-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <filter class="ch.qos.logback.classic.filter.LevelFilter"> - <level>ERROR</level> - <onMatch>ACCEPT</onMatch> - <onMismatch>DENY</onMismatch> - </filter> - <file>logs/spring-boot-application-error.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/spring-boot-application-error.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>30</maxHistory> - </rollingPolicy> - <encoder> - <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <appender name="WARN-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <filter class="ch.qos.logback.classic.filter.LevelFilter"> - <level>WARN</level> - <onMatch>ACCEPT</onMatch> - <onMismatch>DENY</onMismatch> - </filter> - <file>logs/spring-boot-application-warn.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/spring-boot-application-warn.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>30</maxHistory> - </rollingPolicy> - <encoder> - <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <appender name="INFO-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <filter class="ch.qos.logback.classic.filter.LevelFilter"> - <level>INFO</level> - <onMatch>ACCEPT</onMatch> - <onMismatch>DENY</onMismatch> - </filter> - <file>logs/spring-boot-application-info.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/spring-boot-application-info.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>30</maxHistory> - </rollingPolicy> - <encoder> - <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <appender name="DEBUG-ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <filter class="ch.qos.logback.classic.filter.LevelFilter"> - <level>DEBUG</level> - <onMatch>ACCEPT</onMatch> - <onMismatch>DENY</onMismatch> - </filter> - <file>logs/spring-boot-application-debug.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>logs/spring-boot-application-debug.%d{yyyy-MM-dd}.log</fileNamePattern> - <maxHistory>30</maxHistory> - </rollingPolicy> - <encoder> - <!-- 날짜, 시간, 로그 레벨, 스레드 이름, 로거 이름, 메시지 형식 --> - <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern> - </encoder> - </appender> - - <springProfile name="default"> - <root level="INFO"> - <appender-ref ref="CONSOLE"/> - </root> - </springProfile> - - <springProfile name="dev"> - <root level="INFO"> - <appender-ref ref="ERROR-ROLLING"/> - <appender-ref ref="WARN-ROLLING"/> - <appender-ref ref="INFO-ROLLING"/> - <appender-ref ref="DEBUG-ROLLING"/> - </root> - </springProfile> - - <springProfile name="prod"> - <root level="ERROR"> - <appender-ref ref="ERROR-ROLLING"/> - </root> - </springProfile> -</configuration> diff --git a/server/src/test/java/server/haengdong/application/ActionServiceTest.java b/server/src/test/java/server/haengdong/application/ActionServiceTest.java deleted file mode 100644 index ee979b278..000000000 --- a/server/src/test/java/server/haengdong/application/ActionServiceTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; -import static server.haengdong.support.fixture.Fixture.BILL_ACTION; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class ActionServiceTest extends ServiceTestSupport { - - @Autowired - private ActionService actionService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(savedEvent, 1L), "소하", IN, 1L), - new MemberAction(new Action(savedEvent, 2L), "감자", IN, 1L), - new MemberAction(new Action(savedEvent, 3L), "쿠키", IN, 1L), - new MemberAction(new Action(savedEvent, 5L), "감자", OUT, 2L) - ); - List<BillAction> billActions = List.of( - new BillAction(new Action(savedEvent, 4L), "뽕족", 60_000L), - new BillAction(new Action(savedEvent, 7L), "인생네컷", 20_000L) - ); - billActions.get(0).addDetails( - List.of( - new BillActionDetail(BILL_ACTION, "소하", 10_000L, false), - new BillActionDetail(BILL_ACTION, "감자", 40_000L, true), - new BillActionDetail(BILL_ACTION, "쿠키", 10_000L, false) - ) - ); - billActions.get(1).addDetails( - List.of( - new BillActionDetail(BILL_ACTION, "소하", 5_000L, true), - new BillActionDetail(BILL_ACTION, "쿠키", 15_000L, true) - ) - ); - memberActionRepository.saveAll(memberActions); - billActionRepository.saveAll(billActions); - - List<MemberBillReportAppResponse> responses = actionService.getMemberBillReports(event.getToken()); - - assertThat(responses) - .hasSize(3) - .extracting(MemberBillReportAppResponse::name, MemberBillReportAppResponse::price) - .containsExactlyInAnyOrder( - tuple("감자", 40_000L), - tuple("쿠키", 25_000L), - tuple("소하", 15_000L) - ); - } - - @DisplayName("존재하지 않는 이벤트의 참여자별 정산 현황을 조회하는 경우 예외가 발생한다.") - @Test - void getMemberBillReports1() { - assertThatThrownBy(() -> actionService.getMemberBillReports("invalid token")) - .isInstanceOf(HaengdongException.class) - .hasMessage(HaengdongErrorCode.EVENT_NOT_FOUND.getMessage()); - } -} diff --git a/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java deleted file mode 100644 index 7074ce846..000000000 --- a/server/src/test/java/server/haengdong/application/BillActionDetailServiceTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.tuple; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.request.BillActionDetailUpdateAppRequest; -import server.haengdong.application.request.BillActionDetailsUpdateAppRequest; -import server.haengdong.application.response.BillActionDetailAppResponse; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionDetailRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class BillActionDetailServiceTest extends ServiceTestSupport { - - @Autowired - private BillActionDetailService billActionDetailService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private BillActionDetailRepository billActionDetailRepository; - - @DisplayName("참여자별 지출 금액을 조회한다.") - @Test - void findBillActionDetailsTest() { - Event event1 = Fixture.EVENT1; - eventRepository.save(event1); - Action action = new Action(event1, 1L); - BillAction billAction = new BillAction(action, "뽕족", 10000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 6000L, true); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 4000L, true); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); - - BillActionDetailsAppResponse response = billActionDetailService.findBillActionDetails( - event1.getToken(), action.getId()); - - assertThat(response.billActionDetailAppResponses()).hasSize(2) - .extracting(BillActionDetailAppResponse::name, BillActionDetailAppResponse::price) - .containsExactly( - tuple("토다리", 6000L), - tuple("쿠키", 4000L) - ); - } - - @DisplayName("지출 금액 수정 요청의 총합이 지출 금액과 일치하지 않으면 예외가 발생한다.") - @Test - void updateBillActionDetailsTest1() { - Event event1 = Fixture.EVENT1; - eventRepository.save(event1); - Action action = new Action(event1, 1L); - BillAction billAction = new BillAction(action, "뽕족", 10000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 5000L, false); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 5000L, false); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); - - BillActionDetailsUpdateAppRequest request = new BillActionDetailsUpdateAppRequest(List.of( - new BillActionDetailUpdateAppRequest("토다리", 3000L, true), - new BillActionDetailUpdateAppRequest("쿠키", 4000L, true) - )); - assertThatCode( - () -> billActionDetailService.updateBillActionDetails(event1.getToken(), action.getId(), request)) - .isInstanceOf(HaengdongException.class) - .hasMessage("지출 총액이 일치하지 않습니다."); - } - - @DisplayName("지출 고정 금액을 수정한다.") - @Test - void updateBillActionDetailsTest2() { - Event event1 = Fixture.EVENT1; - eventRepository.save(event1); - Action action = new Action(event1, 1L); - BillAction billAction = new BillAction(action, "뽕족", 10000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "토다리", 5000L, false); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "쿠키", 5000L, false); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); - - BillActionDetailsUpdateAppRequest request = new BillActionDetailsUpdateAppRequest(List.of( - new BillActionDetailUpdateAppRequest("토다리", 3000L, true), - new BillActionDetailUpdateAppRequest("쿠키", 7000L, true) - )); - billActionDetailService.updateBillActionDetails(event1.getToken(), action.getId(), request); - - List<BillActionDetail> results = billActionDetailRepository.findAll(); - - assertThat(results).hasSize(2) - .extracting(BillActionDetail::getMemberName, BillActionDetail::getPrice) - .containsExactly( - tuple("토다리", 3000L), - tuple("쿠키", 7000L) - ); - } -} diff --git a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java b/server/src/test/java/server/haengdong/application/BillActionServiceTest.java deleted file mode 100644 index 39e52f80c..000000000 --- a/server/src/test/java/server/haengdong/application/BillActionServiceTest.java +++ /dev/null @@ -1,229 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static org.junit.jupiter.api.Assertions.assertAll; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.request.BillActionAppRequest; -import server.haengdong.application.request.BillActionUpdateAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionDetailRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class BillActionServiceTest extends ServiceTestSupport { - - @Autowired - private BillActionService billActionService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private BillActionDetailRepository billActionDetailRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "백호", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "망쵸", MemberActionStatus.IN, 2L); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - - List<BillActionAppRequest> requests = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - billActionService.saveAllBillAction(event.getToken(), requests); - - List<BillAction> actions = billActionRepository.findByAction_Event(savedEvent); - - assertThat(actions).extracting(BillAction::getTitle, BillAction::getPrice, BillAction::getSequence) - .containsExactlyInAnyOrder( - tuple("뽕족", 10_000L, 3L), - tuple("인생맥주", 15_000L, 4L) - ); - } - - @DisplayName("지출 내역을 생성하면 지출 상세 내역이 생성된다.") - @Test - void saveAllBillActionTest1() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "백호", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "망쵸", MemberActionStatus.IN, 2L); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - - List<BillActionAppRequest> request = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - billActionService.saveAllBillAction(event.getToken(), request); - - List<BillActionDetail> billActionDetails = billActionDetailRepository.findAll(); - - assertThat(billActionDetails) - .hasSize(4) - .extracting("memberName", "price") - .containsExactlyInAnyOrder( - tuple("백호", 5_000L), - tuple("망쵸", 5_000L), - tuple("백호", 7_500L), - tuple("망쵸", 7_500L) - ); - } - - @DisplayName("이벤트가 존재하지 않으면 지출 내역을 생성할 수 없다.") - @Test - void saveAllBillAction1() { - List<BillActionAppRequest> requests = List.of( - new BillActionAppRequest("뽕족", 10_000L), - new BillActionAppRequest("인생맥주", 15_000L) - ); - - assertThatThrownBy(() -> billActionService.saveAllBillAction("token", requests)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("지출 액션을 수정한다.") - @Test - void updateBillAction() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - Action action = Action.createFirst(savedEvent); - BillAction billAction = new BillAction(action, "뽕족", 10_000L); - BillAction savedBillAction = billActionRepository.save(billAction); - - Long actionId = savedBillAction.getAction().getId(); - BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); - - billActionService.updateBillAction(event.getToken(), actionId, request); - - BillAction updatedBillAction = billActionRepository.findById(savedBillAction.getId()).get(); - - assertAll( - () -> assertThat(updatedBillAction.getTitle()).isEqualTo("인생맥주"), - () -> assertThat(updatedBillAction.getPrice()).isEqualTo(20_000L) - ); - } - - @DisplayName("행사에 속하지 않은 지출 액션은 수정할 수 없다.") - @Test - void updateBillAction1() { - Event event1 = Fixture.EVENT1; - Event event2 = Fixture.EVENT2; - Event savedEvent1 = eventRepository.save(event1); - Event savedEvent2 = eventRepository.save(event2); - Action action1 = Action.createFirst(savedEvent1); - Action action2 = Action.createFirst(savedEvent2); - BillAction billAction1 = new BillAction(action1, "뽕족", 10_000L); - BillAction billAction2 = new BillAction(action2, "뽕족", 10_000L); - BillAction savedBillAction1 = billActionRepository.save(billAction1); - billActionRepository.save(billAction2); - - Long actionId = savedBillAction1.getAction().getId(); - BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); - - assertThatThrownBy(() -> billActionService.updateBillAction(event2.getToken(), actionId, request)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("지출 내역 금액을 변경하면 지출 디테일이 초기화 된다.") - @Test - void updateBillAction2() { - Event event = Fixture.EVENT1; - Event savedEvent = eventRepository.save(event); - Action action = Action.createFirst(savedEvent); - BillAction billAction = new BillAction(action, "뽕족", 10_000L); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "감자", 3000L, true); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "고구마", 2000L, true); - BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "당근", 3000L, true); - BillActionDetail billActionDetail4 = new BillActionDetail(billAction, "양파", 2000L, true); - billAction.addDetails(List.of(billActionDetail1, billActionDetail2, billActionDetail3, billActionDetail4)); - BillAction savedBillAction = billActionRepository.save(billAction); - - Long actionId = savedBillAction.getAction().getId(); - BillActionUpdateAppRequest request = new BillActionUpdateAppRequest("인생맥주", 20_000L); - - billActionService.updateBillAction(event.getToken(), actionId, request); - - BillAction updatedBillAction = billActionRepository.findById(savedBillAction.getId()).get(); - List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(updatedBillAction); - - assertThat(billActionDetails).hasSize(4) - .extracting("memberName", "price") - .containsExactlyInAnyOrder( - tuple("감자", 5000L), - tuple("고구마", 5000L), - tuple("당근", 5000L), - tuple("양파", 5000L) - ); - } - - @DisplayName("지출 내역을 삭제한다.") - @Test - void deleteBillAction() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - BillAction billAction = new BillAction(new Action(event, 1L), "커피", 50_900L); - billActionRepository.save(billAction); - Long actionId = billAction.getAction().getId(); - - billActionService.deleteBillAction(event.getToken(), actionId); - - assertThat(billActionRepository.findById(billAction.getId())).isEmpty(); - } - - @DisplayName("지출 내역을 삭제하면 지출 상세도 삭제된다.") - @Test - void deleteBillActionTest1() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "백호", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "망쵸", MemberActionStatus.IN, 2L); - BillAction billAction = new BillAction(new Action(event, 3L), "커피", 50_900L); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "백호", 25_450L, false); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "망쵸", 25_450L, false); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - billActionRepository.save(billAction); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2)); - Long actionId = billAction.getAction().getId(); - - billActionService.deleteBillAction(event.getToken(), actionId); - - assertThat(billActionDetailRepository.findAll()).isEmpty(); - } - - @DisplayName("지출 내역 삭제 시 행사가 존재하지 않으면 예외가 발생한다.") - @Test - void deleteBillAction1() { - assertThatThrownBy(() -> billActionService.deleteBillAction("소하망쵸", 1L)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/EventServiceTest.java b/server/src/test/java/server/haengdong/application/EventServiceTest.java deleted file mode 100644 index 407fa1457..000000000 --- a/server/src/test/java/server/haengdong/application/EventServiceTest.java +++ /dev/null @@ -1,231 +0,0 @@ -package server.haengdong.application; - - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.BDDMockito.given; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.request.MemberNameUpdateAppRequest; -import server.haengdong.application.request.MemberNamesUpdateAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.application.response.MembersAppResponse; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.domain.event.EventTokenProvider; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class EventServiceTest extends ServiceTestSupport { - - @Autowired - private EventService eventService; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private MemberActionRepository memberActionRepository; - - @MockBean - private EventTokenProvider eventTokenProvider; - - @DisplayName("행사를 생성한다") - @Test - void saveEventTest() { - EventAppRequest request = new EventAppRequest("test", "1234"); - given(eventTokenProvider.createToken()).willReturn("TOKEN"); - - EventAppResponse response = eventService.saveEvent(request); - - assertThat(response.token()).isEqualTo("TOKEN"); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - - EventDetailAppResponse eventDetailAppResponse = eventService.findEvent(event.getToken()); - - assertThat(eventDetailAppResponse.eventName()).isEqualTo(event.getName()); - } - - @DisplayName("행사에 속한 모든 액션을 조회한다.") - @Test - void findActionsTest() { - Event event = Fixture.EVENT1; - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", IN, 1L); - Action action1 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "쿠키", IN, 1L); - Action action2 = new Action(event, 3L); - BillAction billAction = new BillAction(action2, "뽕나무쟁이족발", 30000L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction, memberAction1)); - billActionRepository.save(billAction); - - List<ActionAppResponse> actionAppResponses = eventService.findActions(event.getToken()); - - assertThat(actionAppResponses).hasSize(3) - .extracting(ActionAppResponse::actionId, - ActionAppResponse::name, - ActionAppResponse::price, - ActionAppResponse::sequence, - ActionAppResponse::actionTypeName) - .containsExactly( - tuple(1L, "토다리", null, 1L, "IN"), - tuple(2L, "쿠키", null, 2L, "IN"), - tuple(3L, "뽕나무쟁이족발", 30000L, 3L, "BILL") - ); - } - - @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") - @Test - void findAllMembersTest() { - Event event = Fixture.EVENT1; - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - Action action3 = new Action(event, 3L); - Action action4 = new Action(event, 4L); - BillAction billAction = new BillAction(action3, "뽕나무쟁이족발", 30000L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(action4, "쿠키", OUT, 1L); - eventRepository.save(event); - billActionRepository.save(billAction); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MembersAppResponse membersAppResponse = eventService.findAllMembers(event.getToken()); - - assertThat(membersAppResponse.memberNames()).containsExactlyInAnyOrder("토다리", "쿠키"); - } - - @DisplayName("행사 참여 인원들의 이름을 변경한다.") - @Test - void updateMember() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "쿠키", OUT, 3L); - MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "쿠키", IN, 4L); - MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "쿠키", OUT, 5L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of( - memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6 - )); - - eventService.updateMember(event.getToken(), new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), - new MemberNameUpdateAppRequest("토다리", "토쟁이") - ))); - - List<MemberAction> foundMemberActions = memberActionRepository.findAllByEvent(event); - assertThat(foundMemberActions) - .extracting(MemberAction::getId, MemberAction::getMemberName) - .contains( - tuple(memberAction1.getId(), "토쟁이"), - tuple(memberAction2.getId(), "쿡쿡"), - tuple(memberAction3.getId(), "웨디"), - tuple(memberAction4.getId(), "쿡쿡"), - tuple(memberAction5.getId(), "쿡쿡"), - tuple(memberAction6.getId(), "쿡쿡") - ); - } - - @DisplayName("이미 존재하는 인원의 이름으로 변경할 수 없다.") - @Test - void updateMember1() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), - new MemberNameUpdateAppRequest("웨디", "토다리") - )); - - assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("존재하지 않는 인원은 변경할 수 없다.") - @Test - void updateMember2() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿡쿡", "토쟁이"), - new MemberNameUpdateAppRequest("웨디", "말복") - )); - - assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("변경 전 참여 인원 이름이 중복될 수 없다.") - @Test - void updateMember3() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), - new MemberNameUpdateAppRequest("쿠키", "토쟁이") - )); - - assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("변경 후 참여 인원 이름이 중복될 수 없다.") - @Test - void updateMember4() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L); - eventRepository.save(event); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3)); - - MemberNamesUpdateAppRequest appRequest = new MemberNamesUpdateAppRequest(List.of( - new MemberNameUpdateAppRequest("쿠키", "쿡쿡"), - new MemberNameUpdateAppRequest("토다리", "쿡쿡") - )); - - assertThatThrownBy(() -> eventService.updateMember(event.getToken(), appRequest)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java b/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java deleted file mode 100644 index c04f06026..000000000 --- a/server/src/test/java/server/haengdong/application/MemberActionFactoryTest.java +++ /dev/null @@ -1,223 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.CurrentMembers; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class MemberActionFactoryTest extends ServiceTestSupport { - - @Autowired - private MemberActionFactory memberActionFactory; - - @Autowired - private MemberActionRepository memberActionRepository; - - @Autowired - private EventRepository eventRepository; - - @DisplayName("이전 멤버 액션이 시퀀스 기준으로 정렬되지 않은 상태에서 새로운 멤버 액션 요청을 검증한다.") - @Test - void createMemberActionsTest() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action1 = new Action(event, 1L); - Action action2 = new Action(event, 2L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); - MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); - memberActionRepository.saveAll(List.of(memberAction1, memberAction2)); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - - List<MemberAction> unorderedMemberActions = List.of(memberAction2, memberAction1); - CurrentMembers currentMembers = CurrentMembers.of(unorderedMemberActions); - Action startAction = new Action(event, 3L); - - assertThatThrownBy(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("인원 변동 액션을 생성한다.") - @Test - void createMemberActionsTest1() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest memberActionsSaveAppRequest = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - Action startAction = new Action(event, 2L); - - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - List<MemberAction> memberActions = memberActionFactory.createMemberActions(memberActionsSaveAppRequest, - currentMembers, startAction - ); - - assertThat(memberActions).hasSize(1) - .extracting(MemberAction::getAction, MemberAction::getMemberName, MemberAction::getStatus) - .containsExactly( - tuple(startAction, "토다리", MemberActionStatus.OUT) - ); - } - - @DisplayName("현재 행사에 참여 중인 경우에 퇴장할 수 있다.") - @Test - void createMemberActionsTest2() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "OUT"))); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") - @Test - void createMemberActionsTest3() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action1 = new Action(event, 1L); - MemberAction memberAction1 = new MemberAction(action1, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction1); - Action action2 = new Action(event, 2L); - MemberAction memberAction2 = new MemberAction(action2, "토다리", MemberActionStatus.OUT, 2L); - memberActionRepository.save(memberAction2); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("토다리", "IN"))); - Action startAction = new Action(event, 3L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction1, memberAction2)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장한 적 없는 경우에 입장할 수 있다.") - @Test - void createMemberActionsTest4() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "토다리", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") - @Test - void createMemberActionTest5() { - Event event = eventRepository.save(Fixture.EVENT1); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "OUT"))); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of()); - - assertThatCode( - () -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("행사에 이미 참여 중인 경우 다시 입장할 수 없다.") - @Test - void createMemberActionTest6() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("쿠키", "IN"))); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 동시에 여러 번 입장할 수 없다.") - @Test - void createMemberActionTest7() { - Event event = eventRepository.save(Fixture.EVENT1); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of( - new MemberActionSaveAppRequest("쿠키", "IN"), - new MemberActionSaveAppRequest("쿠키", "IN") - )); - Action startAction = new Action(event, 1L); - CurrentMembers currentMembers = CurrentMembers.of(List.of()); - - assertThatCode( - () -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 동시에 여러 번 퇴장할 수 없다.") - @Test - void createMemberActionTest8() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of( - new MemberActionSaveAppRequest("쿠키", "OUT"), - new MemberActionSaveAppRequest("쿠키", "OUT") - )); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("한 명의 사용자는 입장과 퇴장을 동시에 할 수 없다.") - @Test - void createMemberActionTest9() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "쿠키", MemberActionStatus.IN, 1L); - memberActionRepository.save(memberAction); - - MemberActionsSaveAppRequest request = new MemberActionsSaveAppRequest( - List.of( - new MemberActionSaveAppRequest("쿠키", "IN"), - new MemberActionSaveAppRequest("쿠키", "OUT") - )); - Action startAction = new Action(event, 2L); - CurrentMembers currentMembers = CurrentMembers.of(List.of(memberAction)); - - assertThatCode(() -> memberActionFactory.createMemberActions(request, currentMembers, startAction)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java b/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java deleted file mode 100644 index b6d29444c..000000000 --- a/server/src/test/java/server/haengdong/application/MemberActionServiceTest.java +++ /dev/null @@ -1,251 +0,0 @@ -package server.haengdong.application; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.groups.Tuple.tuple; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import server.haengdong.application.request.MemberActionSaveAppRequest; -import server.haengdong.application.request.MemberActionsSaveAppRequest; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.action.BillActionDetail; -import server.haengdong.domain.action.BillActionDetailRepository; -import server.haengdong.domain.action.BillActionRepository; -import server.haengdong.domain.action.MemberAction; -import server.haengdong.domain.action.MemberActionRepository; -import server.haengdong.domain.action.MemberActionStatus; -import server.haengdong.domain.event.Event; -import server.haengdong.domain.event.EventRepository; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class MemberActionServiceTest extends ServiceTestSupport { - - @Autowired - private MemberActionService memberActionService; - - @Autowired - private MemberActionRepository memberActionRepository; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private BillActionRepository billActionRepository; - - @Autowired - private BillActionDetailRepository billActionDetailRepository; - - @DisplayName("현재 행사에 참여하고 있는 경우에 나갈 수 있다.") - @Test - void saveMemberActionTest() { - Event event = eventRepository.save(Fixture.EVENT1); - Action action = new Action(event, 1L); - MemberAction memberAction = new MemberAction(action, "망쵸", IN, 1L); - memberActionRepository.save(memberAction); - - assertThatCode(() -> memberActionService.saveMemberAction(event.getToken(), new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("망쵸", "OUT"))))) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에서 퇴장한 경우에 입장할 수 있다.") - @Test - void saveMemberActionTest1() { - Event event = eventRepository.save(Fixture.EVENT1); - Action actionOne = new Action(event, 1L); - MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", IN, 1L); - memberActionRepository.save(memberActionOne); - - Action actionTwo = new Action(event, 2L); - MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", OUT, 1L); - memberActionRepository.save(memberActionTwo); - - assertThatCode(() -> memberActionService.saveMemberAction(event.getToken(), new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("망쵸", "IN"))))) - .doesNotThrowAnyException(); - } - - @DisplayName("행사에 입장하지 않았을 경우 퇴장할 수 없다.") - @Test - void saveMemberActionTest2() { - MemberActionsSaveAppRequest appRequest = new MemberActionsSaveAppRequest( - List.of(new MemberActionSaveAppRequest("TOKEN", "OUT"))); - - assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", appRequest)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("이벤트가 없으면 현재 참여 인원을 조회할 수 없다.") - @Test - void getCurrentMembers() { - assertThatThrownBy(() -> memberActionService.getCurrentMembers("token")) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") - @Test - void deleteMember() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "참여자", IN, 1L); - MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "토다리", IN, 1L); - MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "쿠키", IN, 1L); - MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "소하", IN, 1L); - MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "웨디", IN, 1L); - MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "참여자", OUT, 1L); - memberActionRepository.saveAll( - List.of(memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6)); - - Event event2 = Fixture.EVENT2; - eventRepository.save(event2); - Action action2 = Action.createFirst(event2); - MemberAction anotherMemberAction = new MemberAction(action2, "참여자", IN, 1L); - memberActionRepository.save(anotherMemberAction); - - memberActionService.deleteMember(event.getToken(), "참여자"); - - List<MemberAction> memberActions = memberActionRepository.findAll(); - - assertThat(memberActions).hasSize(5) - .extracting("memberName", "status") - .containsExactly( - tuple("토다리", IN), - tuple("쿠키", IN), - tuple("소하", IN), - tuple("웨디", IN), - tuple("참여자", IN) - ); - } - - @DisplayName("이벤트에 속한 멤버을 삭제하면 전체 지출 내역 디테일이 초기화된다.") - @Test - void deleteMember1() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); - Action targetAction = new Action(event, 2L); - MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); - MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); - MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); - MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "감자", IN, 5L); - memberActionRepository.saveAll( - List.of(memberAction1, - memberAction2, - memberAction3, - memberAction4, - memberAction5 - ) - ); - BillAction billAction = new BillAction(new Action(event, 6L), "뽕족", 100_000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "쿠키", 40_000L, true); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "웨디", 30_000L, false); - BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "감자", 30_000L, false); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2, billActionDetail3)); - List<BillActionDetail> allByBillAction = billActionDetailRepository.findAllByBillAction(billAction); - System.out.println("allByBillAction = " + allByBillAction.isEmpty()); - - memberActionService.deleteMember(event.getToken(), "쿠키"); - - List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(billAction); - - assertThat(billActionDetails).hasSize(2) - .extracting("memberName", "price") - .containsExactlyInAnyOrder( - tuple("웨디", 50_000L), - tuple("감자", 50_000L) - ); - } - - @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") - @Test - void deleteMemberAction() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); - Action targetAction = new Action(event, 2L); - MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); - MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); - MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); - MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "토다리", IN, 5L); - MemberAction memberAction6 = createMemberAction(new Action(event, 6L), "토다리", OUT, 6L); - MemberAction memberAction7 = createMemberAction(new Action(event, 7L), "쿠키", OUT, 7L); - memberActionRepository.saveAll( - List.of(memberAction1, - memberAction2, - memberAction3, - memberAction4, - memberAction5, - memberAction6, - memberAction7) - ); - - memberActionService.deleteMemberAction(event.getToken(), targetAction.getId()); - List<MemberAction> memberActions = memberActionRepository.findAll(); - - assertThat(memberActions).hasSize(4) - .extracting("id", "memberName", "status") - .containsExactly( - tuple(memberAction1.getId(), "토다리", IN), - tuple(memberAction3.getId(), "쿠키", IN), - tuple(memberAction4.getId(), "웨디", IN), - tuple(memberAction7.getId(), "쿠키", OUT) - ); - } - - @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후 지출 내역 디테일이 초기화된다.") - @Test - void deleteMemberAction1() { - Event event = Fixture.EVENT1; - eventRepository.save(event); - MemberAction memberAction1 = createMemberAction(new Action(event, 1L), "토다리", IN, 1L); - Action targetAction = new Action(event, 2L); - MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L); - MemberAction memberAction3 = createMemberAction(new Action(event, 3L), "쿠키", IN, 3L); - MemberAction memberAction4 = createMemberAction(new Action(event, 4L), "웨디", IN, 4L); - MemberAction memberAction5 = createMemberAction(new Action(event, 5L), "감자", IN, 5L); - memberActionRepository.saveAll( - List.of(memberAction1, - memberAction2, - memberAction3, - memberAction4, - memberAction5 - ) - ); - BillAction billAction = new BillAction(new Action(event, 6L), "뽕족", 100_000L); - billActionRepository.save(billAction); - BillActionDetail billActionDetail1 = new BillActionDetail(billAction, "쿠키", 40_000L, true); - BillActionDetail billActionDetail2 = new BillActionDetail(billAction, "웨디", 30_000L, false); - BillActionDetail billActionDetail3 = new BillActionDetail(billAction, "감자", 30_000L, false); - billActionDetailRepository.saveAll(List.of(billActionDetail1, billActionDetail2, billActionDetail3)); - - memberActionService.deleteMemberAction(event.getToken(), targetAction.getId()); - List<BillActionDetail> billActionDetails = billActionDetailRepository.findAllByBillAction(billAction); - - assertThat(billActionDetails).hasSize(4) - .extracting("memberName", "price") - .containsExactlyInAnyOrder( - tuple("토다리", 25_000L), - tuple("쿠키", 25_000L), - tuple("웨디", 25_000L), - tuple("감자", 25_000L) - ); - } - - private MemberAction createMemberAction( - Action action, - String memberName, - MemberActionStatus memberActionStatus, - long memberGroupId - ) { - return new MemberAction(action, memberName, memberActionStatus, memberGroupId); - } -} diff --git a/server/src/test/java/server/haengdong/application/ServiceTestSupport.java b/server/src/test/java/server/haengdong/application/ServiceTestSupport.java deleted file mode 100644 index b0e2db0a6..000000000 --- a/server/src/test/java/server/haengdong/application/ServiceTestSupport.java +++ /dev/null @@ -1,11 +0,0 @@ -package server.haengdong.application; - -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import server.haengdong.support.extension.DatabaseCleanerExtension; - -@ExtendWith(DatabaseCleanerExtension.class) -@SpringBootTest(webEnvironment= WebEnvironment.NONE) -abstract class ServiceTestSupport { -} diff --git a/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java deleted file mode 100644 index 39c2d0bb8..000000000 --- a/server/src/test/java/server/haengdong/docs/ActionControllerDocsTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package server.haengdong.docs; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import server.haengdong.application.ActionService; -import server.haengdong.application.response.MemberBillReportAppResponse; -import server.haengdong.presentation.ActionController; - -class ActionControllerDocsTest extends RestDocsSupport { - - private final ActionService actionService = mock(ActionService.class); - - @Override - protected Object initController() { - return new ActionController(actionService); - } - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() throws Exception { - List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( - new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); - - given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/actions/reports", "망쵸토큰") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))) - .andDo( - document("getMemberBillReports", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("reports").type(JsonFieldType.ARRAY).description("전체 정산 현황 목록"), - fieldWithPath("reports[0].name").type(JsonFieldType.STRING) - .description("참여자 이름"), - fieldWithPath("reports[0].price").type(JsonFieldType.NUMBER) - .description("참여자 정산 금액") - )) - ); - } -} diff --git a/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java deleted file mode 100644 index 7ed6fe6c4..000000000 --- a/server/src/test/java/server/haengdong/docs/BillActionControllerDocsTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package server.haengdong.docs; - -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.application.BillActionService; -import server.haengdong.presentation.BillActionController; -import server.haengdong.presentation.request.BillActionSaveRequest; -import server.haengdong.presentation.request.BillActionUpdateRequest; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -class BillActionControllerDocsTest extends RestDocsSupport { - - private final BillActionService billActionService = mock(BillActionService.class); - - @Override - protected Object initController() { - return new BillActionController(billActionService); - } - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("뽕족", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "쿠키토큰"; - - mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) - .contentType(MediaType.APPLICATION_JSON) - .cookie(EVENT_COOKIE) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo(document("createBillActions", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), - requestFields( - fieldWithPath("actions").description("생성할 지출 액션 목록"), - fieldWithPath("actions[0].title").description("생성할 지출 액션의 제목"), - fieldWithPath("actions[0].price").description("생성할 지출 액션의 금액") - ) - )); - } - - @DisplayName("지출 액션을 수정한다.") - @Test - void updateBillAction() throws Exception { - BillActionUpdateRequest request = new BillActionUpdateRequest("뽕족", 10_000L); - - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "웨디토큰"; - - mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1L) - .cookie(EVENT_COOKIE) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo(document("updateBillAction", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("지출 액션 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), - requestFields( - fieldWithPath("title").description("수정할 지출 액션의 제목"), - fieldWithPath("price").description("수정할 지출 액션의 금액") - ) - )); - } - - @DisplayName("지출 내역을 삭제한다.") - @Test - void deleteBillAction() throws Exception { - String eventId = "토다리토큰"; - - mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1) - .cookie(EVENT_COOKIE) - ) - .andDo(print()) - .andExpect(status().isOk()) - .andDo(document("deleteBillAction", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("지출 액션 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ) - )); - } -} diff --git a/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java deleted file mode 100644 index f492195f3..000000000 --- a/server/src/test/java/server/haengdong/docs/BillActionDetailControllerDocsTest.java +++ /dev/null @@ -1,127 +0,0 @@ -package server.haengdong.docs; - -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; -import server.haengdong.application.BillActionDetailService; -import server.haengdong.application.response.BillActionDetailAppResponse; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.presentation.BillActionDetailController; -import server.haengdong.presentation.request.BillActionDetailUpdateRequest; -import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; - -public class BillActionDetailControllerDocsTest extends RestDocsSupport { - - private final BillActionDetailService billActionDetailService = mock(BillActionDetailService.class); - - @Override - protected Object initController() { - return new BillActionDetailController(billActionDetailService); - } - - @DisplayName("참여자별 지출 금액을 조회한다.") - @Test - void findBillActionDetailsTest() throws Exception { - BillActionDetailsAppResponse appResponse = new BillActionDetailsAppResponse( - List.of(new BillActionDetailAppResponse("토다리", 1000L, false))); - given(billActionDetailService.findBillActionDetails(anyString(), anyLong())) - .willReturn(appResponse); - - mockMvc.perform(get("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.members").isArray()) - .andExpect(jsonPath("$.members[0].name").value("토다리")) - .andExpect(jsonPath("$.members[0].price").value(1000L)) - .andExpect(jsonPath("$.members[0].isFixed").value(false)) - .andDo( - document("findBillActionDetailsTest", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("액션 ID") - ), requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), responseFields( - fieldWithPath("members").type(JsonFieldType.ARRAY) - .description("전체 정산 수정 요청 목록"), - fieldWithPath("members[0].name").type(JsonFieldType.STRING) - .description("참여자 이름"), - fieldWithPath("members[0].price").type(JsonFieldType.NUMBER) - .description("참여자 정산 금액"), - fieldWithPath("members[0].isFixed").type(JsonFieldType.BOOLEAN) - .description("참여자 정산 금액 수정 여부") - ) - ) - ); - } - - @DisplayName("참여자별 지출 금액을 수정한다.") - @Test - void updateBillActionDetailsTest() throws Exception { - List<BillActionDetailUpdateRequest> billActionDetailUpdateRequests = List.of( - new BillActionDetailUpdateRequest("소하", 10000L, true), - new BillActionDetailUpdateRequest("웨디", 20000L, true) - ); - BillActionDetailsUpdateRequest request = new BillActionDetailsUpdateRequest( - billActionDetailUpdateRequests); - - String json = objectMapper.writeValueAsString(request); - - mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) - .cookie(EVENT_COOKIE) - .contentType(MediaType.APPLICATION_JSON) - .content(json)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("updateBillActionDetailsTest", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("액션 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), - requestFields( - fieldWithPath("members").type(JsonFieldType.ARRAY) - .description("전체 정산 수정 요청 목록"), - fieldWithPath("members[0].name").type(JsonFieldType.STRING) - .description("참여자 이름"), - fieldWithPath("members[0].price").type(JsonFieldType.NUMBER) - .description("참여자 정산 금액"), - fieldWithPath("members[0].isFixed").type(JsonFieldType.BOOLEAN) - .description("참여자 정산 금액 수정 여부") - ) - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java deleted file mode 100644 index 88de2a3a6..000000000 --- a/server/src/test/java/server/haengdong/docs/EventControllerDocsTest.java +++ /dev/null @@ -1,381 +0,0 @@ -package server.haengdong.docs; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.cookies.CookieDocumentation.responseCookies; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.put; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; - -import java.time.Duration; -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; -import server.haengdong.application.AuthService; -import server.haengdong.application.EventService; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.ActionAppResponse.ActionType; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.application.response.MembersAppResponse; -import server.haengdong.infrastructure.auth.CookieProperties; -import server.haengdong.presentation.EventController; -import server.haengdong.presentation.request.EventLoginRequest; -import server.haengdong.presentation.request.EventSaveRequest; -import server.haengdong.presentation.request.MemberNameUpdateRequest; -import server.haengdong.presentation.request.MemberNamesUpdateRequest; - -public class EventControllerDocsTest extends RestDocsSupport { - - private final EventService eventService = mock(EventService.class); - private final AuthService authService = mock(AuthService.class); - private final CookieProperties cookieProperties = new CookieProperties( - true, true, "domain", "path", "none", Duration.ofDays(7) - ); - - @Override - protected Object initController() { - return new EventController(eventService, authService, cookieProperties); - } - - @DisplayName("이벤트를 생성한다.") - @Test - void saveEvent() throws Exception { - EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리", "0987"); - String requestBody = objectMapper.writeValueAsString(eventSaveRequest); - String eventId = "쿠키 토큰"; - EventAppResponse eventAppResponse = new EventAppResponse(eventId); - given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); - given(authService.createToken(eventId)).willReturn("jwtToken"); - given(authService.getTokenName()).willReturn("eventToken"); - - mockMvc.perform(post("/api/events") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(cookie().value("eventToken", "jwtToken")) - .andExpect(jsonPath("$.eventId").value("쿠키 토큰")) - .andDo( - document("createEvent", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - requestFields( - fieldWithPath("eventName").type(JsonFieldType.STRING).description("행사 이름"), - fieldWithPath("password").type(JsonFieldType.STRING).description("행사 비밀 번호") - ), - responseFields( - fieldWithPath("eventId").type(JsonFieldType.STRING) - .description("행사 ID") - ), - responseCookies( - cookieWithName("eventToken").description("행사 관리자용 토큰") - ) - ) - ); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() throws Exception { - String eventId = "망쵸토큰"; - EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); - given(eventService.findEvent(eventId)).willReturn(eventDetailAppResponse); - - mockMvc.perform(get("/api/events/{eventId}", eventId)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventName").value("행동대장 회식")) - .andDo( - document("getEvent", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("eventName").type(JsonFieldType.STRING).description("행사 이름") - ) - ) - ); - } - - @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") - @Test - void findAllMembersTest() throws Exception { - MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("토다리", "쿠키")); - given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); - - mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.memberNames").isArray()) - .andExpect(jsonPath("$.memberNames[0]").value("토다리")) - .andExpect(jsonPath("$.memberNames[1]").value("쿠키")) - .andDo( - document("findAllEventMember", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("memberNames").type(JsonFieldType.ARRAY) - .description("행사 참여자 목록") - ) - ) - ); - } - - @DisplayName("행사 참여 인원의 이름을 수정한다.") - @Test - void updateMember() throws Exception { - String token = "TOKEN"; - MemberNamesUpdateRequest memberNameUpdateRequest = new MemberNamesUpdateRequest(List.of( - new MemberNameUpdateRequest("토다링", "토쟁이"), - new MemberNameUpdateRequest("감자", "고구마") - )); - - String requestBody = objectMapper.writeValueAsString(memberNameUpdateRequest); - - mockMvc.perform(put("/api/events/{eventId}/members/nameChange", token) - .cookie(EVENT_COOKIE) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("updateEventMemberName", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰") - ), - requestFields( - fieldWithPath("members").type(JsonFieldType.ARRAY).description("수정할 참여자 목록"), - fieldWithPath("members[].before").type(JsonFieldType.STRING) - .description("수정 전 참여자 이름"), - fieldWithPath("members[].after").type(JsonFieldType.STRING) - .description("수정 후 참여자 이름") - ) - ) - ); - } - - @DisplayName("행사 어드민이 로그인한다.") - @Test - void loginEvent() throws Exception { - String token = "TOKEN"; - EventLoginRequest eventLoginRequest = new EventLoginRequest("1234"); - String requestBody = objectMapper.writeValueAsString(eventLoginRequest); - given(authService.createToken(token)).willReturn("jwtToken"); - given(authService.getTokenName()).willReturn("eventToken"); - - mockMvc.perform(post("/api/events/{eventId}/login", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(cookie().value("eventToken", "jwtToken")) - .andExpect(status().isOk()) - .andDo( - document("eventLogin", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestFields( - fieldWithPath("password").type(JsonFieldType.STRING) - .description("행사 비밀 번호") - ), - responseCookies( - cookieWithName("eventToken").description("행사 관리자용 토큰") - ) - ) - ); - } - - @DisplayName("행사 전체 액션 이력 조회") - @Test - void findActions() throws Exception { - String token = "TOKEN"; - List<ActionAppResponse> actionAppResponses = List.of( - new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), - new ActionAppResponse(2L, "족발", 100L, 2L, ActionType.BILL), - new ActionAppResponse(3L, "인생네컷", 1000L, 3L, ActionType.BILL), - new ActionAppResponse(4L, "망쵸", null, 4L, ActionType.OUT) - ); - given(eventService.findActions(token)).willReturn(actionAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/actions", token) - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.steps[0].type").value(equalTo("IN"))) - .andExpect(jsonPath("$.steps[0].stepName").value(equalTo("0차"))) - .andExpect(jsonPath("$.steps[0].members[0]").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.steps[0].actions[0].actionId").value(equalTo(1))) - .andExpect(jsonPath("$.steps[0].actions[0].name").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.steps[0].actions[0].price").value(equalTo(null))) - .andExpect(jsonPath("$.steps[0].actions[0].sequence").value(equalTo(1))) - - .andExpect(jsonPath("$.steps[1].type").value(equalTo("BILL"))) - .andExpect(jsonPath("$.steps[1].stepName").value(equalTo("1차"))) - .andExpect(jsonPath("$.steps[1].members[0]").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.steps[1].actions[0].actionId").value(equalTo(2))) - .andExpect(jsonPath("$.steps[1].actions[0].name").value(equalTo("족발"))) - .andExpect(jsonPath("$.steps[1].actions[0].price").value(equalTo(100))) - .andExpect(jsonPath("$.steps[1].actions[0].sequence").value(equalTo(2))) - - .andExpect(jsonPath("$.steps[1].actions[1].actionId").value(equalTo(3))) - .andExpect(jsonPath("$.steps[1].actions[1].name").value(equalTo("인생네컷"))) - .andExpect(jsonPath("$.steps[1].actions[1].price").value(equalTo(1000))) - .andExpect(jsonPath("$.steps[1].actions[1].sequence").value(equalTo(3))) - - .andExpect(jsonPath("$.steps[2].type").value(equalTo("OUT"))) - .andExpect(jsonPath("$.steps[2].stepName").value(equalTo("1차"))) - .andExpect(jsonPath("$.steps[2].actions[0].actionId").value(equalTo(4))) - .andExpect(jsonPath("$.steps[2].actions[0].name").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.steps[2].actions[0].price").value(equalTo(null))) - .andExpect(jsonPath("$.steps[2].actions[0].sequence").value(equalTo(4))) - - .andDo( - document("findActions", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("steps[].stepName").type(JsonFieldType.STRING) - .description("스탭 이름"), - fieldWithPath("steps[].type").type(JsonFieldType.STRING) - .description("액션 유형 [BILL, IN, OUT]"), - fieldWithPath("steps[].members").type(JsonFieldType.ARRAY) - .description("해당 step에 참여한 참여자 목록"), - fieldWithPath("steps[].actions[].actionId").type(JsonFieldType.NUMBER) - .description("액션 ID"), - fieldWithPath("steps[].actions[].name").type(JsonFieldType.STRING) - .description("참여자 액션일 경우 참여자 이름, 지출 액션일 경우 지출 내역 이름"), - fieldWithPath("steps[].actions[].price").type(JsonFieldType.NUMBER).optional() - .description("참여자 액션일 경우 null, 지출 액션일 경우 지출 금액"), - fieldWithPath("steps[].actions[].sequence").type(JsonFieldType.NUMBER) - .description("액션 순서"), - fieldWithPath("steps[].actions[].isFixed").type(JsonFieldType.BOOLEAN) - .description("지출 내역의 멤버별 고정 지출 금액 생성 여부") - ) - ) - ); - } - - @DisplayName("행사 전체 액션 이력 조회 v2") - @Test - void findActions2() throws Exception { - String token = "TOKEN"; - List<ActionAppResponse> actionAppResponses = List.of( - new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), - new ActionAppResponse(2L, "족발", 100L, 2L, ActionType.BILL), - new ActionAppResponse(3L, "인생네컷", 1000L, 3L, ActionType.BILL), - new ActionAppResponse(4L, "망쵸", null, 4L, ActionType.OUT) - ); - given(eventService.findActions(token)).willReturn(actionAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/actions/v2", token) - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.actions[0].actionId").value(equalTo(1))) - .andExpect(jsonPath("$.actions[0].name").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.actions[0].price").value(equalTo(null))) - .andExpect(jsonPath("$.actions[0].sequence").value(equalTo(1))) - .andExpect(jsonPath("$.actions[0].type").value(equalTo("IN"))) - - .andExpect(jsonPath("$.actions[1].actionId").value(equalTo(2))) - .andExpect(jsonPath("$.actions[1].name").value(equalTo("족발"))) - .andExpect(jsonPath("$.actions[1].price").value(equalTo(100))) - .andExpect(jsonPath("$.actions[1].sequence").value(equalTo(2))) - .andExpect(jsonPath("$.actions[1].type").value(equalTo("BILL"))) - - .andExpect(jsonPath("$.actions[2].actionId").value(equalTo(3))) - .andExpect(jsonPath("$.actions[2].name").value(equalTo("인생네컷"))) - .andExpect(jsonPath("$.actions[2].price").value(equalTo(1000))) - .andExpect(jsonPath("$.actions[2].sequence").value(equalTo(3))) - .andExpect(jsonPath("$.actions[2].type").value(equalTo("BILL"))) - - .andExpect(jsonPath("$.actions[3].actionId").value(equalTo(4))) - .andExpect(jsonPath("$.actions[3].name").value(equalTo("망쵸"))) - .andExpect(jsonPath("$.actions[3].price").value(equalTo(null))) - .andExpect(jsonPath("$.actions[3].sequence").value(equalTo(4))) - .andExpect(jsonPath("$.actions[3].type").value(equalTo("OUT"))) - - .andDo( - document("findActions", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("actions[].actionId").type(JsonFieldType.NUMBER) - .description("액션 ID"), - fieldWithPath("actions[].name").type(JsonFieldType.STRING) - .description("참여자 액션일 경우 참여자 이름, 지출 액션일 경우 지출 내역 이름"), - fieldWithPath("actions[].price").type(JsonFieldType.NUMBER).optional() - .description("참여자 액션일 경우 null, 지출 액션일 경우 지출 금액"), - fieldWithPath("actions[].sequence").type(JsonFieldType.NUMBER) - .description("액션 순서"), - fieldWithPath("actions[].type").type(JsonFieldType.STRING) - .description("액션 타입") - ) - ) - ); - } - - @DisplayName("행사 어드민 권한을 확인한다.") - @Test - void authenticateTest() throws Exception { - String token = "TOKEN"; - mockMvc.perform(post("/api/events/{eventId}/auth", token) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - - .andDo( - document("authenticateEvent", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자 토큰").optional() - ) - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java b/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java deleted file mode 100644 index afd766c8f..000000000 --- a/server/src/test/java/server/haengdong/docs/MemberActionControllerDocsTest.java +++ /dev/null @@ -1,157 +0,0 @@ -package server.haengdong.docs; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; -import static org.springframework.restdocs.cookies.CookieDocumentation.cookieWithName; -import static org.springframework.restdocs.cookies.CookieDocumentation.requestCookies; -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; -import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; -import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static server.haengdong.support.fixture.Fixture.EVENT_COOKIE; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.restdocs.payload.JsonFieldType; -import server.haengdong.application.MemberActionService; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.MemberActionController; -import server.haengdong.presentation.request.MemberActionsSaveRequest; - -public class MemberActionControllerDocsTest extends RestDocsSupport { - - private final MemberActionService memberActionService = mock(MemberActionService.class); - - @Override - protected Object initController() { - return new MemberActionController(memberActionService); - } - - @DisplayName("참여자 행동을 추가한다.") - @Test - void saveMemberActionTest() throws Exception { - MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( - List.of("웨디", "소하", "토다리", "쿠키"), "IN"); - - String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); - - mockMvc.perform(post("/api/events/{eventId}/member-actions", "망쵸토큰") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("createMemberAction", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - requestCookies( - cookieWithName("eventToken").description("토큰 토큰") - ), - requestFields( - fieldWithPath("members").type(JsonFieldType.ARRAY) - .description("액션 대상 참여자 목록"), - fieldWithPath("status").type(JsonFieldType.STRING) - .description("참여자 액션 상태 [IN(늦참), OUT(탈주)]") - ) - ) - ); - } - - @DisplayName("현재 참여 인원을 조회합니다.") - @Test - void getCurrentMembers() throws Exception { - List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( - new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); - - given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/members/current", "망쵸토큰") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.memberNames[0]").value(equalTo("소하"))) - .andExpect(jsonPath("$.memberNames[1]").value(equalTo("토다리"))) - .andDo( - document("getCurrentMembers", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID") - ), - responseFields( - fieldWithPath("memberNames").type(JsonFieldType.ARRAY) - .description("현재 탈주 가능한 참여 인원 이름 목록") - ) - ) - ); - } - - @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") - @Test - void deleteMemberAction() throws Exception { - String eventId = "망쵸토큰"; - Long actionId = 2L; - - mockMvc.perform(delete("/api/events/{eventId}/member-actions/{actionId}", eventId, actionId) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("deleteMemberAction", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("actionId").description("액션 ID") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자용 토큰") - ) - ) - ); - } - - @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") - @Test - void deleteMember() throws Exception { - String eventId = "망쵸토큰"; - String memberName = "행동대장"; - - mockMvc.perform(delete("/api/events/{eventId}/members/{memberName}", eventId, memberName) - .cookie(EVENT_COOKIE)) - .andDo(print()) - .andExpect(status().isOk()) - .andDo( - document("deleteAllMemberActionByName", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()), - pathParameters( - parameterWithName("eventId").description("행사 ID"), - parameterWithName("memberName").description("행사 참여자 이름") - ), - requestCookies( - cookieWithName("eventToken").description("행사 관리자용 토큰") - ) - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/docs/RestDocsSupport.java b/server/src/test/java/server/haengdong/docs/RestDocsSupport.java deleted file mode 100644 index 3e6901ba8..000000000 --- a/server/src/test/java/server/haengdong/docs/RestDocsSupport.java +++ /dev/null @@ -1,28 +0,0 @@ -package server.haengdong.docs; - -import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.restdocs.RestDocumentationContextProvider; -import org.springframework.restdocs.RestDocumentationExtension; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; - -@ExtendWith({RestDocumentationExtension.class}) -abstract class RestDocsSupport { - - protected MockMvc mockMvc; - - protected ObjectMapper objectMapper = new ObjectMapper(); - - @BeforeEach - void setUp(RestDocumentationContextProvider restDocumentation) { - this.mockMvc = MockMvcBuilders.standaloneSetup(initController()) - .apply(documentationConfiguration(restDocumentation)) - .build(); - } - - protected abstract Object initController(); -} diff --git a/server/src/test/java/server/haengdong/domain/action/ActionTest.java b/server/src/test/java/server/haengdong/domain/action/ActionTest.java deleted file mode 100644 index 6ff25479c..000000000 --- a/server/src/test/java/server/haengdong/domain/action/ActionTest.java +++ /dev/null @@ -1,31 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; -import server.haengdong.support.fixture.Fixture; - -class ActionTest { - - @DisplayName("액션의 초기 순서번호는 1이다.") - @Test - void createFirst() { - Event event = Fixture.EVENT1; - Action action = Action.createFirst(event); - - assertThat(action.getSequence()).isOne(); - } - - @DisplayName("현재 액션의 다음 액션의 순서는 1만큼 증가한다.") - @Test - void next() { - Event event = Fixture.EVENT1; - Action action = new Action(event, 2L); - - Action nextAction = action.next(); - - assertThat(nextAction.getSequence()).isEqualTo(3L); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java b/server/src/test/java/server/haengdong/domain/action/BillActionTest.java deleted file mode 100644 index ba1ab36f2..000000000 --- a/server/src/test/java/server/haengdong/domain/action/BillActionTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; -import static server.haengdong.support.fixture.Fixture.BILL_ACTION; -import static server.haengdong.support.fixture.Fixture.EVENT1; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongException; - -class BillActionTest { - - @DisplayName("지출 내역 제목의 앞뒤 공백을 제거한 길이가 1 ~ 30자가 아니면 지출을 생성할 수 없다.") - @ParameterizedTest - @ValueSource(strings = {"", " ", "1234567890123456789012345678901"}) - void validateTitle(String title) { - Event event = EVENT1; - Action action = new Action(event, 1L); - Long price = 100L; - - assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(HaengdongException.class) - .hasMessage("앞뒤 공백을 제거한 지출 내역 제목은 1 ~ 30자여야 합니다."); - } - - @DisplayName("금액이 10,000,000 이하의 자연수가 아니면 지출을 생성할 수 없다.") - @ParameterizedTest - @ValueSource(longs = {0, 10_000_001, 20_000_000}) - void validatePrice(long price) { - Event event = EVENT1; - Action action = new Action(event, 1L); - String title = "title"; - - assertThatThrownBy(() -> new BillAction(action, title, price)) - .isInstanceOf(HaengdongException.class) - .hasMessage("지출 금액은 10,000,000 이하의 자연수여야 합니다."); - } - - @DisplayName("지출 내역을 올바르게 생성한다.") - @Test - void createBillAction() { - Event event = EVENT1; - Action action = new Action(event, 1L); - String title = "title"; - Long price = 1_000L; - - BillAction billAction = new BillAction(action, title, price); - - assertAll( - () -> assertThat(billAction.getAction()).isEqualTo(action), - () -> assertThat(billAction.getTitle()).isEqualTo(title), - () -> assertThat(billAction.getPrice()).isEqualTo(price) - ); - } - - @DisplayName("지출 액션에 멤버별 고정 금액이 설정되어 있는지 확인한다.") - @Test - void isFixed1() { - BillAction fixedBillAction = new BillAction(new Action(EVENT1, 1L), "인생네컷", 2_000L); - - List<BillActionDetail> unfixedBillActionDetails = List.of( - new BillActionDetail(BILL_ACTION, "감자", 1_000L, false), - new BillActionDetail(BILL_ACTION, "고구마", 1_000L, false) - ); - fixedBillAction.addDetails(unfixedBillActionDetails); - - assertThat(fixedBillAction.isFixed()).isEqualTo(false); - } - - @DisplayName("지출 액션에 멤버별 고정 금액이 설정되어 있는지 확인한다.") - @Test - void isFixed2() { - BillAction fixedBillAction = new BillAction(new Action(EVENT1, 1L), "인생네컷", 5_000L); - - List<BillActionDetail> unfixedBillActionDetails = List.of( - new BillActionDetail(BILL_ACTION, "감자", 4_000L, true), - new BillActionDetail(BILL_ACTION, "고구마", 1_000L, true) - ); - fixedBillAction.addDetails(unfixedBillActionDetails); - - assertThat(fixedBillAction.isFixed()).isEqualTo(true); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java b/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java deleted file mode 100644 index 93148abd3..000000000 --- a/server/src/test/java/server/haengdong/domain/action/CurrentMembersTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; - -import java.util.List; -import java.util.Set; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; -import server.haengdong.exception.HaengdongException; -import server.haengdong.support.fixture.Fixture; - -class CurrentMembersTest { - - @DisplayName("인원 변동 이력으로 현재 참여 인원을 계산한다.") - @Test - void of() { - Event event = Fixture.EVENT1; - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(event, 1L), "망쵸", IN, 1L), - new MemberAction(new Action(event, 2L), "백호", IN, 1L), - new MemberAction(new Action(event, 3L), "백호", OUT, 1L), - new MemberAction(new Action(event, 4L), "웨디", IN, 1L) - ); - - CurrentMembers currentMembers = CurrentMembers.of(memberActions); - - assertThat(currentMembers.getMembers()) - .containsExactlyInAnyOrder("망쵸", "웨디"); - } - - @DisplayName("인원 변동 액션의 상태가 IN이면 현재 인원에 추가한다.") - @Test - void addMemberAction1() { - CurrentMembers currentMembers = new CurrentMembers(); - Event event = Fixture.EVENT1; - MemberAction memberAction = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); - - CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction); - Set<String> members = addedCurrentMembers.getMembers(); - - assertThat(members).hasSize(1) - .containsExactly("웨디"); - } - - @DisplayName("인원 변동 액션의 상태가 OUT이면 현재 인원에서 제외한다.") - @Test - void addMemberAction2() { - Event event = Fixture.EVENT1; - MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "웨디", IN, 1L); - CurrentMembers currentMembers = new CurrentMembers().addMemberAction(memberAction1); - MemberAction memberAction2 = new MemberAction(new Action(event, 1L), "웨디", OUT, 1L); - - CurrentMembers addedCurrentMembers = currentMembers.addMemberAction(memberAction2); - - assertThat(addedCurrentMembers.getMembers()).hasSize(0); - } - - @DisplayName("현재 참여중인 인원은 나갈 수 있다.") - @Test - void validate1() { - CurrentMembers currentMembers = new CurrentMembers(Set.of("토다리")); - - assertThatCode(() -> currentMembers.validate("토다리", OUT)) - .doesNotThrowAnyException(); - } - - @DisplayName("현재 참여중이지 않은 인원은 들어올 수 있다.") - @Test - void validate2() { - CurrentMembers currentMembers = new CurrentMembers(Set.of("쿠키")); - - assertThatCode(() -> currentMembers.validate("토다리", IN)) - .doesNotThrowAnyException(); - } - - @DisplayName("현재 참여중인 인원은 들어올 수 없다.") - @Test - void validate3() { - CurrentMembers currentMembers = new CurrentMembers(Set.of("토다리")); - - assertThatCode(() -> currentMembers.validate("토다리", IN)) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("현재 참여중이지 않은 인원은 나갈 수 없다.") - @Test - void validate4() { - CurrentMembers currentMembers = new CurrentMembers(Set.of("쿠키")); - - assertThatCode(() -> currentMembers.validate("토다리", OUT)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java b/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java deleted file mode 100644 index 02070a537..000000000 --- a/server/src/test/java/server/haengdong/domain/action/MemberBillReportTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package server.haengdong.domain.action; - -import static org.assertj.core.api.Assertions.assertThat; -import static server.haengdong.domain.action.MemberActionStatus.IN; -import static server.haengdong.domain.action.MemberActionStatus.OUT; -import static server.haengdong.support.fixture.Fixture.BILL_ACTION; - -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.domain.event.Event; -import server.haengdong.support.fixture.Fixture; - -class MemberBillReportTest { - - @DisplayName("액션 목록으로 참가자 정산 리포트를 생성한다.") - @Test - void createByActions() { - Event event = Fixture.EVENT1; - List<BillAction> billActions = List.of( - new BillAction(new Action(event, 4L), "뽕족", 60_000L), - new BillAction(new Action(event, 7L), "인생네컷", 20_000L) - ); - billActions.get(0).addDetails( - List.of( - new BillActionDetail(BILL_ACTION, "소하", 10_000L, false), - new BillActionDetail(BILL_ACTION, "감자", 40_000L, true), - new BillActionDetail(BILL_ACTION, "쿠키", 10_000L, false) - ) - ); - billActions.get(1).addDetails( - List.of( - new BillActionDetail(BILL_ACTION, "소하", 5_000L, true), - new BillActionDetail(BILL_ACTION, "쿠키", 15_000L, true) - ) - ); - List<MemberAction> memberActions = List.of( - new MemberAction(new Action(event, 1L), "소하", IN, 1L), - new MemberAction(new Action(event, 2L), "감자", IN, 1L), - new MemberAction(new Action(event, 3L), "쿠키", IN, 1L), - new MemberAction(new Action(event, 5L), "감자", OUT, 2L) - ); - - MemberBillReport memberBillReport = MemberBillReport.createByActions(billActions, memberActions); - - assertThat(memberBillReport.getReports()) - .containsAllEntriesOf( - Map.of( - "감자", 40_000L, - "쿠키", 25_000L, - "소하", 15_000L - ) - ); - } -} diff --git a/server/src/test/java/server/haengdong/domain/event/EventTest.java b/server/src/test/java/server/haengdong/domain/event/EventTest.java deleted file mode 100644 index 12c0c0569..000000000 --- a/server/src/test/java/server/haengdong/domain/event/EventTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package server.haengdong.domain.event; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.exception.HaengdongException; - -class EventTest { - - @DisplayName("공백 문자가 연속되지 않고, 이름이 2자 이상 20자 이하인 행사를 생성하면 예외가 발생하지 않는다.") - @ParameterizedTest - @ValueSource(strings = {"12", "12345678901234567890", "공 백", " 공백", "공백 ", " 공 백 "}) - void createSuccessTest(String eventName) { - assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) - .doesNotThrowAnyException(); - } - - @DisplayName("공백 문자가 연속되면 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {" 공백", "공백 ", "공백 연속", "공 백"}) - void createFailTest1(String eventName) { - assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class) - .hasMessage(String.format("행사 이름에는 공백 문자가 연속될 수 없습니다. 입력한 이름 : %s", eventName)); - } - - @DisplayName("이름이 1자 미만이거나 20자 초과인 경우 예외가 발생한다.") - @ParameterizedTest - @ValueSource(strings = {"", " ", "123456789012345678901"}) - void createFilTest2(String eventName) { - assertThatCode(() -> new Event(eventName, "1234", "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class) - .hasMessage(String.format("행사 이름은 1자 이상 20자 이하만 입력 가능합니다. 입력한 이름 길이 : %d", eventName.length())); - } - - @DisplayName("비밀번호는 4자리 숫자 입니다.") - @ParameterizedTest - @ValueSource(strings = {"1", "12", "123", "12345", "adgd"}) - void validatePassword(String password) { - assertThatCode(() -> new Event("이름", password, "TEST_TOKEN")) - .isInstanceOf(HaengdongException.class); - } - - @DisplayName("비밀번호가 다른지 검증한다.") - @Test - void isNotSamePassword() { - String rawPassword = "1234"; - Event event = new Event("이름", rawPassword, "TEST_TOKEN"); - - assertThat(event.isPasswordMismatch(rawPassword)).isFalse(); - } - - @DisplayName("비밀번호가 다른지 검증한다.") - @Test - void isNotSamePassword1() { - String rawPassword = "1234"; - Event event = new Event("이름", "5678", "TEST_TOKEN"); - - assertThat(event.isPasswordMismatch(rawPassword)).isTrue(); - } -} diff --git a/server/src/test/java/server/haengdong/domain/event/PasswordTest.java b/server/src/test/java/server/haengdong/domain/event/PasswordTest.java deleted file mode 100644 index c504d3aa2..000000000 --- a/server/src/test/java/server/haengdong/domain/event/PasswordTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.domain.event; - -import static org.assertj.core.api.Assertions.assertThatCode; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import server.haengdong.exception.HaengdongException; - -class PasswordTest { - - @DisplayName("비밀번호는 4자리 숫자 입니다.") - @ParameterizedTest - @ValueSource(strings = {"1", "12", "123", "12345", "adgd"}) - void validatePassword(String rawPassword) { - assertThatCode(() -> new Password(rawPassword)) - .isInstanceOf(HaengdongException.class); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java deleted file mode 100644 index 1de5889b5..000000000 --- a/server/src/test/java/server/haengdong/presentation/ActionControllerTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package server.haengdong.presentation; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import server.haengdong.application.response.MemberBillReportAppResponse; - -class ActionControllerTest extends ControllerTestSupport { - - @DisplayName("참여자별 정산 현황을 조회한다.") - @Test - void getMemberBillReports() throws Exception { - List<MemberBillReportAppResponse> memberBillReportAppResponses = List.of( - new MemberBillReportAppResponse("소하", 20_000L), new MemberBillReportAppResponse("토다리", 200_000L)); - - given(actionService.getMemberBillReports(any())).willReturn(memberBillReportAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/actions/reports", "망쵸토큰") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].name").value(equalTo("소하"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[0].price").value(equalTo(20_000))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].name").value(equalTo("토다리"))) - .andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000))); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java deleted file mode 100644 index 4420e369c..000000000 --- a/server/src/test/java/server/haengdong/presentation/BillActionControllerTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package server.haengdong.presentation; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doThrow; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.exception.HaengdongErrorCode; -import server.haengdong.exception.HaengdongException; -import server.haengdong.presentation.request.BillActionSaveRequest; -import server.haengdong.presentation.request.BillActionUpdateRequest; -import server.haengdong.presentation.request.BillActionsSaveRequest; - -class BillActionControllerTest extends ControllerTestSupport { - - @DisplayName("지출 내역을 생성한다.") - @Test - void saveAllBillAction() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("뽕족", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "쿠키토큰"; - - mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("title이 비어 있는 경우 지출 내역을 생성할 수 없다.") - @Test - void saveAllBillAction1() throws Exception { - BillActionsSaveRequest request = new BillActionsSaveRequest( - List.of( - new BillActionSaveRequest("", 10_000L), - new BillActionSaveRequest("인생맥주", 10_000L) - ) - ); - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "소하토큰"; - - mockMvc.perform(post("/api/events/{eventId}/bill-actions", eventId) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isBadRequest()); - } - - @DisplayName("지출 액션을 수정한다.") - @Test - void updateBillAction() throws Exception { - BillActionUpdateRequest request = new BillActionUpdateRequest("뽕족", 10_000L); - - String requestBody = objectMapper.writeValueAsString(request); - String eventId = "웨디토큰"; - - mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("지출 내역을 삭제한다.") - @Test - void deleteBillAction() throws Exception { - String eventId = "토다리토큰"; - - mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("존재하지 않는 행사에 대한 지출 내역을 삭제할 수 없다.") - @Test - void deleteBillAction1() throws Exception { - String eventId = "이상해토큰"; - doThrow(new HaengdongException(HaengdongErrorCode.EVENT_NOT_FOUND)) - .when(billActionService).deleteBillAction(any(String.class), any(Long.class)); - - mockMvc.perform(delete("/api/events/{eventId}/bill-actions/{actionId}", eventId, 1)) - .andDo(print()) - .andExpect(status().isBadRequest()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java b/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java deleted file mode 100644 index 6b595ee27..000000000 --- a/server/src/test/java/server/haengdong/presentation/BillActionDetailControllerTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package server.haengdong.presentation; - -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.application.response.BillActionDetailAppResponse; -import server.haengdong.application.response.BillActionDetailsAppResponse; -import server.haengdong.presentation.request.BillActionDetailUpdateRequest; -import server.haengdong.presentation.request.BillActionDetailsUpdateRequest; - -class BillActionDetailControllerTest extends ControllerTestSupport { - - @DisplayName("참여자별 지출 금액을 조회한다.") - @Test - void findBillActionDetails() throws Exception { - BillActionDetailsAppResponse appResponse = new BillActionDetailsAppResponse( - List.of(new BillActionDetailAppResponse("토다리", 1000L, false))); - given(billActionDetailService.findBillActionDetails(anyString(), anyLong())) - .willReturn(appResponse); - - mockMvc.perform(get("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.members").isArray()) - .andExpect(jsonPath("$.members[0].name").value("토다리")) - .andExpect(jsonPath("$.members[0].price").value(1000L)); - } - - @DisplayName("참여자별 지출 금액을 수정한다.") - @Test - void updateBillActionDetailsTest() throws Exception { - List<BillActionDetailUpdateRequest> billActionDetailUpdateRequests = List.of( - new BillActionDetailUpdateRequest("소하", 10000L, true), - new BillActionDetailUpdateRequest("웨디", 20000L, true) - ); - BillActionDetailsUpdateRequest request = new BillActionDetailsUpdateRequest( - billActionDetailUpdateRequests); - - String json = objectMapper.writeValueAsString(request); - - mockMvc.perform(put("/api/events/{eventId}/bill-actions/{actionId}/fixed", "TOKEN", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(json)) - .andDo(print()) - .andExpect(status().isOk()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java b/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java deleted file mode 100644 index 46489b1a5..000000000 --- a/server/src/test/java/server/haengdong/presentation/ControllerTestSupport.java +++ /dev/null @@ -1,53 +0,0 @@ -package server.haengdong.presentation; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.FilterType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import server.haengdong.application.ActionService; -import server.haengdong.application.AuthService; -import server.haengdong.application.BillActionDetailService; -import server.haengdong.application.BillActionService; -import server.haengdong.application.EventService; -import server.haengdong.application.MemberActionService; - -@WebMvcTest( - controllers = { - EventController.class, - ActionController.class, - BillActionController.class, - MemberActionController.class, - BillActionDetailController.class - }, - excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {WebMvcConfigurer.class})} -) -abstract class ControllerTestSupport { - - @Autowired - protected MockMvc mockMvc; - - @Autowired - protected ObjectMapper objectMapper; - - @MockBean - protected EventService eventService; - - @MockBean - protected AuthService authService; - - @MockBean - protected ActionService actionService; - - @MockBean - protected MemberActionService memberActionService; - - @MockBean - protected BillActionService billActionService; - - @MockBean - protected BillActionDetailService billActionDetailService; -} diff --git a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java b/server/src/test/java/server/haengdong/presentation/EventControllerTest.java deleted file mode 100644 index fcfe48d01..000000000 --- a/server/src/test/java/server/haengdong/presentation/EventControllerTest.java +++ /dev/null @@ -1,111 +0,0 @@ -package server.haengdong.presentation; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.cookie; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.application.request.EventAppRequest; -import server.haengdong.application.response.EventAppResponse; -import server.haengdong.application.response.EventDetailAppResponse; -import server.haengdong.application.response.MembersAppResponse; -import server.haengdong.presentation.request.EventLoginRequest; -import server.haengdong.presentation.request.EventSaveRequest; -import server.haengdong.presentation.request.MemberNameUpdateRequest; -import server.haengdong.presentation.request.MemberNamesUpdateRequest; - - -class EventControllerTest extends ControllerTestSupport { - - @DisplayName("이벤트를 생성한다.") - @Test - void saveEvent() throws Exception { - EventSaveRequest eventSaveRequest = new EventSaveRequest("토다리", "0987"); - String requestBody = objectMapper.writeValueAsString(eventSaveRequest); - String eventId = "망쵸토큰"; - EventAppResponse eventAppResponse = new EventAppResponse(eventId); - given(eventService.saveEvent(any(EventAppRequest.class))).willReturn(eventAppResponse); - given(authService.createToken(eventId)).willReturn("jwtToken"); - given(authService.getTokenName()).willReturn("eventToken"); - - mockMvc.perform(post("/api/events") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(cookie().value("eventToken", "jwtToken")) - .andExpect(jsonPath("$.eventId").value("망쵸토큰")); - } - - @DisplayName("토큰으로 행사를 조회한다.") - @Test - void findEventTest() throws Exception { - String eventId = "망쵸토큰"; - EventDetailAppResponse eventDetailAppResponse = new EventDetailAppResponse("행동대장 회식"); - given(eventService.findEvent(eventId)).willReturn(eventDetailAppResponse); - - mockMvc.perform(get("/api/events/{eventId}", eventId)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.eventName").value("행동대장 회식")); - } - - @DisplayName("행사에 참여한 전체 인원을 중복 없이 조회한다.") - @Test - void findAllMembersTest() throws Exception { - MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("토다리", "쿠키")); - given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse); - - mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.memberNames").isArray()) - .andExpect(jsonPath("$.memberNames[0]").value("토다리")) - .andExpect(jsonPath("$.memberNames[1]").value("쿠키")); - } - - @DisplayName("행사 참여 인원의 이름을 수정한다.") - @Test - void updateMember() throws Exception { - String token = "TOKEN"; - MemberNamesUpdateRequest memberNameUpdateRequest = new MemberNamesUpdateRequest(List.of( - new MemberNameUpdateRequest("토다링", "토쟁이"), - new MemberNameUpdateRequest("감자", "고구마") - )); - - String requestBody = objectMapper.writeValueAsString(memberNameUpdateRequest); - - mockMvc.perform(put("/api/events/{eventId}/members/nameChange", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("행사 어드민이 로그인한다.") - @Test - void loginEvent() throws Exception { - String token = "TOKEN"; - EventLoginRequest eventLoginRequest = new EventLoginRequest("1234"); - String requestBody = objectMapper.writeValueAsString(eventLoginRequest); - given(authService.createToken(token)).willReturn("jwtToken"); - given(authService.getTokenName()).willReturn("eventToken"); - - mockMvc.perform(post("/api/events/{eventId}/login", token) - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(cookie().value("eventToken", "jwtToken")) - .andExpect(status().isOk()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java b/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java deleted file mode 100644 index f50c70a17..000000000 --- a/server/src/test/java/server/haengdong/presentation/MemberActionControllerTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package server.haengdong.presentation; - -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import server.haengdong.application.response.CurrentMemberAppResponse; -import server.haengdong.presentation.request.MemberActionsSaveRequest; - -class MemberActionControllerTest extends ControllerTestSupport { - - @DisplayName("참여자 행동을 추가한다.") - @Test - void saveMemberActionTest() throws Exception { - MemberActionsSaveRequest memberActionsSaveRequest = new MemberActionsSaveRequest( - List.of("웨디", "소하", "토다리", "쿠키"), "IN"); - - String requestBody = objectMapper.writeValueAsString(memberActionsSaveRequest); - - mockMvc.perform(post("/api/events/{eventId}/member-actions", "망쵸토큰") - .contentType(MediaType.APPLICATION_JSON) - .content(requestBody)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("현재 참여 인원을 조회합니다.") - @Test - void getCurrentMembers() throws Exception { - List<CurrentMemberAppResponse> currentMemberAppResponses = List.of( - new CurrentMemberAppResponse("소하"), new CurrentMemberAppResponse("토다리")); - - given(memberActionService.getCurrentMembers(any())).willReturn(currentMemberAppResponses); - - mockMvc.perform(get("/api/events/{eventId}/members/current", "망쵸토큰") - .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.memberNames[0]").value(equalTo("소하"))) - .andExpect(jsonPath("$.memberNames[1]").value(equalTo("토다리"))); - } - - @DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.") - @Test - void deleteMemberAction() throws Exception { - String eventId = "망쵸토큰"; - Long actionId = 2L; - - mockMvc.perform(delete("/api/events/{eventId}/member-actions/{actionId}", eventId, actionId)) - .andDo(print()) - .andExpect(status().isOk()); - } - - @DisplayName("행사의 전체 참여자 중에서 특정 참여자의 맴버 액션을 전부 삭제한다.") - @Test - void deleteMember() throws Exception { - String eventId = "망쵸토큰"; - String memberName = "행동대장"; - - mockMvc.perform(delete("/api/events/{eventId}/members/{memberName}", eventId, memberName)) - .andDo(print()) - .andExpect(status().isOk()); - } -} diff --git a/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java b/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java deleted file mode 100644 index 051fcae0f..000000000 --- a/server/src/test/java/server/haengdong/presentation/response/StepsResponseTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package server.haengdong.presentation.response; - - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import server.haengdong.application.response.ActionAppResponse; -import server.haengdong.application.response.ActionAppResponse.ActionType; - -class StepsResponseTest { - - @DisplayName("이웃한 같은 타입의 액션들을 그룹화 하여 응답객체를 생성한다.") - @Test - void of() { - List<ActionAppResponse> actions = List.of( - new ActionAppResponse(1L, "망쵸", null, 1L, ActionType.IN), - new ActionAppResponse(2L, "백호", null, 2L, ActionType.IN), - new ActionAppResponse(3L, "감자탕", 10_000L, 3L, ActionType.BILL), - new ActionAppResponse(4L, "인생네컷", 10_000L, 4L, ActionType.BILL), - new ActionAppResponse(5L, "소하", null, 5L, ActionType.IN), - new ActionAppResponse(6L, "웨디", null, 6L, ActionType.IN), - new ActionAppResponse(7L, "망쵸", null, 7L, ActionType.OUT), - new ActionAppResponse(8L, "백호", null, 8L, ActionType.OUT), - new ActionAppResponse(9L, "노래방", 20_000L, 9L, ActionType.BILL) - ); - - StepsResponse stepsResponse = StepsResponse.of(actions); - - StepsResponse expected = new StepsResponse( - List.of( - new StepResponse("0차", "IN", List.of("망쵸", "백호"), List.of( - new ActionResponse(1L, "망쵸", null, 1L), - new ActionResponse(2L, "백호", null, 2L) - )), - new StepResponse("1차", "BILL", List.of("망쵸", "백호"), List.of( - new ActionResponse(3L, "감자탕", 10_000L, 3L), - new ActionResponse(4L, "인생네컷", 10_000L, 4L) - )), - new StepResponse("1차", "IN", List.of("망쵸", "백호", "소하", "웨디"), List.of( - new ActionResponse(5L, "소하", null, 5L), - new ActionResponse(6L, "웨디", null, 6L) - )), - new StepResponse("1차", "OUT", List.of("소하", "웨디"), List.of( - new ActionResponse(7L, "망쵸", null, 7L), - new ActionResponse(8L, "백호", null, 8L) - )), - new StepResponse("2차", "BILL", List.of("소하", "웨디"), List.of( - new ActionResponse(9L, "노래방", 20_000L, 9L) - )) - ) - ); - assertThat(stepsResponse).isEqualTo(expected); - } - - @DisplayName("액션이 없으면 빈 스탭들이 만들어진다.") - @Test - void ofEmpty() { - StepsResponse stepsResponse = StepsResponse.of(List.of()); - assertThat(stepsResponse.steps()).isEmpty(); - } -} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java deleted file mode 100644 index 346e81d2d..000000000 --- a/server/src/test/java/server/haengdong/support/extension/DatabaseCleaner.java +++ /dev/null @@ -1,52 +0,0 @@ -package server.haengdong.support.extension; - -import jakarta.annotation.PostConstruct; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import java.util.List; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -@Component -class DatabaseCleaner { - - private static final String REFERENTIAL_FORMAT = "set referential_integrity %b;"; - private static final String TRUNCATE_FORMAT = "truncate table %s restart identity;"; - - @PersistenceContext - private EntityManager em; - private String truncateTablesQuery; - - @PostConstruct - public void createTruncateQuery() { - List<String> tableNames = getTableNames(); - StringBuilder stringBuilder = new StringBuilder(); - - for (String tableName : tableNames) { - String truncateQuery = String.format(TRUNCATE_FORMAT, tableName); - stringBuilder.append(truncateQuery); - } - truncateTablesQuery = stringBuilder.toString(); - } - - private List<String> getTableNames() { - String sql = """ - select table_name - from information_schema.tables - where table_schema = 'PUBLIC' - """; - return em.createNativeQuery(sql).getResultList(); - } - - @Transactional - public void clear() { - em.clear(); - truncate(); - } - - private void truncate() { - em.createNativeQuery(String.format(REFERENTIAL_FORMAT, false)).executeUpdate(); - em.createNativeQuery(truncateTablesQuery).executeUpdate(); - em.createNativeQuery(String.format(REFERENTIAL_FORMAT, true)).executeUpdate(); - } -} diff --git a/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java b/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java deleted file mode 100644 index 653ecadb3..000000000 --- a/server/src/test/java/server/haengdong/support/extension/DatabaseCleanerExtension.java +++ /dev/null @@ -1,19 +0,0 @@ -package server.haengdong.support.extension; - -import org.junit.jupiter.api.extension.AfterEachCallback; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -public class DatabaseCleanerExtension implements AfterEachCallback { - - @Override - public void afterEach(ExtensionContext context) { - DatabaseCleaner databaseCleaner = getDataCleaner(context); - databaseCleaner.clear(); - } - - private DatabaseCleaner getDataCleaner(ExtensionContext extensionContext) { - return SpringExtension.getApplicationContext(extensionContext) - .getBean(DatabaseCleaner.class); - } -} diff --git a/server/src/test/java/server/haengdong/support/fixture/Fixture.java b/server/src/test/java/server/haengdong/support/fixture/Fixture.java deleted file mode 100644 index 6844915d9..000000000 --- a/server/src/test/java/server/haengdong/support/fixture/Fixture.java +++ /dev/null @@ -1,15 +0,0 @@ -package server.haengdong.support.fixture; - -import jakarta.servlet.http.Cookie; -import server.haengdong.domain.action.Action; -import server.haengdong.domain.action.BillAction; -import server.haengdong.domain.event.Event; - -public class Fixture { - - public static final Event EVENT1 = new Event("쿠키", "1234", "TOKEN1"); - public static final Event EVENT2 = new Event("웨디", "1234", "TOKEN2"); - public static final Cookie EVENT_COOKIE = new Cookie("eventToken", "토큰토큰"); - public static final Action ACTION = new Action(EVENT1, 1L); - public static final BillAction BILL_ACTION = new BillAction(ACTION, "뽕족", 30_000L); -} From 47e6bd922a7a216b81ae317961d33a9944c794fa Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 20 Sep 2024 18:22:32 +0900 Subject: [PATCH 229/273] =?UTF-8?q?feat:=20=EB=B3=80=EA=B2=BD=EB=90=9C=20A?= =?UTF-8?q?PI=20=EC=A0=81=EC=9A=A9=20=EB=B0=8F=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0,=20=EC=A7=80=EC=B6=9C=EB=82=B4=EC=97=AD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20flow=20=EB=B0=8F=20UI=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20(#574)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: NumberKeyboard 구현 * feature: Top Top.Line component 구현 및 행사 생성 플로우 UX 개선 * fix: 공백을 포함하지 않던 문제 수정 * refactor: useNumberKeyboard로 기능 관련 역할 분리 * feat: keyboard type에 string 추가 * style: lint 적용 * feature: CompleteCreateEventPage 변경 * refactor: api 변경에 따라, USER_API_PREFIX, ADMIN_API_PREFIX로 구분 * chore: MSW 설정 변경 중 TODO: intercept 되지 않는 오류 수정 중 * fix: 사용하지 않는 Button component의 isFull 속성 제거 * fix: mockEndpointPrefix 경로 수정 * feat: Amount Component 구현 * fix: meatball Icon 추가 * fix: 잘못 적용된 endpoint 적용 * fix: Title component 수정 * test: Top component storybook 추가 * feat: ListItem Component 추가 * feat: Chip Component 추가 * feat: ChipGroup Component 생성 * design: ChipGroup style 수정 * fix: FixedButton에 onBackClick prop 추가 * refactor: 변경된 api 구조에 맞게 수정 및 type 생성에 대한 통일화 * fix: 변경된 api에 맞게 MSW 코드 변경 * feature: ChipButton component 구현 * feature: AmountInput Component 구현 * design: Button disabled color 변경 * move: NumberKeyboard 위치 변경 * feature: AddBillFunnel page 구현 * fix: API 및 UX 변경사항으로 인해 함꼐 변경이 필요한 사항들 적용 * refactor: api 변경사항에 따른 request 함수들 및 react-query hook 변경 1. request 함수 내에서 Request type 선언하도록 변경 2. react-query에서 data를 정제 및 이름을 변경하여 return 하도록 변경 3. react-query hook들을 domain 별로 그룹화 4. react-qeury hook 및 request 함수 backEnd에서 사용하는 이름 및 model과 통일되도록 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * move: NumberKeyboard component 위치 변경 * remove: 개선 과정에서 사용하지 않는 레거시 파일 삭제 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * fix: 현재 사용하지 않지만, 추후 사용 가능성이 있는 코드 이름 변경 및 주석 처리 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * refactor: API 변경 사항 및 전체 구조 변경에 따른 코드 반영 및 경로 수정, 이름 변경 Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> * fix: MSW mocking 해제 * style: lint 적용 * style: 사용하지 않는 코드 제거 * fix: NumberKeyboard import 잘못 지정된 오류 수정 * style: lint 적용 * fix: 사용하지 않는 테스트 코드 제거 --------- Co-authored-by: Soyeon Choe <soi-ha@users.noreply.github.com> Co-authored-by: JinHo Kim <jinhokim98@users.noreply.github.com> --- .../apis/{tempPrefix.ts => endpointPrefix.ts} | 3 +- client/src/apis/request/auth.ts | 18 +- client/src/apis/request/bill.ts | 78 +++-- client/src/apis/request/event.ts | 49 ++- client/src/apis/request/member.ts | 90 ++--- client/src/apis/request/report.ts | 18 +- client/src/apis/request/step.ts | 15 + client/src/apis/request/stepList.ts | 17 - .../{withEventId.type.ts => withId.type.ts} | 4 + client/src/assets/image/meatballs.svg | 3 + .../AmountInput/AmountInput.stories.tsx | 23 ++ .../components/AmountInput/AmountInput.tsx | 37 ++ .../components/Amount/Amount.stories.tsx | 28 ++ .../Design/components/Amount/Amount.tsx | 20 ++ .../Design/components/Button/Button.style.ts | 2 +- .../Design/components/Chip/Chip.stories.tsx | 36 ++ .../Design/components/Chip/Chip.style.ts | 20 ++ .../Design/components/Chip/Chip.tsx | 26 ++ .../ChipButton/ChipButton.stories.tsx | 34 ++ .../components/ChipButton/ChipButton.style.ts | 21 ++ .../components/ChipButton/ChipButton.tsx | 27 ++ .../ChipGroup/ChipGroup.stories.tsx | 29 ++ .../components/ChipGroup/ChipGroup.style.ts | 6 + .../Design/components/ChipGroup/ChipGroup.tsx | 27 ++ .../FixedButton/FixedButton.style.ts | 28 +- .../components/FixedButton/FixedButton.tsx | 8 +- .../FixedButton/FixedButton.type.ts | 1 + .../Design/components/Icon/Icon.style.ts | 1 + .../Design/components/Icon/Icon.tsx | 2 + .../Design/components/Icon/Icon.type.ts | 11 +- .../components/ListItem/ListItem.stories.tsx | 37 ++ .../components/ListItem/ListItem.style.ts | 21 ++ .../Design/components/ListItem/ListItem.tsx | 14 + .../Design/components/ListItem/Row.tsx | 11 + .../components/NumberKeyboard/Keypad.tsx | 42 +++ .../NumberKeyboard/NumberKeyboard.stories.tsx | 42 +++ .../NumberKeyboard/NumberKeyboard.tsx | 72 ++++ .../NumberKeyboard/useNumberKeyboard.tsx | 53 +++ .../Design/components/Title/Title.stories.tsx | 12 +- .../Design/components/Title/Title.style.ts | 14 +- .../Design/components/Title/Title.tsx | 34 +- .../Design/components/Title/Title.type.ts | 3 +- .../components/Design/components/Top/Line.tsx | 36 ++ .../Design/components/Top/Top.stories.tsx | 30 ++ .../components/Design/components/Top/Top.tsx | 19 + .../components/Design/layouts/MainLayout.tsx | 2 +- .../ExpenseDetailModal/ExpenseDetailModal.tsx | 130 +++++++ .../ExpenseDetailModal/ExpenseDetailModal.tsx | 142 -------- .../MemberListInBillStep.style.ts | 10 - .../MemberListInBillStep.tsx | 53 --- .../Modal/MemberListInBillStep/index.ts | 1 - .../ModalBasedOnMemberCount.tsx | 39 --- .../AddMemberActionListModalContent.style.ts | 23 -- .../AddMemberActionListModalContent.tsx | 50 --- .../InMember.tsx | 35 -- .../OutMember.tsx | 52 --- .../AddMemberActionListModalContent/index.ts | 1 - .../DeleteMemberActionModal.style.ts | 27 -- .../DeleteMemberActionModal.tsx | 88 ----- .../DeleteMemberActionModal/index.ts | 1 - .../PutAndDeleteBillActionModal.tsx | 155 --------- .../PutAndDeltetBillActionModal.style.ts | 28 -- .../PutAndDeleteBillActionModal/index.ts | 1 - .../SetActionListModal.style.ts | 20 -- .../SetActionModal/SetActionListModal.tsx | 43 --- .../components/Modal/SetActionModal/index.ts | 1 - .../SetAllMemberListModal.style.ts | 36 -- .../SetAllMemberListModal.tsx | 80 ----- .../SetInitialMemberListModal.style.ts | 20 -- .../SetInitialMemberListModal.tsx | 66 ---- .../Modal/SetInitialMemberListModal/index.ts | 1 - client/src/components/Modal/index.ts | 4 - .../Reports.tsx} | 14 +- .../src/components/StepList/BillStepItem.tsx | 139 -------- .../components/StepList/MemberStepItem.tsx | 39 --- .../src/components/StepList/Step.stories.tsx | 60 ++++ client/src/components/StepList/Step.tsx | 71 ++-- client/src/components/StepList/StepList.tsx | 85 ----- client/src/components/StepList/Steps.tsx | 27 ++ client/src/constants/queryKeys.ts | 10 +- client/src/constants/routerUrls.ts | 1 + .../useRequestPostAuthentication.ts | 11 +- .../queries/{ => auth}/useRequestPostLogin.ts | 12 +- .../queries/bill/useRequestDeleteBill.ts | 29 ++ .../queries/bill/useRequestGetBillDetails.ts | 23 ++ .../hooks/queries/bill/useRequestPostBill.ts | 27 ++ .../hooks/queries/bill/useRequestPutBill.ts | 26 ++ .../queries/bill/useRequestPutBillDetails.ts | 48 +++ .../hooks/queries/event/useRequestGetEvent.ts | 25 ++ .../queries/event/useRequestPostEvent.ts | 17 + .../queries/member/useRequestDeleteMember.ts | 26 ++ .../queries/member/useRequestGetAllMembers.ts | 20 ++ .../member/useRequestGetCurrentMembers.ts | 20 ++ .../queries/member/useRequestPostMembers.ts | 32 ++ .../queries/member/useRequestPutMembers.ts | 26 ++ .../queries/report/useRequestGetReports.ts | 22 ++ .../useRequestGetSteps.ts} | 15 +- .../queries/useRequestDeleteAllMemberList.ts | 28 -- .../queries/useRequestDeleteBillAction.ts | 26 -- .../queries/useRequestDeleteMemberAction.ts | 28 -- .../queries/useRequestGetAllMemberList.ts | 18 - .../useRequestGetCurrentInMemberList.ts | 18 - .../hooks/queries/useRequestGetEventName.ts | 18 - .../queries/useRequestGetMemberReportList.ts | 17 - .../useRequestGetMemberReportListInAction.ts | 24 -- .../hooks/queries/useRequestPostBillList.ts | 27 -- .../src/hooks/queries/useRequestPostEvent.ts | 16 - .../hooks/queries/useRequestPostMemberList.ts | 37 -- .../queries/useRequestPutAllMemberList.ts | 28 -- .../hooks/queries/useRequestPutBillAction.ts | 29 -- .../useRequestPutMemberReportListInAction.ts | 49 --- .../useBillDetailInput.tsx} | 31 +- .../hooks/useBillDetails/useBillDetails.ts | 157 +++++++++ .../useDeleteMemberAction.test.tsx | 140 -------- .../useDeleteMemberAction.tsx | 86 ----- client/src/hooks/useDynamicInput.tsx | 142 -------- client/src/hooks/useEventLogin.ts | 4 +- .../useMemberReportListInAction.test.tsx | 327 ------------------ .../useMemberReportListInAction.ts | 156 --------- client/src/hooks/usePutAndDeleteBill.ts | 115 ++++++ client/src/hooks/usePutAndDeleteBillAction.ts | 115 ------ client/src/hooks/useSearchInMemberList.ts | 54 --- .../useSearchMemberReportList.test.tsx | 41 --- .../useSearchMemberReportList.tsx | 17 - client/src/hooks/useSearchReports/index.ts | 1 + .../useSearchReports/useSearchReports.tsx | 16 + client/src/hooks/useSetAllMemberList.tsx | 200 +++++------ client/src/hooks/useSetBillInput.ts | 70 ---- client/src/hooks/useSetEventPasswordPage.ts | 10 +- client/src/index.tsx | 10 +- client/src/mocks/handlers.ts | 8 +- client/src/mocks/handlers/authHandlers.ts | 108 ++---- client/src/mocks/handlers/billHandler.ts | 105 ++++++ client/src/mocks/handlers/eventHandlers.ts | 99 +++--- client/src/mocks/handlers/memberHandler.ts | 62 ++++ .../handlers/memberReportInActionHandlers.ts | 49 --- client/src/mocks/handlers/reportHandlers.ts | 14 +- client/src/mocks/handlers/stepListHandler.ts | 113 ------ client/src/mocks/invalidMemberStepList.json | 100 ------ client/src/mocks/memberActionStepList.json | 23 -- .../src/mocks/memberReportListInAction.json | 6 - client/src/mocks/memberReportSearchList.json | 10 - client/src/mocks/mockEndpointPrefix.ts | 3 + client/src/mocks/reportList.json | 18 - client/src/mocks/sharedState.ts | 109 ++++++ client/src/mocks/stepList.json | 100 ------ client/src/pages/BillPage/AddBillFunnel.tsx | 220 ++++++++++++ .../CompleteCreateEventPage.tsx | 22 +- .../CreateEventPage/SetEventNamePage.tsx | 55 ++- .../CreateEventPage/SetEventPasswordPage.tsx | 63 ++-- client/src/pages/ErrorPage/ErrorPage.tsx | 5 +- .../EventPage/AdminPage/AdminPage.style.ts | 3 +- .../pages/EventPage/AdminPage/AdminPage.tsx | 92 ++--- .../EventPage/AdminPage/EventLoginPage.tsx | 13 +- .../src/pages/EventPage/EventPageLayout.tsx | 5 +- .../src/pages/EventPage/HomePage/HomePage.tsx | 12 +- client/src/pages/MainPage/MainPage.tsx | 4 +- ...berReportSection.tsx => ReportSection.tsx} | 4 +- client/src/router.tsx | 5 + client/src/store/stepListStore.ts | 16 - client/src/store/stepsStore.ts | 16 + client/src/store/totalExpenseAmountStore.ts | 6 +- client/src/types/serviceType.ts | 121 +++---- client/src/utils/caculateExpense.ts | 16 +- client/src/utils/groupActions.ts | 27 -- client/src/utils/stepListToActions.ts | 23 -- ...portInAction.ts => validateBillDetails.ts} | 4 +- 167 files changed, 2801 insertions(+), 3969 deletions(-) rename client/src/apis/{tempPrefix.ts => endpointPrefix.ts} (63%) create mode 100644 client/src/apis/request/step.ts delete mode 100644 client/src/apis/request/stepList.ts rename client/src/apis/{withEventId.type.ts => withId.type.ts} (50%) create mode 100644 client/src/assets/image/meatballs.svg create mode 100644 client/src/components/AmountInput/AmountInput.stories.tsx create mode 100644 client/src/components/AmountInput/AmountInput.tsx create mode 100644 client/src/components/Design/components/Amount/Amount.stories.tsx create mode 100644 client/src/components/Design/components/Amount/Amount.tsx create mode 100644 client/src/components/Design/components/Chip/Chip.stories.tsx create mode 100644 client/src/components/Design/components/Chip/Chip.style.ts create mode 100644 client/src/components/Design/components/Chip/Chip.tsx create mode 100644 client/src/components/Design/components/ChipButton/ChipButton.stories.tsx create mode 100644 client/src/components/Design/components/ChipButton/ChipButton.style.ts create mode 100644 client/src/components/Design/components/ChipButton/ChipButton.tsx create mode 100644 client/src/components/Design/components/ChipGroup/ChipGroup.stories.tsx create mode 100644 client/src/components/Design/components/ChipGroup/ChipGroup.style.ts create mode 100644 client/src/components/Design/components/ChipGroup/ChipGroup.tsx create mode 100644 client/src/components/Design/components/ListItem/ListItem.stories.tsx create mode 100644 client/src/components/Design/components/ListItem/ListItem.style.ts create mode 100644 client/src/components/Design/components/ListItem/ListItem.tsx create mode 100644 client/src/components/Design/components/ListItem/Row.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/Keypad.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx create mode 100644 client/src/components/Design/components/Top/Line.tsx create mode 100644 client/src/components/Design/components/Top/Top.stories.tsx create mode 100644 client/src/components/Design/components/Top/Top.tsx create mode 100644 client/src/components/ExpenseDetailModal/ExpenseDetailModal.tsx delete mode 100644 client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx delete mode 100644 client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts delete mode 100644 client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx delete mode 100644 client/src/components/Modal/MemberListInBillStep/index.ts delete mode 100644 client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx delete mode 100644 client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts delete mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts delete mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx delete mode 100644 client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts delete mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx delete mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts delete mode 100644 client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts delete mode 100644 client/src/components/Modal/SetActionModal/SetActionListModal.style.ts delete mode 100644 client/src/components/Modal/SetActionModal/SetActionListModal.tsx delete mode 100644 client/src/components/Modal/SetActionModal/index.ts delete mode 100644 client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts delete mode 100644 client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx delete mode 100644 client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts delete mode 100644 client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx delete mode 100644 client/src/components/Modal/SetInitialMemberListModal/index.ts delete mode 100644 client/src/components/Modal/index.ts rename client/src/components/{MemberReportList/MemberReportList.tsx => Reports/Reports.tsx} (60%) delete mode 100644 client/src/components/StepList/BillStepItem.tsx delete mode 100644 client/src/components/StepList/MemberStepItem.tsx create mode 100644 client/src/components/StepList/Step.stories.tsx delete mode 100644 client/src/components/StepList/StepList.tsx create mode 100644 client/src/components/StepList/Steps.tsx rename client/src/hooks/queries/{ => auth}/useRequestPostAuthentication.ts (74%) rename client/src/hooks/queries/{ => auth}/useRequestPostLogin.ts (65%) create mode 100644 client/src/hooks/queries/bill/useRequestDeleteBill.ts create mode 100644 client/src/hooks/queries/bill/useRequestGetBillDetails.ts create mode 100644 client/src/hooks/queries/bill/useRequestPostBill.ts create mode 100644 client/src/hooks/queries/bill/useRequestPutBill.ts create mode 100644 client/src/hooks/queries/bill/useRequestPutBillDetails.ts create mode 100644 client/src/hooks/queries/event/useRequestGetEvent.ts create mode 100644 client/src/hooks/queries/event/useRequestPostEvent.ts create mode 100644 client/src/hooks/queries/member/useRequestDeleteMember.ts create mode 100644 client/src/hooks/queries/member/useRequestGetAllMembers.ts create mode 100644 client/src/hooks/queries/member/useRequestGetCurrentMembers.ts create mode 100644 client/src/hooks/queries/member/useRequestPostMembers.ts create mode 100644 client/src/hooks/queries/member/useRequestPutMembers.ts create mode 100644 client/src/hooks/queries/report/useRequestGetReports.ts rename client/src/hooks/queries/{useRequestGetStepList.ts => step/useRequestGetSteps.ts} (69%) delete mode 100644 client/src/hooks/queries/useRequestDeleteAllMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestDeleteBillAction.ts delete mode 100644 client/src/hooks/queries/useRequestDeleteMemberAction.ts delete mode 100644 client/src/hooks/queries/useRequestGetAllMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestGetCurrentInMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestGetEventName.ts delete mode 100644 client/src/hooks/queries/useRequestGetMemberReportList.ts delete mode 100644 client/src/hooks/queries/useRequestGetMemberReportListInAction.ts delete mode 100644 client/src/hooks/queries/useRequestPostBillList.ts delete mode 100644 client/src/hooks/queries/useRequestPostEvent.ts delete mode 100644 client/src/hooks/queries/useRequestPostMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestPutAllMemberList.ts delete mode 100644 client/src/hooks/queries/useRequestPutBillAction.ts delete mode 100644 client/src/hooks/queries/useRequestPutMemberReportListInAction.ts rename client/src/hooks/{useMemberReportListInAction/useMemberReportInput.tsx => useBillDetails/useBillDetailInput.tsx} (69%) create mode 100644 client/src/hooks/useBillDetails/useBillDetails.ts delete mode 100644 client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx delete mode 100644 client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx delete mode 100644 client/src/hooks/useDynamicInput.tsx delete mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx delete mode 100644 client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts create mode 100644 client/src/hooks/usePutAndDeleteBill.ts delete mode 100644 client/src/hooks/usePutAndDeleteBillAction.ts delete mode 100644 client/src/hooks/useSearchInMemberList.ts delete mode 100644 client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx delete mode 100644 client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx create mode 100644 client/src/hooks/useSearchReports/index.ts create mode 100644 client/src/hooks/useSearchReports/useSearchReports.tsx delete mode 100644 client/src/hooks/useSetBillInput.ts create mode 100644 client/src/mocks/handlers/billHandler.ts create mode 100644 client/src/mocks/handlers/memberHandler.ts delete mode 100644 client/src/mocks/handlers/memberReportInActionHandlers.ts delete mode 100644 client/src/mocks/handlers/stepListHandler.ts delete mode 100644 client/src/mocks/invalidMemberStepList.json delete mode 100644 client/src/mocks/memberActionStepList.json delete mode 100644 client/src/mocks/memberReportListInAction.json delete mode 100644 client/src/mocks/memberReportSearchList.json create mode 100644 client/src/mocks/mockEndpointPrefix.ts delete mode 100644 client/src/mocks/reportList.json create mode 100644 client/src/mocks/sharedState.ts delete mode 100644 client/src/mocks/stepList.json create mode 100644 client/src/pages/BillPage/AddBillFunnel.tsx rename client/src/pages/MainPage/Section/{MemberReportSection.tsx => ReportSection.tsx} (91%) delete mode 100644 client/src/store/stepListStore.ts create mode 100644 client/src/store/stepsStore.ts delete mode 100644 client/src/utils/groupActions.ts delete mode 100644 client/src/utils/stepListToActions.ts rename client/src/utils/validate/{validateMemberReportInAction.ts => validateBillDetails.ts} (85%) diff --git a/client/src/apis/tempPrefix.ts b/client/src/apis/endpointPrefix.ts similarity index 63% rename from client/src/apis/tempPrefix.ts rename to client/src/apis/endpointPrefix.ts index 949981b73..18b5756cf 100644 --- a/client/src/apis/tempPrefix.ts +++ b/client/src/apis/endpointPrefix.ts @@ -1,2 +1,3 @@ // TODO: (@weadie) 반복되서 쓰이는 이 api/events가 추후 수정 가능성이 있어서 일단 편집하기 편하게 이 변수를 재사용하도록 했습니다. -export const TEMP_PREFIX = '/api/events'; +export const USER_API_PREFIX = '/api/events'; +export const ADMIN_API_PREFIX = '/api/admin/events'; diff --git a/client/src/apis/request/auth.ts b/client/src/apis/request/auth.ts index 9c56d1f6b..aac5c622d 100644 --- a/client/src/apis/request/auth.ts +++ b/client/src/apis/request/auth.ts @@ -1,23 +1,23 @@ import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestPostWithoutResponse} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; - -export type RequestToken = { - password: string; -}; +import {WithEventId} from '@apis/withId.type'; export const requestPostAuthentication = async ({eventId}: WithEventId) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/auth`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/auth`, }); }; -export const requestPostToken = async ({eventId, password}: WithEventId<RequestToken>) => { +export interface RequestPostToken { + password: string; +} + +export const requestPostToken = async ({eventId, password}: WithEventId<RequestPostToken>) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/login`, + endpoint: `${USER_API_PREFIX}/${eventId}/login`, body: { password: password, }, diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index c08168520..561afcc52 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -1,69 +1,73 @@ -import type {Bill, MemberReportInAction} from 'types/serviceType'; +import type {BillDetails} from 'types/serviceType'; import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestDelete, requestGet, requestPostWithoutResponse, requestPut} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; +import {WithBillId, WithEventId} from '@apis/withId.type'; -type RequestPostBillList = { - billList: Bill[]; -}; +export interface RequestPostBill { + title: string; + price: number; + members: number[]; +} -export const requestPostBillList = async ({eventId, billList}: WithEventId<RequestPostBillList>) => { +export const requestPostBill = async ({eventId, title, price, members}: WithEventId<RequestPostBill>) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills`, body: { - actions: billList, + title, + price, + members, }, }); }; -type RequestBillAction = { - actionId: number; -}; - -export const requestDeleteBillAction = async ({eventId, actionId}: WithEventId<RequestBillAction>) => { +export const requestDeleteBill = async ({eventId, billId}: WithEventId<WithBillId>) => { await requestDelete({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills/${billId}`, }); }; -type RequestPutBillAction = Bill & RequestBillAction; +export interface RequestPutBill { + title: string; + price: number; +} -export const requestPutBillAction = async ({eventId, actionId, title, price}: WithEventId<RequestPutBillAction>) => { +export const requestPutBill = async ({eventId, billId, title, price}: WithEventId<WithBillId<RequestPutBill>>) => { await requestPut({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}`, - body: { - title, - price, - }, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills/${billId}`, + body: {title, price}, }); }; -export type MemberReportList = {members: MemberReportInAction[]}; - -export const requestGetMemberReportListInAction = async ({eventId, actionId}: WithEventId<RequestBillAction>) => { - return requestGet<MemberReportList>({ +export const requestGetBillDetails = async ({eventId, billId}: WithEventId<WithBillId>) => { + return requestGet<BillDetails>({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, + endpoint: `${USER_API_PREFIX}/${eventId}/bills/${billId}/fixed`, }); }; -type RequestPutMemberReportList = RequestBillAction & MemberReportList; +interface PutBillDetail { + id: number; + price: number; + isFixed: boolean; +} + +export interface RequestPutBillDetails { + billDetails: PutBillDetail[]; +} -export const requestPutMemberReportListInAction = async ({ +export const requestPutBillDetails = async ({ eventId, - actionId, - members, -}: WithEventId<RequestPutMemberReportList>) => { - return requestPut({ + billId, + billDetails, +}: WithEventId<WithBillId<RequestPutBillDetails>>) => { + await requestPut({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/bill-actions/${actionId}/fixed`, - body: { - members, - }, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills/${billId}/fixed`, + body: {billDetails}, }); }; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index 6d559e94f..c8c218f3a 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -1,32 +1,43 @@ -import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestGet, requestPostWithResponse} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; +import {Event, EventId} from 'types/serviceType'; -export type RequestPostNewEvent = { +import {USER_API_PREFIX} from '@apis/endpointPrefix'; +import {requestGet, requestPostWithResponse, requestPut} from '@apis/fetcher'; +import {WithEventId} from '@apis/withId.type'; + +export interface RequestPostEvent { eventName: string; password: string; -}; +} -export type ResponsePostNewEvent = { - eventId: string; -}; - -export const requestPostNewEvent = async ({eventName, password}: RequestPostNewEvent) => { - return await requestPostWithResponse<ResponsePostNewEvent>({ - endpoint: TEMP_PREFIX, +export const requestPostEvent = async ({eventName, password}: RequestPostEvent) => { + return await requestPostWithResponse<EventId>({ + endpoint: USER_API_PREFIX, body: { - eventName: eventName, - password: password, + eventName, + password, }, }); }; -type ResponseGetEventName = { - eventName: string; +export const requestGetEvent = async ({eventId}: WithEventId) => { + return await requestGet<Event>({ + endpoint: `${USER_API_PREFIX}/${eventId}`, + }); }; -export const requestGetEventName = async ({eventId}: WithEventId) => { - return requestGet<ResponseGetEventName>({ - endpoint: `${TEMP_PREFIX}/${eventId}`, +export interface RequestPutEvent { + eventName?: string; + bankName?: string; + accountNumber?: string; +} + +export const requestPutEvent = async ({eventId, eventName, bankName, accountNumber}: WithEventId<RequestPutEvent>) => { + return await requestPut({ + endpoint: `${USER_API_PREFIX}/${eventId}`, + body: { + eventName, + bankName, + accountNumber, + }, }); }; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index dd7152575..9c0a0506f 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -1,84 +1,68 @@ -import type {MemberType} from 'types/serviceType'; +import type {AllMembers, Members} from 'types/serviceType'; import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestDelete, requestGet, requestPut, requestPostWithoutResponse} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; +import {requestDelete, requestGet, requestPut, requestPostWithResponse} from '@apis/fetcher'; +import {WithEventId} from '@apis/withId.type'; -type RequestPostMemberList = { - memberNameList: string[]; - type: MemberType; -}; +interface PostMember { + name: string; +} + +export interface RequestPostMembers { + members: PostMember[]; +} -export const requestPostMemberList = async ({eventId, type, memberNameList}: WithEventId<RequestPostMemberList>) => { - await requestPostWithoutResponse({ +export const requestPostMembers = async ({eventId, members: newMembers}: WithEventId<RequestPostMembers>) => { + return await requestPostWithResponse<Members>({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/member-actions`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/members`, body: { - members: memberNameList, - status: type, + members: newMembers, }, }); }; -type RequestDeleteMemberAction = { - actionId: number; -}; +export interface RequestDeleteMember { + memberId: number; +} -export const requestDeleteMemberAction = async ({eventId, actionId}: WithEventId<RequestDeleteMemberAction>) => { +export const requestDeleteMember = async ({eventId, memberId}: WithEventId<RequestDeleteMember>) => { await requestDelete({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/member-actions/${actionId}`, - }); -}; - -type ResponseGetAllMemberList = { - memberNames: string[]; -}; - -export const requestGetAllMemberList = async ({eventId}: WithEventId) => { - return requestGet<ResponseGetAllMemberList>({ - endpoint: `${TEMP_PREFIX}/${eventId}/members`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/members/${memberId}`, }); }; -export type MemberChange = { - before: string; - after: string; -}; +interface PutMember { + id: number; + name: string; + isDeposited: boolean; +} -type RequestPutAllMemberList = { - members: MemberChange[]; -}; +export interface RequestPutMembers { + members: PutMember[]; +} -export const requestPutAllMemberList = async ({eventId, members}: WithEventId<RequestPutAllMemberList>) => { +export const requestPutMembers = async ({eventId, members}: WithEventId<RequestPutMembers>) => { await requestPut({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/members/nameChange`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/members`, body: { - members, + members: members, }, }); }; -type RequestDeleteAllMemberList = { - memberName: string; -}; - -export const requestDeleteAllMemberList = async ({eventId, memberName}: WithEventId<RequestDeleteAllMemberList>) => { - await requestDelete({ +export const requestGetCurrentMembers = async ({eventId}: WithEventId) => { + return await requestGet<Members>({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/members/${memberName}`, + endpoint: `${USER_API_PREFIX}/${eventId}/members/current`, }); }; -export type ResponseGetCurrentInMemberList = { - memberNames: string[]; -}; - -export const requestGetCurrentInMemberList = async ({eventId}: WithEventId) => { - return await requestGet<ResponseGetCurrentInMemberList>({ - baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/members/current`, +export const requestGetAllMembers = async ({eventId}: WithEventId) => { + return await requestGet<AllMembers>({ + endpoint: `${USER_API_PREFIX}/${eventId}/members`, }); }; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts index 8992f9c30..6d73ff161 100644 --- a/client/src/apis/request/report.ts +++ b/client/src/apis/request/report.ts @@ -1,19 +1,13 @@ -import type {MemberReport} from 'types/serviceType'; +import type {Reports} from 'types/serviceType'; import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestGet} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; +import {WithEventId} from '@apis/withId.type'; -type ResponseGetMemberReportList = { - reports: MemberReport[]; -}; - -export const requestGetMemberReportList = async ({eventId}: WithEventId) => { - const {reports} = await requestGet<ResponseGetMemberReportList>({ +export const requestGetReports = async ({eventId}: WithEventId) => { + return await requestGet<Reports>({ baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/actions/reports`, + endpoint: `${USER_API_PREFIX}/${eventId}/reports`, }); - - return reports; }; diff --git a/client/src/apis/request/step.ts b/client/src/apis/request/step.ts new file mode 100644 index 000000000..f67615e2d --- /dev/null +++ b/client/src/apis/request/step.ts @@ -0,0 +1,15 @@ +import {Steps} from 'types/serviceType'; + +import {BASE_URL} from '@apis/baseUrl'; +import {USER_API_PREFIX} from '@apis/endpointPrefix'; +import {requestGet} from '@apis/fetcher'; +import {WithEventId} from '@apis/withId.type'; + +export const requestGetSteps = async ({eventId}: WithEventId) => { + const {steps} = await requestGet<Steps>({ + baseUrl: BASE_URL.HD, + endpoint: `${USER_API_PREFIX}/${eventId}/bills`, + }); + + return steps; +}; diff --git a/client/src/apis/request/stepList.ts b/client/src/apis/request/stepList.ts deleted file mode 100644 index 0d47ab90e..000000000 --- a/client/src/apis/request/stepList.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type {StepList} from 'types/serviceType'; - -import {BASE_URL} from '@apis/baseUrl'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; -import {requestGet} from '@apis/fetcher'; -import {WithEventId} from '@apis/withEventId.type'; - -// TODO: (@weadie) 현재 토큰을 어떻게 관리할지.. 계속 사용되는데 -export const requestGetStepList = async ({eventId}: WithEventId) => { - // TODO: (@weadie) response가 어떻게 오는지 안나와서 data로만 써뒀어요. - const {steps} = await requestGet<StepList>({ - baseUrl: BASE_URL.HD, - endpoint: `${TEMP_PREFIX}/${eventId}/actions`, - }); - - return steps; -}; diff --git a/client/src/apis/withEventId.type.ts b/client/src/apis/withId.type.ts similarity index 50% rename from client/src/apis/withEventId.type.ts rename to client/src/apis/withId.type.ts index b88160e3e..2b1d3c2e8 100644 --- a/client/src/apis/withEventId.type.ts +++ b/client/src/apis/withId.type.ts @@ -1,3 +1,7 @@ export type WithEventId<P = unknown> = P & { eventId: string; }; + +export type WithBillId<P = unknown> = P & { + billId: number; +}; diff --git a/client/src/assets/image/meatballs.svg b/client/src/assets/image/meatballs.svg new file mode 100644 index 000000000..bc3e17d2f --- /dev/null +++ b/client/src/assets/image/meatballs.svg @@ -0,0 +1,3 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M12 18C12.1989 18 12.3897 17.921 12.5303 17.7803C12.671 17.6397 12.75 17.4489 12.75 17.25C12.75 17.0511 12.671 16.8603 12.5303 16.7197C12.3897 16.579 12.1989 16.5 12 16.5C11.8011 16.5 11.6103 16.579 11.4697 16.7197C11.329 16.8603 11.25 17.0511 11.25 17.25C11.25 17.4489 11.329 17.6397 11.4697 17.7803C11.6103 17.921 11.8011 18 12 18ZM12 12.75C12.1989 12.75 12.3897 12.671 12.5303 12.5303C12.671 12.3897 12.75 12.1989 12.75 12C12.75 11.8011 12.671 11.6103 12.5303 11.4697C12.3897 11.329 12.1989 11.25 12 11.25C11.8011 11.25 11.6103 11.329 11.4697 11.4697C11.329 11.6103 11.25 11.8011 11.25 12C11.25 12.1989 11.329 12.3897 11.4697 12.5303C11.6103 12.671 11.8011 12.75 12 12.75ZM12 7.5C12.1989 7.5 12.3897 7.42098 12.5303 7.28033C12.671 7.13968 12.75 6.94891 12.75 6.75C12.75 6.55109 12.671 6.36032 12.5303 6.21967C12.3897 6.07902 12.1989 6 12 6C11.8011 6 11.6103 6.07902 11.4697 6.21967C11.329 6.36032 11.25 6.55109 11.25 6.75C11.25 6.94891 11.329 7.13968 11.4697 7.28033C11.6103 7.42098 11.8011 7.5 12 7.5Z" stroke="currentColor" stroke-width="1.5"/> +</svg> diff --git a/client/src/components/AmountInput/AmountInput.stories.tsx b/client/src/components/AmountInput/AmountInput.stories.tsx new file mode 100644 index 000000000..84cedb178 --- /dev/null +++ b/client/src/components/AmountInput/AmountInput.stories.tsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import AmountInput from './AmountInput'; + +const meta = { + title: 'Components/AmountInput', + component: AmountInput, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: {}, + args: { + value: '112,000', + }, +} satisfies Meta<typeof AmountInput>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/client/src/components/AmountInput/AmountInput.tsx b/client/src/components/AmountInput/AmountInput.tsx new file mode 100644 index 000000000..c82672956 --- /dev/null +++ b/client/src/components/AmountInput/AmountInput.tsx @@ -0,0 +1,37 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Text} from '@components/Design'; + +interface Props { + value: string; +} + +const AmountInput = ({value}: Props) => { + return ( + <div + css={css` + display: flex; + /* height: 4.5rem; */ + justify-content: end; + align-items: end; + gap: 0.5rem; + `} + > + <Text size="head" textColor={value ? 'black' : 'gray'}> + {value ? value : '0'} + </Text> + <Text + textColor="gray" + size="body" + css={css` + margin-bottom: 0.75rem; + `} + > + 원 + </Text> + </div> + ); +}; + +export default AmountInput; diff --git a/client/src/components/Design/components/Amount/Amount.stories.tsx b/client/src/components/Design/components/Amount/Amount.stories.tsx new file mode 100644 index 000000000..bb9ce5b5c --- /dev/null +++ b/client/src/components/Design/components/Amount/Amount.stories.tsx @@ -0,0 +1,28 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Amount from '@HDcomponents/Amount/Amount'; + +const meta = { + title: 'Components/Amount', + component: Amount, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + amount: { + description: '', + control: {type: 'number'}, + }, + }, + args: { + amount: 112000, + }, +} satisfies Meta<typeof Amount>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Amount/Amount.tsx b/client/src/components/Design/components/Amount/Amount.tsx new file mode 100644 index 000000000..f491df6ba --- /dev/null +++ b/client/src/components/Design/components/Amount/Amount.tsx @@ -0,0 +1,20 @@ +/** @jsxImportSource @emotion/react */ +import Flex from '../Flex/Flex'; +import Text from '../Text/Text'; + +interface Props { + amount: number; +} + +const Amount = ({amount}: Props) => { + return ( + <Flex alignItems="center" gap="0.25rem"> + <Text>{amount ? amount.toLocaleString('ko-kr') : 0}</Text> + <Text size="tiny" textColor="gray"> + 원 + </Text> + </Flex> + ); +}; + +export default Amount; diff --git a/client/src/components/Design/components/Button/Button.style.ts b/client/src/components/Design/components/Button/Button.style.ts index 7b76cf789..0d274f116 100644 --- a/client/src/components/Design/components/Button/Button.style.ts +++ b/client/src/components/Design/components/Button/Button.style.ts @@ -23,7 +23,7 @@ const getButtonDefaultStyle = (theme: Theme) => whiteSpace: 'nowrap', '&:disabled': { - backgroundColor: theme.colors.tertiary, + backgroundColor: theme.colors.grayContainer, color: theme.colors.onPrimary, cursor: 'default', }, diff --git a/client/src/components/Design/components/Chip/Chip.stories.tsx b/client/src/components/Design/components/Chip/Chip.stories.tsx new file mode 100644 index 000000000..08e7f259c --- /dev/null +++ b/client/src/components/Design/components/Chip/Chip.stories.tsx @@ -0,0 +1,36 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Chip from '@HDcomponents/Chip/Chip'; + +import Text from '../Text/Text'; +import Amount from '../Amount/Amount'; + +const meta = { + title: 'Components/Chip', + component: Chip, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + color: { + description: '', + control: {type: 'select'}, + }, + text: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + color: 'gray', + text: '망쵸', + }, +} satisfies Meta<typeof Chip>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Chip/Chip.style.ts b/client/src/components/Design/components/Chip/Chip.style.ts new file mode 100644 index 000000000..a7ca3eaf7 --- /dev/null +++ b/client/src/components/Design/components/Chip/Chip.style.ts @@ -0,0 +1,20 @@ +import {css} from '@emotion/react'; + +import {ColorKeys} from '@components/Design/token/colors'; +import {Theme} from '@theme/theme.type'; + +interface ChipStyleProps { + theme: Theme; + color: ColorKeys; +} + +export const chipStyle = ({theme, color}: ChipStyleProps) => + css({ + display: 'flex', + padding: '0.125rem 0.5rem ', + borderRadius: '0.5rem', + color: `${theme.colors[color]}`, + boxSizing: 'border-box', + outline: 'none', + boxShadow: `inset 0 0 0 1px ${theme.colors[color]}`, + }); diff --git a/client/src/components/Design/components/Chip/Chip.tsx b/client/src/components/Design/components/Chip/Chip.tsx new file mode 100644 index 000000000..9566dfe7e --- /dev/null +++ b/client/src/components/Design/components/Chip/Chip.tsx @@ -0,0 +1,26 @@ +/** @jsxImportSource @emotion/react */ + +import {ColorKeys} from '@components/Design/token/colors'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {chipStyle} from './Chip.style'; + +interface Props { + color: ColorKeys; + text: string; +} + +const Chip = ({color, text}: Props) => { + const {theme} = useTheme(); + return ( + <div css={chipStyle({color, theme})}> + <Text size="tiny" textColor={color}> + {text} + </Text> + </div> + ); +}; + +export default Chip; diff --git a/client/src/components/Design/components/ChipButton/ChipButton.stories.tsx b/client/src/components/Design/components/ChipButton/ChipButton.stories.tsx new file mode 100644 index 000000000..b3d3ea534 --- /dev/null +++ b/client/src/components/Design/components/ChipButton/ChipButton.stories.tsx @@ -0,0 +1,34 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ChipButton from '@HDcomponents/ChipButton/ChipButton'; + +const meta = { + title: 'Components/ChipButton', + component: ChipButton, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + color: { + description: '', + control: {type: 'select'}, + }, + text: { + description: '', + control: {type: 'text'}, + }, + }, + args: { + color: 'gray', + text: '망쵸', + onClick: () => {}, + }, +} satisfies Meta<typeof ChipButton>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/ChipButton/ChipButton.style.ts b/client/src/components/Design/components/ChipButton/ChipButton.style.ts new file mode 100644 index 000000000..ec0a19c0b --- /dev/null +++ b/client/src/components/Design/components/ChipButton/ChipButton.style.ts @@ -0,0 +1,21 @@ +import {css} from '@emotion/react'; + +import {ColorKeys} from '@components/Design/token/colors'; +import {Theme} from '@theme/theme.type'; + +interface ChipStyleProps { + theme: Theme; + color: ColorKeys; +} + +export const chipButtonStyle = ({theme, color}: ChipStyleProps) => + css({ + display: 'flex', + padding: '0.25rem 0.375rem 0.25rem 0.75rem', + gap: '0.5rem', + borderRadius: '1rem', + color: `${theme.colors[color]}`, + boxSizing: 'border-box', + outline: 'none', + boxShadow: `inset 0 0 0 1px ${theme.colors[color]}`, + }); diff --git a/client/src/components/Design/components/ChipButton/ChipButton.tsx b/client/src/components/Design/components/ChipButton/ChipButton.tsx new file mode 100644 index 000000000..7b0e1aa50 --- /dev/null +++ b/client/src/components/Design/components/ChipButton/ChipButton.tsx @@ -0,0 +1,27 @@ +/** @jsxImportSource @emotion/react */ + +import {ColorKeys} from '@components/Design/token/colors'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Text from '../Text/Text'; +import Icon from '../Icon/Icon'; + +import {chipButtonStyle} from './ChipButton.style'; + +interface Props { + color: ColorKeys; + text: string; + onClick: () => void; +} + +const ChipButton = ({color, text, onClick}: Props) => { + const {theme} = useTheme(); + return ( + <div css={chipButtonStyle({color, theme})}> + <Text textColor="black">{text}</Text> + <Icon iconType="inputDelete" onClick={onClick} /> + </div> + ); +}; + +export default ChipButton; diff --git a/client/src/components/Design/components/ChipGroup/ChipGroup.stories.tsx b/client/src/components/Design/components/ChipGroup/ChipGroup.stories.tsx new file mode 100644 index 000000000..f60a84a01 --- /dev/null +++ b/client/src/components/Design/components/ChipGroup/ChipGroup.stories.tsx @@ -0,0 +1,29 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ChipGroup from '@HDcomponents/ChipGroup/ChipGroup'; + +const meta = { + title: 'Components/ChipGroup', + component: ChipGroup, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + color: { + description: '', + control: {type: 'select'}, + }, + }, + args: { + color: 'gray', + texts: ['망쵸', '감자', '백호', '이상'], + }, +} satisfies Meta<typeof ChipGroup>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts b/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts new file mode 100644 index 000000000..f85afd3af --- /dev/null +++ b/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts @@ -0,0 +1,6 @@ +import {css} from '@emotion/react'; + +export const chipGroupStyle = css({ + display: 'flex', + gap: '0.25rem', +}); diff --git a/client/src/components/Design/components/ChipGroup/ChipGroup.tsx b/client/src/components/Design/components/ChipGroup/ChipGroup.tsx new file mode 100644 index 000000000..792228217 --- /dev/null +++ b/client/src/components/Design/components/ChipGroup/ChipGroup.tsx @@ -0,0 +1,27 @@ +/** @jsxImportSource @emotion/react */ + +import {ColorKeys} from '@components/Design/token/colors'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import {chipStyle} from '../Chip/Chip.style'; +import Text from '../Text/Text'; +import Chip from '../Chip/Chip'; + +import {chipGroupStyle} from './ChipGroup.style'; + +interface Props { + color: ColorKeys; + texts: string[]; +} + +const ChipGroup = ({color, texts}: Props) => { + return ( + <div css={chipGroupStyle}> + {texts.map(text => ( + <Chip color={color} text={text} /> + ))} + </div> + ); +}; + +export default ChipGroup; diff --git a/client/src/components/Design/components/FixedButton/FixedButton.style.ts b/client/src/components/Design/components/FixedButton/FixedButton.style.ts index a0128a3ee..00a7ea255 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.style.ts +++ b/client/src/components/Design/components/FixedButton/FixedButton.style.ts @@ -59,6 +59,32 @@ export const fixedButtonStyle = (props: Required<FixedButtonStyleProps>) => { return [getFixedButtonDefaultStyle(props.theme), getFixedButtonVariantsStyle(props.variants, props.theme)]; }; +export const cancleButtonStyle = (theme: Theme) => + css({ + display: 'flex', + justifyContent: 'center', + padding: '1rem 1.5rem', + borderRadius: '1rem', + width: '100%', + + fontFamily: 'Pretendard', + fontSize: '1.25rem', + fontWeight: '700', + lineHeight: '1', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + backgroundColor: theme.colors.tertiary, + color: theme.colors.onTertiary, + + '&:disabled': { + backgroundColor: theme.colors.grayContainer, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); + const getFixedButtonDefaultStyle = (theme: Theme) => css({ display: 'flex', @@ -76,7 +102,7 @@ const getFixedButtonDefaultStyle = (theme: Theme) => transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', '&:disabled': { - backgroundColor: theme.colors.tertiary, + backgroundColor: theme.colors.grayContainer, color: theme.colors.onPrimary, cursor: 'default', }, diff --git a/client/src/components/Design/components/FixedButton/FixedButton.tsx b/client/src/components/Design/components/FixedButton/FixedButton.tsx index 3114bb9ce..62ea0127e 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.tsx +++ b/client/src/components/Design/components/FixedButton/FixedButton.tsx @@ -7,6 +7,7 @@ import { fixedButtonContainerStyle, fixedButtonStyle, buttonContainerStyle, + cancleButtonStyle, } from '@HDcomponents/FixedButton/FixedButton.style'; import {FixedButtonProps} from '@HDcomponents/FixedButton/FixedButton.type'; import IconButton from '@HDcomponents/IconButton/IconButton'; @@ -14,7 +15,7 @@ import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElement, FixedButtonProps>(function Button( - {variants = 'primary', onDeleteClick, disabled, children, ...htmlProps}: FixedButtonProps, + {variants = 'primary', onDeleteClick, onBackClick, disabled, children, ...htmlProps}: FixedButtonProps, ref, ) { const {theme} = useTheme(); @@ -26,6 +27,11 @@ export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElem <Icon iconType="trash" /> </IconButton> )} + {onBackClick && ( + <button css={cancleButtonStyle(theme)} ref={ref} onClick={onBackClick}> + 이전으로 + </button> + )} <button css={fixedButtonStyle({variants, theme})} ref={ref} diff --git a/client/src/components/Design/components/FixedButton/FixedButton.type.ts b/client/src/components/Design/components/FixedButton/FixedButton.type.ts index 4d4f74a08..80efc8172 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.type.ts +++ b/client/src/components/Design/components/FixedButton/FixedButton.type.ts @@ -8,6 +8,7 @@ export interface FixedButtonStyleProps { export interface ButtonCustomProps { onDeleteClick?: () => void; + onBackClick?: () => void; } export type FixedButtonOptionProps = FixedButtonStyleProps & ButtonCustomProps; diff --git a/client/src/components/Design/components/Icon/Icon.style.ts b/client/src/components/Design/components/Icon/Icon.style.ts index f0ac3db04..6380f6dc1 100644 --- a/client/src/components/Design/components/Icon/Icon.style.ts +++ b/client/src/components/Design/components/Icon/Icon.style.ts @@ -13,6 +13,7 @@ const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { confirm: 'complete', error: 'warn', trash: 'white', + meatballs: 'black', }; export const iconStyle = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { diff --git a/client/src/components/Design/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx index cfe22a786..307950976 100644 --- a/client/src/components/Design/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -7,6 +7,7 @@ import Confirm from '@assets/image/confirm.svg'; import Trash from '@assets/image/trash.svg'; import Search from '@assets/image/search.svg'; import RightChevron from '@assets/image/rightChevron.svg'; +import Meatballs from '@assets/image/meatballs.svg'; import {IconProps} from '@HDcomponents/Icon/Icon.type'; import {useTheme} from '@theme/HDesignProvider'; @@ -20,6 +21,7 @@ const ICON = { error: <Error />, confirm: <Confirm />, trash: <Trash />, + meatballs: <Meatballs />, }; export const Icon: React.FC<IconProps> = ({iconColor, iconType, ...htmlProps}: IconProps) => { diff --git a/client/src/components/Design/components/Icon/Icon.type.ts b/client/src/components/Design/components/Icon/Icon.type.ts index f07679cf0..7cb7542b0 100644 --- a/client/src/components/Design/components/Icon/Icon.type.ts +++ b/client/src/components/Design/components/Icon/Icon.type.ts @@ -1,7 +1,16 @@ +import {Meatballs} from '@assets/image/meatballs.svg'; import {Theme} from '@theme/theme.type'; import {ColorKeys} from '@token/colors'; -export type IconType = 'inputDelete' | 'buljusa' | 'rightChevron' | 'search' | 'error' | 'confirm' | 'trash'; +export type IconType = + | 'inputDelete' + | 'buljusa' + | 'rightChevron' + | 'search' + | 'error' + | 'confirm' + | 'trash' + | 'meatballs'; export type IconColor = ColorKeys; export interface IconStyleProps { diff --git a/client/src/components/Design/components/ListItem/ListItem.stories.tsx b/client/src/components/Design/components/ListItem/ListItem.stories.tsx new file mode 100644 index 000000000..5d7f12e1c --- /dev/null +++ b/client/src/components/Design/components/ListItem/ListItem.stories.tsx @@ -0,0 +1,37 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import ListItem from '@HDcomponents/ListItem/ListItem'; + +import Text from '../Text/Text'; +import Amount from '../Amount/Amount'; + +const meta = { + title: 'Components/ListItem', + component: ListItem, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: {}, + args: {}, +} satisfies Meta<typeof ListItem>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + return ( + <div style={{width: '400px'}}> + <ListItem> + <ListItem.Row> + <Text size="bodyBold">뽕쟁이 족발</Text> + <Amount amount={112000} /> + </ListItem.Row> + </ListItem> + </div> + ); + }, +}; diff --git a/client/src/components/Design/components/ListItem/ListItem.style.ts b/client/src/components/Design/components/ListItem/ListItem.style.ts new file mode 100644 index 000000000..755feab36 --- /dev/null +++ b/client/src/components/Design/components/ListItem/ListItem.style.ts @@ -0,0 +1,21 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@components/Design/theme/theme.type'; + +export const listItemStyle = (theme: Theme) => + css({ + display: 'flex', + flexDirection: 'column', + width: '100%', + gap: '0.5rem', + backgroundColor: theme.colors.white, + padding: '0.5rem 1rem', + borderRadius: '0.75rem', + }); + +export const rowStyle = (theme: Theme) => + css({ + display: 'flex', + width: '100%', + justifyContent: 'space-between', + }); diff --git a/client/src/components/Design/components/ListItem/ListItem.tsx b/client/src/components/Design/components/ListItem/ListItem.tsx new file mode 100644 index 000000000..fc99b4c1a --- /dev/null +++ b/client/src/components/Design/components/ListItem/ListItem.tsx @@ -0,0 +1,14 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import {listItemStyle} from './ListItem.style'; +import Row from './Row'; + +const ListItem = ({children}: React.PropsWithChildren) => { + const {theme} = useTheme(); + return <div css={listItemStyle(theme)}>{children}</div>; +}; + +ListItem.Row = Row; + +export default ListItem; diff --git a/client/src/components/Design/components/ListItem/Row.tsx b/client/src/components/Design/components/ListItem/Row.tsx new file mode 100644 index 000000000..aec6a749d --- /dev/null +++ b/client/src/components/Design/components/ListItem/Row.tsx @@ -0,0 +1,11 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import {rowStyle} from './ListItem.style'; + +const Row = ({children}: React.PropsWithChildren) => { + const {theme} = useTheme(); + return <div css={rowStyle(theme)}>{children}</div>; +}; + +export default Row; diff --git a/client/src/components/Design/components/NumberKeyboard/Keypad.tsx b/client/src/components/Design/components/NumberKeyboard/Keypad.tsx new file mode 100644 index 000000000..3f41fad95 --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/Keypad.tsx @@ -0,0 +1,42 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {setDarker, setLighter} from '@components/Design/utils/colors'; + +import {Text, useTheme} from '@components/Design'; + +interface Props { + value: string; + onClick: () => void; + disabled?: boolean; +} + +export function Keypad({value, onClick, disabled = false}: Props) { + const {theme} = useTheme(); + return ( + <button + css={css` + display: flex; + justify-content: center; + width: 100%; + height: 3rem; + border-radius: 1rem; + transition: 0.2s; + transition-timing-function: cubic-bezier(0.7, 0.62, 0.62, 1.16); + + :not(:disabled) { + &:hover { + background-color: ${setLighter(theme.colors.lightGrayContainer, 0.15)}; + } + &:active { + background-color: ${setDarker(theme.colors.lightGrayContainer, 0.15)}; + } + } + `} + onClick={onClick} + disabled={disabled} + > + <Text size="title">{value}</Text> + </button> + ); +} diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx new file mode 100644 index 000000000..a6a525553 --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx @@ -0,0 +1,42 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useRef, useState} from 'react'; + +import {Flex, Input} from '@components/Design'; + +import NumberKeyboard from './NumberKeyboard'; + +const meta = { + title: 'Components/NumberKeyboard', + component: NumberKeyboard, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + type: {description: '', control: {type: 'select'}, options: ['amount', 'number', 'string']}, + }, + args: { + type: 'amount', + maxNumber: 10000000, + onChange: () => {}, + }, +} satisfies Meta<typeof NumberKeyboard>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({type, maxNumber}) => { + const inputRef = useRef<HTMLInputElement>(null); + const [value, setValue] = useState(''); + return ( + <Flex flexDirection="column" gap="2rem" width="430px"> + <Input ref={inputRef} value={value} placeholder="금액을 입력하세요" /> + <NumberKeyboard type={type} maxNumber={maxNumber} onChange={setValue} /> + </Flex> + ); + }, +}; diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx new file mode 100644 index 000000000..0da3862de --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx @@ -0,0 +1,72 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import {Button, useTheme} from '@components/Design'; + +import {Keypad} from './Keypad'; +import useNumberKeyboard from './useNumberKeyboard'; + +export type KeyboardType = 'number' | 'string' | 'amount'; + +interface Props { + type: KeyboardType; + maxNumber: number; + onChange: (value: string) => void; +} + +export default function NumberKeyboard({type, maxNumber, onChange}: Props) { + const {theme} = useTheme(); + const amountKeypads = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '00', '0', '<-']; + const numberKeypads = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '', '0', '<-']; + + const {onClickKeypad, onClickDelete, onClickDeleteAll, onClickAddAmount} = useNumberKeyboard({ + type, + maxNumber, + onChange, + }); + + return ( + <div + css={css` + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-template-rows: ${type === 'amount' ? 'auto' : null} repeat(4, 1fr); + padding: 1rem; + gap: 1rem; + background-color: ${theme.colors.white}; + `} + > + {type === 'amount' && ( + <div + css={css` + grid-column: 1 / -1; + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1rem; + `} + > + <Button size="small" variants="tertiary" onClick={() => onClickAddAmount(10000)}> + +1만 + </Button> + <Button size="small" variants="tertiary" onClick={() => onClickAddAmount(50000)}> + +5만 + </Button> + <Button size="small" variants="tertiary" onClick={() => onClickAddAmount(100000)}> + +10만 + </Button> + <Button size="small" variants="tertiary" onClick={onClickDeleteAll}> + 전체 삭제 + </Button> + </div> + )} + {(type === 'amount' ? amountKeypads : numberKeypads).map(el => ( + <Keypad + key={el} + value={el} + disabled={el === ''} + onClick={el === '<-' ? onClickDelete : () => onClickKeypad(el)} + /> + ))} + </div> + ); +} diff --git a/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx new file mode 100644 index 000000000..f8d5fbaed --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx @@ -0,0 +1,53 @@ +import {useEffect, useState} from 'react'; + +import {KeyboardType} from './NumberKeyboard'; + +interface Props { + type: KeyboardType; + maxNumber?: number; + onChange: (value: string) => void; +} + +const useNumberKeyboard = ({type, maxNumber, onChange}: Props) => { + const [value, setValue] = useState(''); + + const onClickKeypad = (inputValue: string) => { + const newValue = (value + inputValue).replace(/,/g, ''); + setValueByType(newValue); + }; + + const onClickDelete = () => { + const newValue = value.slice(0, value.length - 1).replace(/,/g, ''); + setValueByType(newValue); + }; + + const onClickDeleteAll = () => { + setValue(''); + }; + + const onClickAddAmount = (amount: number) => { + const newValue = `${Number(value.replace(/,/g, '')) + amount}`; + setValueByType(newValue); + }; + + const setValueByType = (value: string) => { + if (type === 'string') { + setValue(value); + } else { + const limitedValue = maxNumber && Number(value) > maxNumber ? `${maxNumber}` : value; + if (Number(limitedValue) === 0) { + setValue(''); + } else { + setValue(type === 'amount' ? Number(limitedValue).toLocaleString() : `${limitedValue}`); + } + } + }; + + useEffect(() => { + onChange(value); + }, [value]); + + return {value, onClickKeypad, onClickDelete, onClickDeleteAll, onClickAddAmount}; +}; + +export default useNumberKeyboard; diff --git a/client/src/components/Design/components/Title/Title.stories.tsx b/client/src/components/Design/components/Title/Title.stories.tsx index 4eab2d5c8..899c78b83 100644 --- a/client/src/components/Design/components/Title/Title.stories.tsx +++ b/client/src/components/Design/components/Title/Title.stories.tsx @@ -14,20 +14,14 @@ const meta = { description: '', control: {type: 'text'}, }, - description: { - description: '', - control: {type: 'text'}, - }, - price: { + amount: { description: '', control: {type: 'number'}, }, }, args: { - title: '페이지 제목이에요', - description: `이곳에는 페이지 설명이 들어가요. - 페이지에 대한 설명을 자세하게 적어주면 좋아요 :)`, - price: 100000, + title: '행동대장 야유회', + amount: 100000, }, } satisfies Meta<typeof Title>; diff --git a/client/src/components/Design/components/Title/Title.style.ts b/client/src/components/Design/components/Title/Title.style.ts index ab347a214..bd19002d1 100644 --- a/client/src/components/Design/components/Title/Title.style.ts +++ b/client/src/components/Design/components/Title/Title.style.ts @@ -2,18 +2,26 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; -export const titleContainerStyle = (theme: Theme) => +export const titleStyle = (theme: Theme) => css({ display: 'flex', flexDirection: 'column', width: '100%', gap: '0.5rem', backgroundColor: theme.colors.white, - padding: '1rem', + padding: '0.5rem', + borderRadius: '0.75rem', }); -export const priceContainerStyle = css({ +export const titleContainerStyle = css({ + display: 'flex', + justifyContent: 'space-between', + paddingLeft: '0.5rem', +}); + +export const amountContainerStyle = css({ display: 'flex', justifyContent: 'space-between', alignItems: 'end', + paddingInline: '0.5rem', }); diff --git a/client/src/components/Design/components/Title/Title.tsx b/client/src/components/Design/components/Title/Title.tsx index 4050399ea..1c28c3325 100644 --- a/client/src/components/Design/components/Title/Title.tsx +++ b/client/src/components/Design/components/Title/Title.tsx @@ -1,31 +1,27 @@ /** @jsxImportSource @emotion/react */ import Flex from '@HDcomponents/Flex/Flex'; import Text from '@HDcomponents/Text/Text'; -import {priceContainerStyle, titleContainerStyle} from '@HDcomponents/Title/Title.style'; +import {amountContainerStyle, titleContainerStyle, titleStyle} from '@HDcomponents/Title/Title.style'; import {TitleProps} from '@HDcomponents/Title/Title.type'; import {useTheme} from '@theme/HDesignProvider'; -export const Title: React.FC<TitleProps> = ({title, description, price}: TitleProps) => { +import Icon from '../Icon/Icon'; +import Amount from '../Amount/Amount'; + +export const Title: React.FC<TitleProps> = ({title, amount}: TitleProps) => { const {theme} = useTheme(); return ( - <div css={titleContainerStyle(theme)}> - <Text size="subTitle">{title}</Text> - {description && ( - <Text textColor="darkGray" size="body"> - {description} + <div css={titleStyle(theme)}> + <div css={titleContainerStyle}> + <Text size="subTitle">{title}</Text> + <Icon iconType="meatballs" /> + </div> + <div css={amountContainerStyle}> + <Text textColor="gray" size="caption"> + 전체 지출 금액 </Text> - )} - {price !== undefined && ( - <div css={priceContainerStyle}> - <Text textColor="gray" size="caption"> - 전체 지출 금액 - </Text> - <Flex alignItems="center" gap="0.25rem"> - <Text>{price.toLocaleString('ko-kr')}</Text> - <Text size="caption">원</Text> - </Flex> - </div> - )} + <Amount amount={amount ?? 0} /> + </div> </div> ); }; diff --git a/client/src/components/Design/components/Title/Title.type.ts b/client/src/components/Design/components/Title/Title.type.ts index 4b12f23b2..2b0718dda 100644 --- a/client/src/components/Design/components/Title/Title.type.ts +++ b/client/src/components/Design/components/Title/Title.type.ts @@ -2,8 +2,7 @@ export interface TitleStyleProps {} export interface TitleCustomProps { title: string; - description?: string; - price?: number; + amount?: number; } export type TitleOptionProps = TitleStyleProps & TitleCustomProps; diff --git a/client/src/components/Design/components/Top/Line.tsx b/client/src/components/Design/components/Top/Line.tsx new file mode 100644 index 000000000..552dc0276 --- /dev/null +++ b/client/src/components/Design/components/Top/Line.tsx @@ -0,0 +1,36 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import Text from '../Text/Text'; + +interface Props { + text: string; + emphasize?: string[]; +} + +export default function Line({text, emphasize = []}: Props) { + const getTextElements = ({text, emphasize = []}: Props) => { + if (emphasize.length === 0) return [text]; + + const regexPattern = new RegExp(`(${emphasize.join('|')})`, 'g'); + return text.split(regexPattern).filter(Boolean); + }; + + const elements = getTextElements({text, emphasize}); + + return ( + <div + css={css` + display: flex; + `} + > + {elements.map(text => { + return ( + <Text size="subTitle" textColor={emphasize.includes(text) ? 'black' : 'gray'} style={{whiteSpace: 'pre'}}> + {`${text}`} + </Text> + ); + })} + </div> + ); +} diff --git a/client/src/components/Design/components/Top/Top.stories.tsx b/client/src/components/Design/components/Top/Top.stories.tsx new file mode 100644 index 000000000..20aa07b8e --- /dev/null +++ b/client/src/components/Design/components/Top/Top.stories.tsx @@ -0,0 +1,30 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Top from '@HDcomponents/Top/Top'; + +const meta = { + title: 'Components/Top', + component: Top, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: {}, + args: {}, +} satisfies Meta<typeof Top>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + return ( + <Top> + <Top.Line text="정산을 시작하려는" /> + <Top.Line text="행사의 이름은 무엇인가요?" emphasize={['행사의 이름']} /> + </Top> + ); + }, +}; diff --git a/client/src/components/Design/components/Top/Top.tsx b/client/src/components/Design/components/Top/Top.tsx new file mode 100644 index 000000000..9d00801d5 --- /dev/null +++ b/client/src/components/Design/components/Top/Top.tsx @@ -0,0 +1,19 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + +import Line from './Line'; + +Top.Line = Line; + +export default function Top({children}: React.PropsWithChildren) { + return ( + <div + css={css` + display: flex; + flex-direction: column; + `} + > + {children} + </div> + ); +} diff --git a/client/src/components/Design/layouts/MainLayout.tsx b/client/src/components/Design/layouts/MainLayout.tsx index 22012fde8..d7a699662 100644 --- a/client/src/components/Design/layouts/MainLayout.tsx +++ b/client/src/components/Design/layouts/MainLayout.tsx @@ -15,7 +15,7 @@ export function MainLayout({backgroundColor, children}: MainLayoutProps) { justifyContent="flexStart" flexDirection="column" padding="1rem 0 0 0" - gap="1rem" + gap="0.5rem" width="100%" height="100%" minHeight="100vh" diff --git a/client/src/components/ExpenseDetailModal/ExpenseDetailModal.tsx b/client/src/components/ExpenseDetailModal/ExpenseDetailModal.tsx new file mode 100644 index 000000000..ddc151387 --- /dev/null +++ b/client/src/components/ExpenseDetailModal/ExpenseDetailModal.tsx @@ -0,0 +1,130 @@ +// import type {BillAction} from 'types/serviceType'; + +// import validatePurchase from '@utils/validate/validatePurchase'; +// import useRequestGetSteps from '@hooks/queries/step/useRequestGetSteps'; +// import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; +// import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; + +// import usePutAndDeleteBill from '@hooks/usePutAndDeleteBill'; + +// import {BottomSheet, EditableItem, FixedButton, Flex, Text} from '@HDesign/index'; + +// type ExpenseDetailModalProps = { +// billAction: BillAction; +// isBottomSheetOpened: boolean; +// setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; +// }; + +// const ExpenseDetailModal = ({billAction, isBottomSheetOpened, setIsBottomSheetOpened}: ExpenseDetailModalProps) => { +// const { +// inputPair, +// handleInputChange, +// // handleOnBlur, +// // errorMessage, +// // errorInfo, +// canSubmit, +// onDelete, +// onSubmit: putBillAction, +// } = usePutAndDeleteBill({title: billAction.name, price: String(billAction.price), index: 0}, validatePurchase, () => +// setIsBottomSheetOpened(false), +// ); + +// const { +// memberReportListInAction, +// addAdjustedMember, +// onSubmit: putMemberReportListInAction, +// getIsSamePriceStateAndServerState, +// getOnlyOneNotAdjustedRemainMemberIndex, +// isExistAdjustedPrice, +// } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); +// const { +// inputList, +// onChange, +// canEditList, +// canSubmit: isChangedMemberReportInput, +// } = useMemberReportInput({ +// data: memberReportListInAction, +// addAdjustedMember, +// totalPrice: Number(inputPair.price), +// getIsSamePriceStateAndServerState, +// getOnlyOneNotAdjustedRemainMemberIndex, +// }); + +// const {steps} = useRequestGetSteps(); + +// const actionMemberList = steps.filter(({actions}) => +// actions.find(({actionId}) => actionId === billAction.actionId), +// )[0].members; + +// return ( +// <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> +// <form css={bottomSheetStyle} onSubmit={() => setIsBottomSheetOpened(false)}> +// <h2 css={bottomSheetHeaderStyle}> +// <Text size="bodyBold">지출 내역 상세</Text> +// </h2> +// <fieldset css={inputContainerStyle}> +// <EditableItem backgroundColor="lightGrayContainer" prefixLabelText="지출 내역 / 금액"> +// <EditableItem.Input +// placeholder="지출 내역" +// textSize="bodyBold" +// value={inputPair.title} +// onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('title', event)} +// disabled +// /> +// <Flex alignItems="center" gap="0.25rem"> +// <EditableItem.Input +// placeholder="0" +// style={{ +// textAlign: 'right', +// }} +// type="number" +// value={inputPair.price} +// onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('price', event)} +// isFixed={isExistAdjustedPrice()} +// disabled +// /> +// <Text size="caption">원</Text> +// </Flex> +// </EditableItem> + +// <EditableItem +// backgroundColor="lightGrayContainer" +// prefixLabelText="참여자" +// suffixLabelText={`총 ${actionMemberList.length}명`} +// > +// <Flex flexDirection="column" width="100%" gap="1rem"> +// {inputList.map(({name, price, isFixed}, index) => ( +// <Flex key={name} justifyContent="spaceBetween"> +// <EditableItem.Input +// value={name} +// placeholder="참여자 명" +// textSize="smallBodyBold" +// disabled +// ></EditableItem.Input> +// <Flex gap="0.25rem" alignItems="center"> +// <EditableItem.Input +// onChange={event => onChange(event, index)} +// isFixed={isFixed} +// textSize="smallBody" +// value={price} +// placeholder="0" +// type="number" +// disabled +// style={{textAlign: 'right'}} +// ></EditableItem.Input> +// <Text size="caption">원</Text> +// </Flex> +// </Flex> +// ))} +// </Flex> +// </EditableItem> +// </fieldset> +// <FixedButton type="submit" variants="tertiary"> +// 닫기 +// </FixedButton> +// </form> +// </BottomSheet> +// ); +// }; + +// export default ExpenseDetailModal; diff --git a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx b/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx deleted file mode 100644 index 93a950084..000000000 --- a/client/src/components/Modal/ExpenseDetailModal/ExpenseDetailModal.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import type {BillAction} from 'types/serviceType'; - -import validatePurchase from '@utils/validate/validatePurchase'; -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; -import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; - -import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; - -import {BottomSheet, EditableItem, FixedButton, Flex, Text} from '@HDesign/index'; - -import { - bottomSheetHeaderStyle, - bottomSheetStyle, - inputContainerStyle, -} from '../SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style'; - -type PutAndDeleteBillActionModalProps = { - billAction: BillAction; - isBottomSheetOpened: boolean; - setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; -}; - -const ExpenseDetailModal = ({ - billAction, - isBottomSheetOpened, - setIsBottomSheetOpened, -}: PutAndDeleteBillActionModalProps) => { - const { - inputPair, - handleInputChange, - // handleOnBlur, - // errorMessage, - // errorInfo, - canSubmit, - onDelete, - onSubmit: putBillAction, - } = usePutAndDeleteBillAction( - {title: billAction.name, price: String(billAction.price), index: 0}, - validatePurchase, - () => setIsBottomSheetOpened(false), - ); - - const { - memberReportListInAction, - addAdjustedMember, - onSubmit: putMemberReportListInAction, - getIsSamePriceStateAndServerState, - getOnlyOneNotAdjustedRemainMemberIndex, - isExistAdjustedPrice, - } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); - const { - inputList, - onChange, - canEditList, - canSubmit: isChangedMemberReportInput, - } = useMemberReportInput({ - data: memberReportListInAction, - addAdjustedMember, - totalPrice: Number(inputPair.price), - getIsSamePriceStateAndServerState, - getOnlyOneNotAdjustedRemainMemberIndex, - }); - - const {data: stepListData = []} = useRequestGetStepList(); - - const actionMemberList = stepListData.filter(({actions}) => - actions.find(({actionId}) => actionId === billAction.actionId), - )[0].members; - - return ( - <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> - <form css={bottomSheetStyle} onSubmit={() => setIsBottomSheetOpened(false)}> - <h2 css={bottomSheetHeaderStyle}> - <Text size="bodyBold">지출 내역 상세</Text> - </h2> - <fieldset css={inputContainerStyle}> - <EditableItem backgroundColor="lightGrayContainer" prefixLabelText="지출 내역 / 금액"> - <EditableItem.Input - placeholder="지출 내역" - textSize="bodyBold" - value={inputPair.title} - onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('title', event)} - disabled - /> - <Flex alignItems="center" gap="0.25rem"> - <EditableItem.Input - placeholder="0" - style={{ - textAlign: 'right', - }} - type="number" - value={inputPair.price} - onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('price', event)} - isFixed={isExistAdjustedPrice()} - disabled - /> - <Text size="caption">원</Text> - </Flex> - </EditableItem> - - <EditableItem - backgroundColor="lightGrayContainer" - prefixLabelText="참여자" - suffixLabelText={`총 ${actionMemberList.length}명`} - > - <Flex flexDirection="column" width="100%" gap="1rem"> - {inputList.map(({name, price, isFixed}, index) => ( - <Flex key={name} justifyContent="spaceBetween"> - <EditableItem.Input - value={name} - placeholder="참여자 명" - textSize="smallBodyBold" - disabled - ></EditableItem.Input> - <Flex gap="0.25rem" alignItems="center"> - <EditableItem.Input - onChange={event => onChange(event, index)} - isFixed={isFixed} - textSize="smallBody" - value={price} - placeholder="0" - type="number" - disabled - style={{textAlign: 'right'}} - ></EditableItem.Input> - <Text size="caption">원</Text> - </Flex> - </Flex> - ))} - </Flex> - </EditableItem> - </fieldset> - <FixedButton type="submit" variants="tertiary"> - 닫기 - </FixedButton> - </form> - </BottomSheet> - ); -}; - -export default ExpenseDetailModal; diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts deleted file mode 100644 index 4bbefdba9..000000000 --- a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.style.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {css} from '@emotion/react'; - -export const bottomSheetStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - width: '100%', - height: '100%', - padding: '0 1.5rem', -}); diff --git a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx b/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx deleted file mode 100644 index f75969277..000000000 --- a/client/src/components/Modal/MemberListInBillStep/MemberListInBillStep.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import type {MemberReport} from 'types/serviceType'; - -import {BottomSheet, FixedButton, Flex, Text} from '@HDesign/index'; - -import {bottomSheetStyle} from './MemberListInBillStep.style'; - -type MemberListInBillStepProps = { - stepName: string; - memberList: MemberReport[]; - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -}; - -const MemberListInBillStep = ({ - stepName, - memberList, - isOpenBottomSheet, - setIsOpenBottomSheet, -}: MemberListInBillStepProps) => { - const closeModal = () => setIsOpenBottomSheet(false); - - return ( - <BottomSheet isOpened={isOpenBottomSheet} onClose={closeModal}> - <div css={bottomSheetStyle}> - <Flex justifyContent="spaceBetween" alignItems="center" padding="0 0.5rem"> - <Text size="bodyBold" textColor="onTertiary">{`${stepName} 참석자`}</Text> - <Text size="bodyBold" textColor="gray">{`총 ${memberList.length}명`}</Text> - </Flex> - <Flex flexDirection="column" gap="0.5rem" padding="0 0.5rem"> - <ul> - {memberList.map(member => ( - <li key={member.name}> - <Flex padding="0.5rem 1rem" width="100%" justifyContent="spaceBetween"> - <Text size="bodyBold" textColor="onTertiary"> - {member.name} - </Text> - <Text size="body" textColor="black"> - {`${member.price.toLocaleString('ko-kr')} 원`} - </Text> - </Flex> - </li> - ))} - </ul> - </Flex> - </div> - <FixedButton variants="tertiary" onClick={closeModal}> - 닫기 - </FixedButton> - </BottomSheet> - ); -}; - -export default MemberListInBillStep; diff --git a/client/src/components/Modal/MemberListInBillStep/index.ts b/client/src/components/Modal/MemberListInBillStep/index.ts deleted file mode 100644 index 137df8c87..000000000 --- a/client/src/components/Modal/MemberListInBillStep/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as MemberListInBillStep} from './MemberListInBillStep'; diff --git a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx b/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx deleted file mode 100644 index 51e33589b..000000000 --- a/client/src/components/Modal/ModalBasedOnMemberCount/ModalBasedOnMemberCount.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import {SetAllMemberListModal, SetInitialMemberListModal, SetActionListModal} from '@components/Modal/index'; - -interface ModalBasedOnMemberCountProps { - allMemberList: string[]; - isOpenBottomSheet: boolean; - isOpenAllMemberListButton: boolean; - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; - setIsOpenAllMemberListButton: React.Dispatch<React.SetStateAction<boolean>>; -} - -const ModalBasedOnMemberCount = ({ - allMemberList, - isOpenBottomSheet, - isOpenAllMemberListButton, - setIsOpenBottomSheet, - setIsOpenAllMemberListButton, -}: ModalBasedOnMemberCountProps) => { - if (isOpenAllMemberListButton) { - return ( - <SetAllMemberListModal - allMemberList={allMemberList} - setIsOpenBottomSheet={setIsOpenBottomSheet} - isOpenBottomSheet={isOpenBottomSheet} - setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} - /> - ); - } - switch (allMemberList.length) { - case 0: - return ( - <SetInitialMemberListModal setIsOpenBottomSheet={setIsOpenBottomSheet} isOpenBottomSheet={isOpenBottomSheet} /> - ); - - default: - return <SetActionListModal setIsOpenBottomSheet={setIsOpenBottomSheet} isOpenBottomSheet={isOpenBottomSheet} />; - } -}; - -export default ModalBasedOnMemberCount; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts deleted file mode 100644 index 7fad2e001..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.style.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {css} from '@emotion/react'; - -const container = css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - height: '100%', -}); - -const inputGroup = css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - overflow: 'auto', - paddingBottom: '14rem', -}); - -const addMemberActionListModalContentStyle = { - container, - inputGroup, -}; - -export default addMemberActionListModalContentStyle; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx deleted file mode 100644 index a15681e4a..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/AddMemberActionListModalContent.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import type {MemberType} from 'types/serviceType'; - -import validateMemberName from '@utils/validate/validateMemberName'; -import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; - -import useDynamicInput from '@hooks/useDynamicInput'; - -import {FixedButton, LabelGroupInput} from '@HDesign/index'; - -import style from './AddMemberActionListModalContent.style'; -import InMember from './InMember'; -import OutMember from './OutMember'; - -interface AddMemberActionListModalContentProps { - inOutAction: MemberType; - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -} - -const AddMemberActionListModalContent = ({inOutAction, setIsOpenBottomSheet}: AddMemberActionListModalContentProps) => { - const dynamicProps = useDynamicInput(validateMemberName); - const {inputList, getFilledInputList, errorMessage, canSubmit, resetInputValue} = dynamicProps; - - const {mutate: postMemberList} = useRequestPostMemberList(); - - const handleUpdateMemberListSubmit = () => { - postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: inOutAction}); - setIsOpenBottomSheet(false); - }; - - return ( - <div css={style.container}> - <div css={style.inputGroup}> - <LabelGroupInput labelText="이름" errorText={errorMessage ?? ''}> - {inOutAction === 'IN' ? <InMember dynamicProps={dynamicProps} /> : <OutMember dynamicProps={dynamicProps} />} - </LabelGroupInput> - </div> - <FixedButton - disabled={!canSubmit} - variants={'primary'} - children={`${inputList.length - 1}명 ${inOutAction === 'OUT' ? '탈주' : '늦참'}`} - onClick={() => { - handleUpdateMemberListSubmit(); - resetInputValue(); - }} - /> - </div> - ); -}; - -export default AddMemberActionListModalContent; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx deleted file mode 100644 index 44da530fe..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/InMember.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; - -import {LabelGroupInput} from '@HDesign/index'; - -interface InMemberProps { - dynamicProps: ReturnUseDynamicInput; -} - -const InMember = ({dynamicProps}: InMemberProps) => { - const { - inputList, - inputRefList, - handleInputChange, - deleteEmptyInputElementOnBlur, - focusNextInputOnEnter, - errorIndexList, - } = dynamicProps; - return inputList.map(({value, index}) => ( - <LabelGroupInput.Element - key={index} - elementKey={`${index}`} - type="text" - value={value} - ref={el => (inputRefList.current[index] = el)} - isError={errorIndexList.includes(index)} - onChange={e => handleInputChange(index, e)} - onBlur={() => deleteEmptyInputElementOnBlur()} - onKeyDown={e => focusNextInputOnEnter(e, index)} - placeholder="이름" - autoFocus={inputList.length === 1 && index === 0} - /> - )); -}; - -export default InMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx deleted file mode 100644 index 2ed739b60..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/OutMember.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import {ReturnUseDynamicInput} from '@hooks/useDynamicInput'; -import useSearchInMemberList from '@hooks/useSearchInMemberList'; - -import {LabelGroupInput, Search} from '@HDesign/index'; - -interface OutMemberProps { - dynamicProps: ReturnUseDynamicInput; -} - -const OutMember = ({dynamicProps}: OutMemberProps) => { - const { - inputList, - inputRefList, - errorIndexList, - deleteEmptyInputElementOnBlur, - focusNextInputOnEnter, - handleInputChange, - handleChange, - } = dynamicProps; - const {currentInputIndex, filteredInMemberList, handleCurrentInputIndex, searchCurrentInMember, chooseMember} = - useSearchInMemberList(handleChange); - - const validationAndSearchOnChange = (inputIndex: number, event: React.ChangeEvent<HTMLInputElement>) => { - handleCurrentInputIndex(inputIndex); - handleInputChange(inputIndex, event); - searchCurrentInMember(event); - }; - - return inputList.map(({value, index}) => ( - <Search - key={index} - isShowTargetInput={currentInputIndex === index} - matchItems={filteredInMemberList} - onMatchItemClick={(term: string) => chooseMember(currentInputIndex, term)} - > - <LabelGroupInput.Element - elementKey={`${index}`} - type="text" - value={value} - ref={el => (inputRefList.current[index] = el)} - isError={errorIndexList.includes(index)} - onChange={e => validationAndSearchOnChange(index, e)} - onBlur={() => deleteEmptyInputElementOnBlur()} - onKeyDown={e => focusNextInputOnEnter(e, index)} - placeholder="이름" - autoFocus={inputList.length === 1 && index === 0} - /> - </Search> - )); -}; - -export default OutMember; diff --git a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts b/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts deleted file mode 100644 index 6519283f4..000000000 --- a/client/src/components/Modal/SetActionModal/AddMemberActionListModalContent/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as AddMemberActionListModalContent} from './AddMemberActionListModalContent'; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts deleted file mode 100644 index 7be2f2141..000000000 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.style.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {css} from '@emotion/react'; - -export const bottomSheetStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - width: '100%', - height: '100%', - padding: '0 1rem', -}); - -export const bottomSheetHeaderStyle = css({ - display: 'flex', - justifyContent: 'space-between', - alignContent: 'center', - - width: '100%', - padding: '0 0.5rem', -}); - -export const inputGroupStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - overflow: 'auto', - paddingBottom: '11rem', -}); diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx deleted file mode 100644 index 7d6573193..000000000 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/DeleteMemberActionModal.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import type {MemberAction, MemberType} from 'types/serviceType'; - -import useDeleteMemberAction from '@hooks/useDeleteMemberAction/useDeleteMemberAction'; -import {useToast} from '@hooks/useToast/useToast'; - -import {BottomSheet, Flex, Input, Text, IconButton, FixedButton, Icon} from '@HDesign/index'; - -import {bottomSheetHeaderStyle, bottomSheetStyle, inputGroupStyle} from './DeleteMemberActionModal.style'; - -type DeleteMemberActionModalProps = { - memberActionType: MemberType; - memberActionList: MemberAction[]; - isBottomSheetOpened: boolean; - setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; -}; - -const DeleteMemberActionModal = ({ - memberActionType, - memberActionList, - isBottomSheetOpened, - setIsBottomSheetOpened, -}: DeleteMemberActionModalProps) => { - const {showToast} = useToast(); - - const showToastAlreadyExistMemberAction = () => { - showToast({ - isClickToClose: true, - showingTime: 3000, - message: '이미 삭제된 인원입니다.', - type: 'error', - bottom: '160px', - }); - }; - - const showToastExistSameMemberFromAfterStep = (name: string) => { - showToast({ - isClickToClose: true, - showingTime: 3000, - message: `이후의 ${name}가 사라져요`, - type: 'error', - position: 'top', - top: '30px', - style: { - zIndex: 9000, - }, - }); - }; - - const {aliveActionList, deleteMemberActionList, addDeleteMemberAction} = useDeleteMemberAction({ - memberActionList, - setIsBottomSheetOpened, - showToastAlreadyExistMemberAction, - showToastExistSameMemberFromAfterStep, - }); - - return ( - <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> - <div css={bottomSheetStyle}> - <header css={bottomSheetHeaderStyle}> - <Text size="bodyBold">{memberActionType === 'IN' ? '들어온' : '나간'} 인원 수정하기</Text> - <Text size="bodyBold" textColor="gray">{`${aliveActionList.length}명`}</Text> - </header> - <ul css={inputGroupStyle}> - {aliveActionList.map(member => ( - <li key={member.actionId}> - <Flex flexDirection="row" width="100%" gap="1rem"> - <div style={{flexGrow: 1}}> - <Input disabled key={`${member.actionId}`} type="text" style={{flexGrow: 1}} value={member.name} /> - </div> - <IconButton size="medium" variants="tertiary" onClick={() => addDeleteMemberAction(member)}> - <Icon iconType="trash" iconColor="onTertiary" /> - </IconButton> - </Flex> - </li> - ))} - </ul> - <FixedButton - variants="primary" - children="수정 완료" - onClick={deleteMemberActionList} - disabled={memberActionList.length === aliveActionList.length} - /> - </div> - </BottomSheet> - ); -}; - -export default DeleteMemberActionModal; diff --git a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts b/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts deleted file mode 100644 index 2a6b52b45..000000000 --- a/client/src/components/Modal/SetActionModal/DeleteMemberActionModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as DeleteMemberActionModal} from './DeleteMemberActionModal'; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx deleted file mode 100644 index 95a72c99b..000000000 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeleteBillActionModal.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import type {BillAction} from 'types/serviceType'; - -import {useEffect} from 'react'; - -import validatePurchase from '@utils/validate/validatePurchase'; -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import useMemberReportListInAction from '@hooks/useMemberReportListInAction/useMemberReportListInAction'; -import useMemberReportInput from '@hooks/useMemberReportListInAction/useMemberReportInput'; - -import usePutAndDeleteBillAction from '@hooks/usePutAndDeleteBillAction'; - -import {BottomSheet, EditableItem, FixedButton, Flex, Text} from '@HDesign/index'; - -import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './PutAndDeltetBillActionModal.style'; - -type PutAndDeleteBillActionModalProps = { - billAction: BillAction; - isBottomSheetOpened: boolean; - setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; -}; - -const PutAndDeleteBillActionModal = ({ - billAction, - isBottomSheetOpened, - setIsBottomSheetOpened, -}: PutAndDeleteBillActionModalProps) => { - const { - inputPair, - handleInputChange, - // handleOnBlur, - // errorMessage, - // errorInfo, - canSubmit, - onDelete, - onSubmit: putBillAction, - } = usePutAndDeleteBillAction( - {title: billAction.name, price: String(billAction.price), index: 0}, - validatePurchase, - () => setIsBottomSheetOpened(false), - ); - - const { - memberReportListInAction, - addAdjustedMember, - onSubmit: putMemberReportListInAction, - getIsSamePriceStateAndServerState, - getOnlyOneNotAdjustedRemainMemberIndex, - isExistAdjustedPrice, - } = useMemberReportListInAction(billAction.actionId, Number(inputPair.price), () => setIsBottomSheetOpened(false)); - const { - inputList, - onChange, - canEditList, - canSubmit: isChangedMemberReportInput, - } = useMemberReportInput({ - data: memberReportListInAction, - addAdjustedMember, - totalPrice: Number(inputPair.price), - getIsSamePriceStateAndServerState, - getOnlyOneNotAdjustedRemainMemberIndex, - }); - - const {data: stepListData = []} = useRequestGetStepList(); - - const actionMemberList = stepListData.filter(({actions}) => - actions.find(({actionId}) => actionId === billAction.actionId), - )[0].members; - - useEffect(() => { - console.log(inputList); - }, [inputList]); - - return ( - <BottomSheet isOpened={isBottomSheetOpened} onClose={() => setIsBottomSheetOpened(false)}> - <form - css={bottomSheetStyle} - onSubmit={async event => { - event.preventDefault(); - - if (canSubmit) await putBillAction(event, inputPair, billAction.actionId); - if (isChangedMemberReportInput) putMemberReportListInAction(); - }} - > - <h2 css={bottomSheetHeaderStyle}> - <Text size="bodyBold">지출 내역 수정하기</Text> - </h2> - <fieldset css={inputContainerStyle}> - <EditableItem backgroundColor="lightGrayContainer" prefixLabelText="지출 내역 / 금액"> - <EditableItem.Input - placeholder="지출 내역" - textSize="bodyBold" - value={inputPair.title} - onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('title', event)} - /> - <Flex alignItems="center" gap="0.25rem"> - <EditableItem.Input - placeholder="0" - style={{ - textAlign: 'right', - }} - type="number" - value={inputPair.price} - onChange={(event: React.ChangeEvent<HTMLInputElement>) => handleInputChange('price', event)} - isFixed={isExistAdjustedPrice()} - /> - <Text size="caption">원</Text> - </Flex> - </EditableItem> - - <EditableItem - backgroundColor="lightGrayContainer" - prefixLabelText="참여자" - suffixLabelText={`총 ${actionMemberList.length}명`} - > - <Flex flexDirection="column" width="100%" gap="1rem"> - {inputList.map(({name, price, isFixed}, index) => ( - <Flex key={name} justifyContent="spaceBetween"> - <EditableItem.Input - value={name} - placeholder="참여자 명" - textSize="smallBodyBold" - disabled - ></EditableItem.Input> - <Flex gap="0.25rem" alignItems="center"> - <EditableItem.Input - onChange={event => onChange(event, index)} - isFixed={isFixed} - textSize="smallBody" - value={price} - placeholder="0" - type="number" - readOnly={!canEditList[index]} - style={{textAlign: 'right'}} - ></EditableItem.Input> - <Text size="caption">원</Text> - </Flex> - </Flex> - ))} - </Flex> - </EditableItem> - </fieldset> - <FixedButton - type="submit" - variants="primary" - disabled={!(canSubmit || isChangedMemberReportInput)} - onDeleteClick={() => onDelete(billAction.actionId)} - > - 수정 완료 - </FixedButton> - </form> - </BottomSheet> - ); -}; - -export default PutAndDeleteBillActionModal; diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts deleted file mode 100644 index f58f43425..000000000 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/PutAndDeltetBillActionModal.style.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {css} from '@emotion/react'; - -export const bottomSheetStyle = css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - width: '100%', - height: '100%', - padding: '0 1rem', -}); - -export const bottomSheetHeaderStyle = css({ - display: 'flex', - justifyContent: 'space-between', - alignContent: 'center', - - width: '100%', - padding: '0 0.5rem', -}); - -export const inputContainerStyle = css({ - display: 'flex', - height: '100%', - flexDirection: 'column', - gap: '1.5rem', - overflow: 'auto', - paddingBottom: '14rem', -}); diff --git a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts b/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts deleted file mode 100644 index c7cbcfcb6..000000000 --- a/client/src/components/Modal/SetActionModal/PutAndDeleteBillActionModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as PutAndDeleteBillActionModal} from './PutAndDeleteBillActionModal'; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts b/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts deleted file mode 100644 index ca6703309..000000000 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.style.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {css} from '@emotion/react'; - -export const container = css({ - display: 'flex', - flexDirection: 'column', - width: '100%', - height: '100%', - padding: '0 1.5rem', - gap: '1.5rem', -}); - -export const switchContainer = css({ - display: 'flex', - width: '100%', - justifyContent: 'space-between', -}); - -const setActionListModalStyle = {container, switchContainer}; - -export default setActionListModalStyle; diff --git a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx b/client/src/components/Modal/SetActionModal/SetActionListModal.tsx deleted file mode 100644 index 6550175e6..000000000 --- a/client/src/components/Modal/SetActionModal/SetActionListModal.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import type {InOutType} from 'types/serviceType'; - -import {useState} from 'react'; - -import {BottomSheet, Switch, Text} from '@HDesign/index'; - -import {AddMemberActionListModalContent} from './AddMemberActionListModalContent'; -import style from './SetActionListModal.style'; - -export type ActionType = '지출' | '인원'; - -interface SetActionModalContentProps { - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -} - -const SetActionListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetActionModalContentProps) => { - const [inOutAction, setInOutAction] = useState<InOutType>('탈주'); - - const handleParticipantTypeChange = (value: string) => { - setInOutAction(value as InOutType); - }; - - return ( - <BottomSheet isOpened={isOpenBottomSheet} onClose={() => setIsOpenBottomSheet(false)}> - <div css={style.container}> - <div css={style.switchContainer}> - <Text size="bodyBold" color="onTertiary"> - 인원 변동 - </Text> - <Switch values={['늦참', '탈주']} value={inOutAction} onChange={handleParticipantTypeChange} /> - </div> - - <AddMemberActionListModalContent - inOutAction={inOutAction === '탈주' ? 'OUT' : 'IN'} - setIsOpenBottomSheet={setIsOpenBottomSheet} - /> - </div> - </BottomSheet> - ); -}; - -export default SetActionListModal; diff --git a/client/src/components/Modal/SetActionModal/index.ts b/client/src/components/Modal/SetActionModal/index.ts deleted file mode 100644 index f689cb596..000000000 --- a/client/src/components/Modal/SetActionModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as SetActionListModal} from './SetActionListModal'; diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts deleted file mode 100644 index f54166c08..000000000 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.style.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {css} from '@emotion/react'; - -export const allMemberListModalStyle = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - width: '100%', - height: '100%', - }); - -export const allMemberListModalTitleStyle = () => - css({ - display: 'flex', - justifyContent: 'space-between', - width: '100%', - padding: '0 1.5rem', - }); - -export const allMemberListModalLabelGroupInputStyle = () => - css({ - display: 'flex', - flexDirection: 'column', - padding: '0 1rem', - paddingBottom: '10rem', - - overflow: 'auto', - }); - -export const InputAndDeleteButtonContainer = () => - css({ - display: 'flex', - alignItems: 'center', - width: '100%', - gap: '1rem', - }); diff --git a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx b/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx deleted file mode 100644 index 62853f912..000000000 --- a/client/src/components/Modal/SetAllMemberListModal/SetAllMemberListModal.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import validateMemberName from '@utils/validate/validateMemberName'; - -import useSetAllMemberList from '@hooks/useSetAllMemberList'; - -import {BottomSheet, Text, LabelGroupInput, FixedButton, IconButton, Icon} from '@HDesign/index'; - -import { - allMemberListModalLabelGroupInputStyle, - allMemberListModalStyle, - allMemberListModalTitleStyle, - InputAndDeleteButtonContainer, -} from './SetAllMemberListModal.style'; - -interface SetAllMemberListModalProps { - isOpenBottomSheet: boolean; - allMemberList: string[]; - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; - setIsOpenAllMemberListButton: React.Dispatch<React.SetStateAction<boolean>>; -} - -const SetAllMemberListModal = ({ - isOpenBottomSheet, - allMemberList, - setIsOpenBottomSheet, - setIsOpenAllMemberListButton, -}: SetAllMemberListModalProps) => { - const handleCloseAllMemberListModal = () => { - setIsOpenAllMemberListButton(prev => !prev); - setIsOpenBottomSheet(false); - }; - - const { - editedAllMemberList, - canSubmit, - errorMessage, - errorIndexList, - handleNameChange, - handleClickDeleteButton, - handlePutAllMemberList, - } = useSetAllMemberList({ - validateFunc: validateMemberName, - allMemberList, - handleCloseAllMemberListModal, - }); - - return ( - <BottomSheet isOpened={isOpenBottomSheet} onClose={handleCloseAllMemberListModal}> - <div css={allMemberListModalStyle}> - <div css={allMemberListModalTitleStyle}> - <Text size="bodyBold">전체 참여자 수정하기</Text> - <Text size="bodyBold" textColor="gray"> - 총 {allMemberList.length}명 - </Text> - </div> - <div css={allMemberListModalLabelGroupInputStyle}> - <LabelGroupInput labelText="이름" errorText={errorMessage}> - {editedAllMemberList.map((member, index) => ( - <div css={InputAndDeleteButtonContainer} key={index}> - <div css={{flexGrow: 1}}> - <LabelGroupInput.Element - elementKey="e" - value={member} - isError={errorIndexList.includes(index)} - onChange={e => handleNameChange(index, e)} - /> - </div> - <IconButton variants="tertiary" size="medium" onClick={() => handleClickDeleteButton(index)}> - <Icon iconType="trash" iconColor="onTertiary" /> - </IconButton> - </div> - ))} - </LabelGroupInput> - </div> - <FixedButton children="수정 완료" disabled={!canSubmit} onClick={handlePutAllMemberList} /> - </div> - </BottomSheet> - ); -}; - -export default SetAllMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts deleted file mode 100644 index ed835682c..000000000 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.style.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {css} from '@emotion/react'; - -export const setInitialMemberListModalStyle = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '1.5rem', - width: '100%', - height: '100%', - padding: '0 1.5rem', - }); - -export const setInitialMemberListModalInputGroupStyle = () => - css({ - display: 'flex', - flexDirection: 'column', - gap: '1rem', - overflow: 'auto', - paddingBottom: '11rem', - }); diff --git a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx b/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx deleted file mode 100644 index f4f2dc220..000000000 --- a/client/src/components/Modal/SetInitialMemberListModal/SetInitialMemberListModal.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import validateMemberName from '@utils/validate/validateMemberName'; -import useRequestPostMemberList from '@hooks/queries/useRequestPostMemberList'; - -import useDynamicInput from '@hooks/useDynamicInput'; - -import {Text, BottomSheet, FixedButton, LabelGroupInput} from '@HDesign/index'; - -import { - setInitialMemberListModalInputGroupStyle, - setInitialMemberListModalStyle, -} from './SetInitialMemberListModal.style'; - -interface SetInitialMemberListProps { - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -} - -const SetInitialMemberListModal = ({isOpenBottomSheet, setIsOpenBottomSheet}: SetInitialMemberListProps) => { - const { - inputList, - inputRefList, - handleInputChange, - deleteEmptyInputElementOnBlur, - getFilledInputList, - errorMessage, - canSubmit, - errorIndexList, - focusNextInputOnEnter, - } = useDynamicInput(validateMemberName); - const {mutate: postMemberList} = useRequestPostMemberList(); - - const handleSubmit = () => { - postMemberList({memberNameList: getFilledInputList().map(({value}) => value), type: 'IN'}); - setIsOpenBottomSheet(false); - }; - - return ( - <BottomSheet isOpened={isOpenBottomSheet} onClose={() => setIsOpenBottomSheet(false)}> - <div css={setInitialMemberListModalStyle}> - <Text size="bodyBold">시작 인원 추가하기</Text> - <div css={setInitialMemberListModalInputGroupStyle}> - <LabelGroupInput labelText="이름" errorText={errorMessage ?? ''}> - {inputList.map(({value, index}) => ( - <LabelGroupInput.Element - key={`${index}`} - elementKey={`${index}`} - placeholder="이름" - type="text" - value={value} - isError={errorIndexList.includes(index)} - ref={el => (inputRefList.current[index] = el)} - onChange={e => handleInputChange(index, e)} - onBlur={() => deleteEmptyInputElementOnBlur()} - onKeyDown={e => focusNextInputOnEnter(e, index)} - autoFocus={inputList.length === 1 && index === 0} - /> - ))} - </LabelGroupInput> - </div> - </div> - <FixedButton disabled={!canSubmit} variants={'primary'} onClick={handleSubmit} children={'인원 설정 완료'} /> - </BottomSheet> - ); -}; - -export default SetInitialMemberListModal; diff --git a/client/src/components/Modal/SetInitialMemberListModal/index.ts b/client/src/components/Modal/SetInitialMemberListModal/index.ts deleted file mode 100644 index 18098e4f6..000000000 --- a/client/src/components/Modal/SetInitialMemberListModal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export {default as SetInitialMemberListModal} from './SetInitialMemberListModal'; diff --git a/client/src/components/Modal/index.ts b/client/src/components/Modal/index.ts deleted file mode 100644 index 180063b03..000000000 --- a/client/src/components/Modal/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export {default as SetActionListModal} from './SetActionModal/SetActionListModal'; -export {default as SetInitialMemberListModal} from './SetInitialMemberListModal/SetInitialMemberListModal'; -export {default as SetAllMemberListModal} from './SetAllMemberListModal/SetAllMemberListModal'; -export {default as ModalBasedOnMemberCount} from './ModalBasedOnMemberCount/ModalBasedOnMemberCount'; diff --git a/client/src/components/MemberReportList/MemberReportList.tsx b/client/src/components/Reports/Reports.tsx similarity index 60% rename from client/src/components/MemberReportList/MemberReportList.tsx rename to client/src/components/Reports/Reports.tsx index bfc7cf84c..9215831d7 100644 --- a/client/src/components/MemberReportList/MemberReportList.tsx +++ b/client/src/components/Reports/Reports.tsx @@ -1,12 +1,12 @@ -import React, {useEffect, useState} from 'react'; +import React, {useState} from 'react'; -import useSearchMemberReportList from '@hooks/useSearchMemberReportList/useSearchMemberReportList'; +import {useSearchReports} from '@hooks/useSearchReports'; import {ExpenseList, Flex, Input, Text} from '@HDesign/index'; -const MemberReportList = () => { +const Reports = () => { const [name, setName] = useState(''); - const {memberReportSearchList, memberReportList} = useSearchMemberReportList({name}); + const {matchedReports, reports} = useSearchReports({name}); const changeName = ({target}: React.ChangeEvent<HTMLInputElement>) => { setName(target.value); @@ -14,10 +14,10 @@ const MemberReportList = () => { return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - {memberReportList.length > 0 ? ( + {reports.length > 0 ? ( <> <Input inputType="search" value={name} onChange={changeName} placeholder="참여자 이름" /> - {memberReportSearchList.length !== 0 && <ExpenseList expenseList={memberReportSearchList} />} + {matchedReports.length !== 0 && <ExpenseList expenseList={matchedReports} />} </> ) : ( <Flex width="100%" justifyContent="center"> @@ -30,4 +30,4 @@ const MemberReportList = () => { ); }; -export default MemberReportList; +export default Reports; diff --git a/client/src/components/StepList/BillStepItem.tsx b/client/src/components/StepList/BillStepItem.tsx deleted file mode 100644 index ca5f4ee05..000000000 --- a/client/src/components/StepList/BillStepItem.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import {Fragment, useState} from 'react'; -import {useOutletContext} from 'react-router-dom'; - -import {BillStep, MemberReport} from 'types/serviceType'; -import {PutAndDeleteBillActionModal} from '@components/Modal/SetActionModal/PutAndDeleteBillActionModal'; -import {MemberListInBillStep} from '@components/Modal/MemberListInBillStep'; -import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; -import ExpenseDetailModal from '@components/Modal/ExpenseDetailModal/ExpenseDetailModal'; - -import useSetBillInput from '@hooks/useSetBillInput'; - -import {DragHandleItem, DragHandleItemContainer, EditableItem, Flex, Text} from '@HDesign/index'; - -interface BillStepItemProps { - step: BillStep; - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; - isAddEditableItem: boolean; - setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; - isLastBillItem: boolean; - index: number; -} - -const BillStepItem: React.FC<BillStepItemProps> = ({ - step, - isOpenBottomSheet, - setIsOpenBottomSheet, - isAddEditableItem, - setIsAddEditableItem, - isLastBillItem, - index, -}) => { - const {isAdmin} = useOutletContext<EventPageContextProps>(); - const {handleBlurBillRequest, handleChangeBillInput, billInput} = useSetBillInput({setIsAddEditableItem}); - - const [clickedIndex, setClickedIndex] = useState(-1); - const [isOpenMemberListInBillStep, setIsOpenMemberListInBillStep] = useState(false); - - const totalPrice = step.actions && step.type === 'BILL' ? step.actions.reduce((acc, cur) => acc + cur.price, 0) : 0; - - const handleDragHandleItemClick = (index: number) => { - setClickedIndex(index); - setIsOpenBottomSheet(true); - }; - - const memberList: MemberReport[] = step.members.map(member => ({ - name: member, - price: totalPrice / step.members.length, - })); - - const handleTopRightTextClick = () => { - setIsOpenMemberListInBillStep(true); - }; - - return ( - <> - <DragHandleItemContainer - id={`${index}`} - topLeftText={step.stepName} - topRightText={`${step.members.length}명`} - bottomLeftText="총액" - bottomRightText={`${totalPrice.toLocaleString('ko-kr')} 원`} - backgroundColor="white" - // TODO: (@soha) 백엔드의 요청으로 인해 인원수 click시 BottomSheet가 띄워지지 않도록 주석처리 - // onTopRightTextClick={handleTopRightTextClick} - > - {step.actions && - step.type === 'BILL' && - step.actions.map((action, index) => ( - <Fragment key={action.actionId}> - <DragHandleItem - // TODO: (@todari) dnd 없으므로 false - // hasDragHandler={isAdmin} - hasDragHandler={false} - prefix={action.name} - suffix={`${action.price.toLocaleString('ko-kr')} 원`} - backgroundColor="lightGrayContainer" - onClick={() => handleDragHandleItemClick(index)} - isFixed={action.isFixed} - /> - - {isOpenBottomSheet && clickedIndex === index && isAdmin && ( - <PutAndDeleteBillActionModal - billAction={action} - isBottomSheetOpened={isOpenBottomSheet} - setIsBottomSheetOpened={setIsOpenBottomSheet} - /> - )} - {isOpenBottomSheet && clickedIndex === index && !isAdmin && ( - <ExpenseDetailModal - billAction={action} - isBottomSheetOpened={isOpenBottomSheet} - setIsBottomSheetOpened={setIsOpenBottomSheet} - /> - )} - </Fragment> - ))} - - {isAddEditableItem && isLastBillItem && ( - <EditableItem - backgroundColor="lightGrayContainer" - onBlur={handleBlurBillRequest} - onKeyDown={e => { - if (e.key === 'Enter') { - handleBlurBillRequest(); - } - }} - > - <EditableItem.Input - placeholder="지출 내역" - textSize="bodyBold" - value={billInput.title} - onChange={e => handleChangeBillInput('title', e)} - autoFocus - ></EditableItem.Input> - <Flex gap="0.25rem" alignItems="center"> - <EditableItem.Input - placeholder="0" - type="number" - value={billInput.price || ''} - onChange={e => handleChangeBillInput('price', e)} - style={{textAlign: 'right'}} - ></EditableItem.Input> - <Text size="caption">원</Text> - </Flex> - </EditableItem> - )} - </DragHandleItemContainer> - <MemberListInBillStep - stepName={step.stepName} - memberList={memberList} - isOpenBottomSheet={isOpenMemberListInBillStep} - setIsOpenBottomSheet={setIsOpenMemberListInBillStep} - /> - </> - ); -}; - -export default BillStepItem; diff --git a/client/src/components/StepList/MemberStepItem.tsx b/client/src/components/StepList/MemberStepItem.tsx deleted file mode 100644 index b0ef25de2..000000000 --- a/client/src/components/StepList/MemberStepItem.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import type {MemberStep} from 'types/serviceType'; - -import {useOutletContext} from 'react-router-dom'; - -import {DeleteMemberActionModal} from '@components/Modal/SetActionModal/DeleteMemberActionModal'; -import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; - -import {DragHandleItem} from '@HDesign/index'; - -interface MemberStepItemProps { - step: MemberStep; - isOpenBottomSheet: boolean; - setIsOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>; -} - -const MemberStepItem: React.FC<MemberStepItemProps> = ({step, isOpenBottomSheet, setIsOpenBottomSheet}) => { - const {isAdmin} = useOutletContext<EventPageContextProps>(); - - return ( - <> - <DragHandleItem - hasDragHandler={false} - backgroundColor="white" - prefix={`${step.actions.map(({name}) => name).join(', ')} ${step.type === 'IN' ? '들어옴' : '나감'}`} - onClick={() => setIsOpenBottomSheet(prev => !prev)} - /> - {isOpenBottomSheet && isAdmin && ( - <DeleteMemberActionModal - memberActionType={step.type} - memberActionList={step.actions} - isBottomSheetOpened={isOpenBottomSheet} - setIsBottomSheetOpened={setIsOpenBottomSheet} - /> - )} - </> - ); -}; - -export default MemberStepItem; diff --git a/client/src/components/StepList/Step.stories.tsx b/client/src/components/StepList/Step.stories.tsx new file mode 100644 index 000000000..076879f6b --- /dev/null +++ b/client/src/components/StepList/Step.stories.tsx @@ -0,0 +1,60 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Step from './Step'; + +const meta = { + title: 'Components/Step', + component: Step, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + step: { + description: '', + }, + }, + args: { + step: { + bills: [ + { + id: 1, + title: '커피', + price: 10000, + isFixed: false, + }, + { + id: 2, + title: '인생네컷', + price: 20000, + isFixed: false, + }, + ], + members: [ + { + id: 1, + name: '망쵸', + }, + { + id: 2, + name: '백호', + }, + ], + }, + }, +} satisfies Meta<typeof Step>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: ({...args}) => { + return ( + <div style={{width: '400px'}}> + <Step {...args} /> + </div> + ); + }, +}; diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index f6c89475b..1fec736fc 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -1,51 +1,34 @@ -import type {BillStep, MemberStep} from 'types/serviceType'; +/** @jsxImportSource @emotion/react */ +import Amount from '@components/Design/components/Amount/Amount'; +import ChipGroup from '@components/Design/components/ChipGroup/ChipGroup'; +import ListItem from '@components/Design/components/ListItem/ListItem'; +import {Step as StepType} from 'types/serviceType'; -import {useEffect, useState} from 'react'; +import {Text} from '@components/Design'; -import BillStepItem from './BillStepItem'; -import MemberStepItem from './MemberStepItem'; - -interface StepProps { - step: BillStep | MemberStep; - isAddEditableItem: boolean; - lastBillItemIndex: number; - lastItemIndex: number; - index: number; - setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; +interface Prop { + step: StepType; } -const Step = ({step, isAddEditableItem, lastBillItemIndex, lastItemIndex, setIsAddEditableItem, index}: StepProps) => { - const [isOpenBottomSheet, setIsOpenBottomSheet] = useState<boolean>(false); - const [isLastBillItem, setIsLastBillItem] = useState<boolean>(false); - - useEffect(() => { - if (index === lastBillItemIndex && lastBillItemIndex === lastItemIndex) { - // index를 사용하여 마지막 BillStep인지 확인 - setIsLastBillItem(true); - } else { - setIsLastBillItem(false); - } - }, [index, lastBillItemIndex]); - - if (step.actions && step.type === 'BILL') { - return ( - <BillStepItem - index={index} - step={step as BillStep} - isOpenBottomSheet={isOpenBottomSheet} - setIsOpenBottomSheet={setIsOpenBottomSheet} - isAddEditableItem={isAddEditableItem} - setIsAddEditableItem={setIsAddEditableItem} - isLastBillItem={isLastBillItem} - /> - ); - } else if (step.actions && (step.type === 'IN' || step.type === 'OUT')) { - return ( - <MemberStepItem step={step} isOpenBottomSheet={isOpenBottomSheet} setIsOpenBottomSheet={setIsOpenBottomSheet} /> - ); - } else { - return <></>; - } +const Step = ({step}: Prop) => { + return ( + <ListItem> + <ListItem.Row> + <ChipGroup color="gray" texts={step.members.map(member => member.name)} /> + <Text size="caption" textColor="gray"> + {step.members.length}명 + </Text> + </ListItem.Row> + {step.bills.map(bill => { + return ( + <ListItem.Row> + <Text size="bodyBold">{bill.title}</Text> + <Amount amount={bill.price} /> + </ListItem.Row> + ); + })} + </ListItem> + ); }; export default Step; diff --git a/client/src/components/StepList/StepList.tsx b/client/src/components/StepList/StepList.tsx deleted file mode 100644 index ccdf547f0..000000000 --- a/client/src/components/StepList/StepList.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import {useEffect, useMemo, useState} from 'react'; - -import {BillStep, MemberStep} from 'types/serviceType'; -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; - -import {Flex, Text} from '@HDesign/index'; - -import Step from './Step'; - -interface StepListProps { - isAddEditableItem?: boolean; - setIsAddEditableItem?: React.Dispatch<React.SetStateAction<boolean>>; -} - -const StepList = ({isAddEditableItem = false, setIsAddEditableItem = () => {}}: StepListProps) => { - const {data: stepListData} = useRequestGetStepList(); - const [stepList, setStepList] = useState<(MemberStep | BillStep)[]>([]); - const existIndexInStepList = stepList.map((step, index) => ({...step, index})); - const [hasAddedItem, setHasAddedItem] = useState(false); - const nextStepName = stepList.length > 0 ? String(stepList[stepList.length - 1].stepName).match(/.*(?=차)/) : ''; - - useEffect(() => { - if (stepListData) { - setStepList(stepListData); - } - }, [stepListData]); - - const lastBillItemIndex = useMemo(() => { - const billSteps = existIndexInStepList.filter(step => step.type === 'BILL'); - - // billSteps 배열이 비어 있지 않으면 마지막 항목의 index를 반환, 그렇지 않으면 -1을 반환 - return billSteps.length > 0 ? billSteps.slice(-1)[0].index : -1; - }, [stepList]); - - const lastItemIndex = useMemo(() => { - return existIndexInStepList.length > 0 ? existIndexInStepList.slice(-1)[0].index : -1; - }, [existIndexInStepList]); - - useEffect(() => { - if (hasAddedItem) { - setHasAddedItem(false); - - setStepList(prev => [...prev.filter(({actions}) => actions.length !== 0)]); - } - - if (isAddEditableItem && lastBillItemIndex !== lastItemIndex && !hasAddedItem) { - setStepList(prev => [ - ...prev, - { - type: 'BILL', - stepName: `${Number(nextStepName) + 1}차`, - members: [], - actions: [], - }, - ]); - setHasAddedItem(prev => !prev); - } - }, [isAddEditableItem]); - - return ( - <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - {stepList.length > 0 ? ( - stepList.map((step, index) => ( - <Step - index={index} - step={step} - lastBillItemIndex={lastBillItemIndex} - lastItemIndex={lastItemIndex} - key={`${step.stepName}${index}`} - isAddEditableItem={isAddEditableItem} - setIsAddEditableItem={setIsAddEditableItem} - /> - )) - ) : ( - <Flex width="100%" justifyContent="center"> - <Text size="body" textColor="gray" style={{paddingTop: '1rem'}}> - 지금은 지출 내역이 없어요. :( - </Text> - </Flex> - )} - </Flex> - ); -}; - -export default StepList; diff --git a/client/src/components/StepList/Steps.tsx b/client/src/components/StepList/Steps.tsx new file mode 100644 index 000000000..3146e355a --- /dev/null +++ b/client/src/components/StepList/Steps.tsx @@ -0,0 +1,27 @@ +import {Step as StepType} from 'types/serviceType'; + +import {Flex, Text} from '@HDesign/index'; + +import Step from './Step'; + +interface Props { + data: StepType[]; +} + +const Steps = ({data}: Props) => { + return ( + <Flex flexDirection="column" gap="0.5rem"> + {data.length > 0 ? ( + data.map(step => <Step step={step} />) + ) : ( + <Flex width="100%" justifyContent="center"> + <Text size="body" textColor="gray" style={{paddingTop: '1rem'}}> + 지금은 지출 내역이 없어요. :( + </Text> + </Flex> + )} + </Flex> + ); +}; + +export default Steps; diff --git a/client/src/constants/queryKeys.ts b/client/src/constants/queryKeys.ts index 17f3f4586..476c05766 100644 --- a/client/src/constants/queryKeys.ts +++ b/client/src/constants/queryKeys.ts @@ -1,10 +1,10 @@ const QUERY_KEYS = { - stepList: 'stepList', + steps: 'steps', eventName: 'eventName', - allMemberList: 'allMemberList', - currentInMember: 'currentInMember', - memberReport: 'memberReport', - memberReportInAction: 'memberReportInAction', + allMembers: 'allMembers', + currentMembers: 'currentMembers', + reports: 'reports', + billDetails: 'billDetails', }; export default QUERY_KEYS; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index 6a3634c3b..99e82b5fe 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -7,4 +7,5 @@ export const ROUTER_URLS = { eventLogin: '/event/:eventId/login', eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', + addBill: 'event/:eventId/addBill', }; diff --git a/client/src/hooks/queries/useRequestPostAuthentication.ts b/client/src/hooks/queries/auth/useRequestPostAuthentication.ts similarity index 74% rename from client/src/hooks/queries/useRequestPostAuthentication.ts rename to client/src/hooks/queries/auth/useRequestPostAuthentication.ts index e533a501b..b44cfcafc 100644 --- a/client/src/hooks/queries/useRequestPostAuthentication.ts +++ b/client/src/hooks/queries/auth/useRequestPostAuthentication.ts @@ -7,17 +7,22 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import {ROUTER_URLS} from '@constants/routerUrls'; -const useRequestPostAuthenticate = () => { +const useRequestPostAuthentication = () => { const eventId = getEventIdByUrl(); const navigate = useNavigate(); - return useMutation({ + const {mutate, ...rest} = useMutation({ mutationFn: () => requestPostAuthentication({eventId}), onError: () => { // 에러가 발생하면 로그인 페이지로 리다이렉트 navigate(`${ROUTER_URLS.event}/${eventId}/login`); }, }); + + return { + postAuthenticate: mutate, + ...rest, + }; }; -export default useRequestPostAuthenticate; +export default useRequestPostAuthentication; diff --git a/client/src/hooks/queries/useRequestPostLogin.ts b/client/src/hooks/queries/auth/useRequestPostLogin.ts similarity index 65% rename from client/src/hooks/queries/useRequestPostLogin.ts rename to client/src/hooks/queries/auth/useRequestPostLogin.ts index 21dce1791..f2f0d7c4c 100644 --- a/client/src/hooks/queries/useRequestPostLogin.ts +++ b/client/src/hooks/queries/auth/useRequestPostLogin.ts @@ -1,26 +1,24 @@ import {useMutation} from '@tanstack/react-query'; import {useNavigate} from 'react-router-dom'; -import {requestPostToken} from '@apis/request/auth'; +import {RequestPostToken, requestPostToken} from '@apis/request/auth'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import {ROUTER_URLS} from '@constants/routerUrls'; -interface PostLoginMutationProps { - password: string; -} - const useRequestPostLogin = () => { const eventId = getEventIdByUrl(); const navigate = useNavigate(); - return useMutation({ - mutationFn: ({password}: PostLoginMutationProps) => requestPostToken({eventId, password}), + const {mutate, ...rest} = useMutation({ + mutationFn: ({password}: RequestPostToken) => requestPostToken({eventId, password}), onSuccess: () => { navigate(`${ROUTER_URLS.event}/${eventId}/admin`); }, }); + + return {postLogin: mutate, ...rest}; }; export default useRequestPostLogin; diff --git a/client/src/hooks/queries/bill/useRequestDeleteBill.ts b/client/src/hooks/queries/bill/useRequestDeleteBill.ts new file mode 100644 index 000000000..68083d52b --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestDeleteBill.ts @@ -0,0 +1,29 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestDeleteBill} from '@apis/request/bill'; + +import {WithBillId} from '@apis/withId.type'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestDeleteBill = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({billId}: WithBillId) => requestDeleteBill({eventId, billId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return { + deleteBill: mutate, + ...rest, + }; +}; + +export default useRequestDeleteBill; diff --git a/client/src/hooks/queries/bill/useRequestGetBillDetails.ts b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts new file mode 100644 index 000000000..604bd7cd8 --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts @@ -0,0 +1,23 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetBillDetails} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetBillDetails = (billId: number) => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.billDetails, billId], + queryFn: () => requestGetBillDetails({eventId, billId}), + }); + + return { + reportFromServer: data?.billDetails ?? [], + ...rest, + }; +}; + +export default useRequestGetBillDetails; diff --git a/client/src/hooks/queries/bill/useRequestPostBill.ts b/client/src/hooks/queries/bill/useRequestPostBill.ts new file mode 100644 index 000000000..80e4b685c --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestPostBill.ts @@ -0,0 +1,27 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPostBill, requestPostBill} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPostBill = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({title, price, members}: RequestPostBill) => requestPostBill({eventId, title, price, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return { + postBill: mutate, + ...rest, + }; +}; + +export default useRequestPostBill; diff --git a/client/src/hooks/queries/bill/useRequestPutBill.ts b/client/src/hooks/queries/bill/useRequestPutBill.ts new file mode 100644 index 000000000..280436f76 --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestPutBill.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPutBill, requestPutBill} from '@apis/request/bill'; + +import {WithBillId} from '@apis/withId.type'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutBill = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({billId, title, price}: WithBillId<RequestPutBill>) => requestPutBill({eventId, billId, title, price}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return {pulBill: mutate, ...rest}; +}; + +export default useRequestPutBill; diff --git a/client/src/hooks/queries/bill/useRequestPutBillDetails.ts b/client/src/hooks/queries/bill/useRequestPutBillDetails.ts new file mode 100644 index 000000000..a63c9d967 --- /dev/null +++ b/client/src/hooks/queries/bill/useRequestPutBillDetails.ts @@ -0,0 +1,48 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPutBillDetails, requestPutBillDetails} from '@apis/request/bill'; + +import {WithBillId} from '@apis/withId.type'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutBillDetails = (billId: number) => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({billId, billDetails}: WithBillId<RequestPutBillDetails>) => + requestPutBillDetails({eventId, billId, billDetails}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.billDetails, billId]}); + }, + // onMutate: async (newMembers: MemberReportInAction[]) => { + // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); + + // const previousMembers = queryClient.getQueryData([QUERY_KEYS.memberReportInAction, actionId]); + + // queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], (oldData: MemberReportList) => ({ + // ...oldData, + // members: oldData.members.map((member: MemberReportInAction) => { + // const updatedMember = newMembers.find(m => m.name === member.name); + // return updatedMember ? {...member, ...updatedMember} : member; + // }), + // })); + + // return {previousMembers}; + // }, + // onError: (err, newMembers, context) => { + // if (context?.previousMembers) { + // queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], context.previousMembers); + // } + // }, + }); + + return {putBillDetails: mutate, ...rest}; +}; + +export default useRequestPutBillDetails; diff --git a/client/src/hooks/queries/event/useRequestGetEvent.ts b/client/src/hooks/queries/event/useRequestGetEvent.ts new file mode 100644 index 000000000..c85faae83 --- /dev/null +++ b/client/src/hooks/queries/event/useRequestGetEvent.ts @@ -0,0 +1,25 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetEvent} from '@apis/request/event'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetEvent = () => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.eventName], + queryFn: () => requestGetEvent({eventId}), + }); + + return { + eventName: data?.eventName ?? '', + bankName: data?.bankName, + accountName: data?.accountNumber, + ...rest, + }; +}; + +export default useRequestGetEvent; diff --git a/client/src/hooks/queries/event/useRequestPostEvent.ts b/client/src/hooks/queries/event/useRequestPostEvent.ts new file mode 100644 index 000000000..ec4c6f2b0 --- /dev/null +++ b/client/src/hooks/queries/event/useRequestPostEvent.ts @@ -0,0 +1,17 @@ +import {useMutation} from '@tanstack/react-query'; + +import {RequestPostEvent, requestPostEvent} from '@apis/request/event'; + +const useRequestPostEvent = () => { + const {mutate, ...rest} = useMutation({ + mutationFn: ({eventName, password}: RequestPostEvent) => requestPostEvent({eventName, password}), + }); + + return { + postEvent: mutate, + isPostEventPending: rest.isPending, + ...rest, + }; +}; + +export default useRequestPostEvent; diff --git a/client/src/hooks/queries/member/useRequestDeleteMember.ts b/client/src/hooks/queries/member/useRequestDeleteMember.ts new file mode 100644 index 000000000..ed3b191ba --- /dev/null +++ b/client/src/hooks/queries/member/useRequestDeleteMember.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestDeleteMember, requestDeleteMember} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestDeleteMember = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({memberId}: RequestDeleteMember) => requestDeleteMember({eventId, memberId}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMembers]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.billDetails]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return {deleteMember: mutate, ...rest}; +}; + +export default useRequestDeleteMember; diff --git a/client/src/hooks/queries/member/useRequestGetAllMembers.ts b/client/src/hooks/queries/member/useRequestGetAllMembers.ts new file mode 100644 index 000000000..0efe290b9 --- /dev/null +++ b/client/src/hooks/queries/member/useRequestGetAllMembers.ts @@ -0,0 +1,20 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetAllMembers} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetAllMembers = () => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.allMembers], + queryFn: () => requestGetAllMembers({eventId}), + }); + + return {members: data?.members ?? [], ...rest}; +}; + +export default useRequestGetAllMembers; diff --git a/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts b/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts new file mode 100644 index 000000000..06c595e3b --- /dev/null +++ b/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts @@ -0,0 +1,20 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetCurrentMembers} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetCurrentMembers = () => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.currentMembers], + queryFn: () => requestGetCurrentMembers({eventId}), + }); + + return {currentMembers: data?.members ?? [], ...rest}; +}; + +export default useRequestGetCurrentMembers; diff --git a/client/src/hooks/queries/member/useRequestPostMembers.ts b/client/src/hooks/queries/member/useRequestPostMembers.ts new file mode 100644 index 000000000..72da9f363 --- /dev/null +++ b/client/src/hooks/queries/member/useRequestPostMembers.ts @@ -0,0 +1,32 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPostMembers, requestPostMembers} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPostMembers = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({members}: RequestPostMembers) => requestPostMembers({eventId, members}), + // TODO: (@todari) : 낙관적 업데이트 적고 있었어용 + // onMutate: async ({type, memberName}) => { + // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.step]}); + // const previousStep = queryClient.getQueryData([QUERY_KEYS.step]); + // queryClient.setQueryData([QUERY_KEYS.step], (prev: (MemberStep | BillStep)[]) => prev && { + // }); + // }, + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMembers]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return {postMember: mutate, ...rest}; +}; + +export default useRequestPostMembers; diff --git a/client/src/hooks/queries/member/useRequestPutMembers.ts b/client/src/hooks/queries/member/useRequestPutMembers.ts new file mode 100644 index 000000000..656866a38 --- /dev/null +++ b/client/src/hooks/queries/member/useRequestPutMembers.ts @@ -0,0 +1,26 @@ +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {RequestPutMembers, requestPutMembers} from '@apis/request/member'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPutMembers = () => { + const eventId = getEventIdByUrl(); + const queryClient = useQueryClient(); + + const {mutate, ...rest} = useMutation({ + mutationFn: ({members}: RequestPutMembers) => requestPutMembers({eventId, members}), + onSuccess: () => { + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMembers]}); + queryClient.removeQueries({queryKey: [QUERY_KEYS.billDetails]}); + queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + }, + }); + + return {putMember: mutate, ...rest}; +}; + +export default useRequestPutMembers; diff --git a/client/src/hooks/queries/report/useRequestGetReports.ts b/client/src/hooks/queries/report/useRequestGetReports.ts new file mode 100644 index 000000000..5cb4de120 --- /dev/null +++ b/client/src/hooks/queries/report/useRequestGetReports.ts @@ -0,0 +1,22 @@ +import {useQuery} from '@tanstack/react-query'; + +import {requestGetReports} from '@apis/request/report'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestGetReports = () => { + const eventId = getEventIdByUrl(); + + const {data, ...rest} = useQuery({ + queryKey: [QUERY_KEYS.reports], + queryFn: () => requestGetReports({eventId}), + }); + + return { + reports: data?.reports ?? [], + ...rest, + }; +}; +export default useRequestGetReports; diff --git a/client/src/hooks/queries/useRequestGetStepList.ts b/client/src/hooks/queries/step/useRequestGetSteps.ts similarity index 69% rename from client/src/hooks/queries/useRequestGetStepList.ts rename to client/src/hooks/queries/step/useRequestGetSteps.ts index 7dfc1799c..312c03164 100644 --- a/client/src/hooks/queries/useRequestGetStepList.ts +++ b/client/src/hooks/queries/step/useRequestGetSteps.ts @@ -1,7 +1,7 @@ import {useQuery} from '@tanstack/react-query'; import {useEffect} from 'react'; -import {requestGetStepList} from '@apis/request/stepList'; +import {requestGetSteps} from '@apis/request/step'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; @@ -9,13 +9,13 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestGetStepList = () => { +const useRequestGetSteps = () => { const eventId = getEventIdByUrl(); const {updateTotalExpenseAmount} = useTotalExpenseAmountStore(); const queryResult = useQuery({ - queryKey: [QUERY_KEYS.stepList], - queryFn: () => requestGetStepList({eventId}), + queryKey: [QUERY_KEYS.steps], + queryFn: () => requestGetSteps({eventId}), }); useEffect(() => { @@ -24,7 +24,10 @@ const useRequestGetStepList = () => { } }, [queryResult.data, queryResult.isSuccess, updateTotalExpenseAmount]); - return queryResult; + return { + steps: queryResult.data ?? [], + ...queryResult, + }; }; -export default useRequestGetStepList; +export default useRequestGetSteps; diff --git a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts b/client/src/hooks/queries/useRequestDeleteAllMemberList.ts deleted file mode 100644 index da6fc4223..000000000 --- a/client/src/hooks/queries/useRequestDeleteAllMemberList.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestDeleteAllMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface DeleteAllMemberListMutationProps { - memberName: string; -} - -const useRequestDeleteAllMemberList = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({memberName}: DeleteAllMemberListMutationProps) => requestDeleteAllMemberList({eventId, memberName}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestDeleteAllMemberList; diff --git a/client/src/hooks/queries/useRequestDeleteBillAction.ts b/client/src/hooks/queries/useRequestDeleteBillAction.ts deleted file mode 100644 index 28be9dfd1..000000000 --- a/client/src/hooks/queries/useRequestDeleteBillAction.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestDeleteBillAction} from '@apis/request/bill'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface DeleteBillActionMutationProps { - actionId: number; -} - -const useRequestDeleteBillAction = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({actionId}: DeleteBillActionMutationProps) => requestDeleteBillAction({eventId, actionId}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestDeleteBillAction; diff --git a/client/src/hooks/queries/useRequestDeleteMemberAction.ts b/client/src/hooks/queries/useRequestDeleteMemberAction.ts deleted file mode 100644 index 08e69ac1f..000000000 --- a/client/src/hooks/queries/useRequestDeleteMemberAction.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestDeleteMemberAction} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface DeleteMemberActionMutationProps { - actionId: number; -} - -const useRequestDeleteMemberAction = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({actionId}: DeleteMemberActionMutationProps) => requestDeleteMemberAction({eventId, actionId}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - }, - }); -}; - -export default useRequestDeleteMemberAction; diff --git a/client/src/hooks/queries/useRequestGetAllMemberList.ts b/client/src/hooks/queries/useRequestGetAllMemberList.ts deleted file mode 100644 index 531285fd6..000000000 --- a/client/src/hooks/queries/useRequestGetAllMemberList.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetAllMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetAllMemberList = () => { - const eventId = getEventIdByUrl(); - - return useQuery({ - queryKey: [QUERY_KEYS.allMemberList], - queryFn: () => requestGetAllMemberList({eventId}), - }); -}; - -export default useRequestGetAllMemberList; diff --git a/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts b/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts deleted file mode 100644 index 31dc058c2..000000000 --- a/client/src/hooks/queries/useRequestGetCurrentInMemberList.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetCurrentInMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetCurrentInMemberList = () => { - const eventId = getEventIdByUrl(); - - return useQuery({ - queryKey: [QUERY_KEYS.currentInMember], - queryFn: () => requestGetCurrentInMemberList({eventId}), - }); -}; - -export default useRequestGetCurrentInMemberList; diff --git a/client/src/hooks/queries/useRequestGetEventName.ts b/client/src/hooks/queries/useRequestGetEventName.ts deleted file mode 100644 index 6ddb21858..000000000 --- a/client/src/hooks/queries/useRequestGetEventName.ts +++ /dev/null @@ -1,18 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetEventName} from '@apis/request/event'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetEventName = () => { - const eventId = getEventIdByUrl(); - - return useQuery({ - queryKey: [QUERY_KEYS.eventName], - queryFn: () => requestGetEventName({eventId}), - }); -}; - -export default useRequestGetEventName; diff --git a/client/src/hooks/queries/useRequestGetMemberReportList.ts b/client/src/hooks/queries/useRequestGetMemberReportList.ts deleted file mode 100644 index fe3372d35..000000000 --- a/client/src/hooks/queries/useRequestGetMemberReportList.ts +++ /dev/null @@ -1,17 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetMemberReportList} from '@apis/request/report'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetMemberReportList = () => { - const eventId = getEventIdByUrl(); - - return useQuery({ - queryKey: [QUERY_KEYS.memberReport], - queryFn: () => requestGetMemberReportList({eventId}), - }); -}; -export default useRequestGetMemberReportList; diff --git a/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts b/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts deleted file mode 100644 index 85b458228..000000000 --- a/client/src/hooks/queries/useRequestGetMemberReportListInAction.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {useQuery} from '@tanstack/react-query'; - -import {requestGetMemberReportListInAction} from '@apis/request/bill'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestGetMemberReportListInAction = (actionId: number) => { - const eventId = getEventIdByUrl(); - - const {data, ...queryResult} = useQuery({ - queryKey: [QUERY_KEYS.memberReportInAction, actionId], - queryFn: () => requestGetMemberReportListInAction({eventId, actionId}), - select: data => data.members, - }); - - return { - memberReportListInActionFromServer: data ?? [], - queryResult, - }; -}; - -export default useRequestGetMemberReportListInAction; diff --git a/client/src/hooks/queries/useRequestPostBillList.ts b/client/src/hooks/queries/useRequestPostBillList.ts deleted file mode 100644 index 676da9d85..000000000 --- a/client/src/hooks/queries/useRequestPostBillList.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestPostBillList} from '@apis/request/bill'; -import {Bill} from 'types/serviceType'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface PostBillActionMutationProps { - billList: Bill[]; -} - -const useRequestPostBillList = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({billList}: PostBillActionMutationProps) => requestPostBillList({eventId, billList}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestPostBillList; diff --git a/client/src/hooks/queries/useRequestPostEvent.ts b/client/src/hooks/queries/useRequestPostEvent.ts deleted file mode 100644 index 5767738ec..000000000 --- a/client/src/hooks/queries/useRequestPostEvent.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {useMutation} from '@tanstack/react-query'; - -import {requestPostNewEvent} from '@apis/request/event'; - -interface PostEventMutationProps { - eventName: string; - password: string; -} - -const usePostEvent = () => { - return useMutation({ - mutationFn: ({eventName, password}: PostEventMutationProps) => requestPostNewEvent({eventName, password}), - }); -}; - -export default usePostEvent; diff --git a/client/src/hooks/queries/useRequestPostMemberList.ts b/client/src/hooks/queries/useRequestPostMemberList.ts deleted file mode 100644 index 8ed69db08..000000000 --- a/client/src/hooks/queries/useRequestPostMemberList.ts +++ /dev/null @@ -1,37 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {MemberType} from 'types/serviceType'; -import {requestPostMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface PostMemberListMutationProps { - type: MemberType; - memberNameList: string[]; -} - -const useRequestPostMemberList = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({type, memberNameList}: PostMemberListMutationProps) => - requestPostMemberList({eventId, type, memberNameList}), - // TODO: (@todari) : 낙관적 업데이트 적고 있었어용 - // onMutate: async ({type, memberNameList}) => { - // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.stepList]}); - // const previousStepList = queryClient.getQueryData([QUERY_KEYS.stepList]); - // queryClient.setQueryData([QUERY_KEYS.stepList], (prev: (MemberStep | BillStep)[]) => prev && { - // }); - // }, - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestPostMemberList; diff --git a/client/src/hooks/queries/useRequestPutAllMemberList.ts b/client/src/hooks/queries/useRequestPutAllMemberList.ts deleted file mode 100644 index 4bd746d0c..000000000 --- a/client/src/hooks/queries/useRequestPutAllMemberList.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {MemberChange, requestPutAllMemberList} from '@apis/request/member'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface PutAllMemberListMutationProps { - members: MemberChange[]; -} - -const useRequestPutAllMemberList = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({members}: PutAllMemberListMutationProps) => requestPutAllMemberList({eventId, members}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMemberList]}); - queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestPutAllMemberList; diff --git a/client/src/hooks/queries/useRequestPutBillAction.ts b/client/src/hooks/queries/useRequestPutBillAction.ts deleted file mode 100644 index a58da8ea4..000000000 --- a/client/src/hooks/queries/useRequestPutBillAction.ts +++ /dev/null @@ -1,29 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {requestPutBillAction} from '@apis/request/bill'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -interface PutBillActionMutationProps { - actionId: number; - title: string; - price: number; -} - -const useRequestPutBillAction = () => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: ({actionId, title, price}: PutBillActionMutationProps) => - requestPutBillAction({eventId, actionId, title, price}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - }, - }); -}; - -export default useRequestPutBillAction; diff --git a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts b/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts deleted file mode 100644 index a87fa44f1..000000000 --- a/client/src/hooks/queries/useRequestPutMemberReportListInAction.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {useMutation, useQueryClient} from '@tanstack/react-query'; - -import {MemberReportList, requestPutMemberReportListInAction} from '@apis/request/bill'; -import {MemberReportInAction} from 'types/serviceType'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -import QUERY_KEYS from '@constants/queryKeys'; - -const useRequestPutMemberReportListInAction = (actionId: number) => { - const eventId = getEventIdByUrl(); - const queryClient = useQueryClient(); - - const {mutate, ...mutationProps} = useMutation({ - mutationFn: (members: MemberReportInAction[]) => requestPutMemberReportListInAction({eventId, actionId, members}), - onSuccess: () => { - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.stepList]}); - queryClient.invalidateQueries({queryKey: [QUERY_KEYS.memberReport]}); - queryClient.removeQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); - }, - onMutate: async (newMembers: MemberReportInAction[]) => { - await queryClient.cancelQueries({queryKey: [QUERY_KEYS.memberReportInAction, actionId]}); - - const previousMembers = queryClient.getQueryData([QUERY_KEYS.memberReportInAction, actionId]); - - queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], (oldData: MemberReportList) => ({ - ...oldData, - members: oldData.members.map((member: MemberReportInAction) => { - const updatedMember = newMembers.find(m => m.name === member.name); - return updatedMember ? {...member, ...updatedMember} : member; - }), - })); - - return {previousMembers}; - }, - onError: (err, newMembers, context) => { - if (context?.previousMembers) { - queryClient.setQueryData([QUERY_KEYS.memberReportInAction, actionId], context.previousMembers); - } - }, - }); - - return { - putMemberReportListInAction: mutate, - mutationProps, - }; -}; - -export default useRequestPutMemberReportListInAction; diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx b/client/src/hooks/useBillDetails/useBillDetailInput.tsx similarity index 69% rename from client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx rename to client/src/hooks/useBillDetails/useBillDetailInput.tsx index 9c9cd80d9..6b3350491 100644 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportInput.tsx +++ b/client/src/hooks/useBillDetails/useBillDetailInput.tsx @@ -1,29 +1,29 @@ -import type {MemberReportInAction} from 'types/serviceType'; +import type {BillDetail} from 'types/serviceType'; import {useEffect, useState} from 'react'; -import validateMemberReportInAction from '@utils/validate/validateMemberReportInAction'; +import validateBillDetails from '@utils/validate/validateBillDetails'; -type MemberReportInput = MemberReportInAction & { +type BillDetailInput = BillDetail & { index: number; }; -type UseMemberReportProps = { - data: MemberReportInAction[]; - addAdjustedMember: (memberReport: MemberReportInAction) => void; +type UseBillDetailInput = { + data: BillDetail[]; + addAdjustedMember: (billDetails: BillDetail) => void; getOnlyOneNotAdjustedRemainMemberIndex: () => number | null; getIsSamePriceStateAndServerState: () => boolean; totalPrice: number; }; -const useMemberReportInput = ({ +const useBillDetailInput = ({ data, addAdjustedMember, totalPrice, getOnlyOneNotAdjustedRemainMemberIndex, getIsSamePriceStateAndServerState, -}: UseMemberReportProps) => { - const [inputList, setInputList] = useState<MemberReportInput[]>(data.map((item, index) => ({...item, index}))); +}: UseBillDetailInput) => { + const [inputList, setInputList] = useState<BillDetailInput[]>(data.map((item, index) => ({...item, index}))); const [canSubmit, setCanSubmit] = useState<boolean>(false); const [canEditList, setCanEditList] = useState<boolean[]>([]); @@ -35,26 +35,27 @@ const useMemberReportInput = ({ }; const validateAndAddAdjustedMember = (price: string, index: number) => { - const {isValid} = validateMemberReportInAction(price, totalPrice); + const {isValid} = validateBillDetails(price, totalPrice); if (isValid) { const newInputList = [...inputList]; newInputList[index].price = Number(price); setInputList(newInputList); - const memberReportData: MemberReportInAction = { - name: newInputList[index].name, + const reportData: BillDetail = { + ...newInputList[index], + memberName: newInputList[index].memberName, price: newInputList[index].price, isFixed: newInputList[index].isFixed, }; - addAdjustedMember(memberReportData); + addAdjustedMember(reportData); } }; // 서버와 값이 같지 않고 input price의 상태가 모두 valid하다면 can submit true useEffect(() => { const isSamePriceState = getIsSamePriceStateAndServerState(); - const isAllValid = inputList.every(input => validateMemberReportInAction(String(input.price), totalPrice)); + const isAllValid = inputList.every(input => validateBillDetails(String(input.price), totalPrice)); setCanSubmit(!isSamePriceState && isAllValid); }, [inputList]); @@ -86,4 +87,4 @@ const useMemberReportInput = ({ }; }; -export default useMemberReportInput; +export default useBillDetailInput; diff --git a/client/src/hooks/useBillDetails/useBillDetails.ts b/client/src/hooks/useBillDetails/useBillDetails.ts new file mode 100644 index 000000000..408bd043b --- /dev/null +++ b/client/src/hooks/useBillDetails/useBillDetails.ts @@ -0,0 +1,157 @@ +import type {BillDetail} from 'types/serviceType'; + +import {useEffect, useState} from 'react'; + +import useRequestGetBillDetails from '@hooks/queries/bill/useRequestGetBillDetails'; +import useRequestPutBillDetails from '@hooks/queries/bill/useRequestPutBillDetails'; + +const useBillDetails = (billId: number, totalPrice: number, onClose: () => void) => { + const {reportFromServer, isSuccess} = useRequestGetBillDetails(billId); + const {putBillDetails} = useRequestPutBillDetails(billId); + + const [billDetails, setBillDetails] = useState<BillDetail[]>(reportFromServer); + + // isFixed를 모두 풀고 계산값으로 모두 처리하는 기능 + const reCalculatePriceByTotalPriceChange = () => { + const {divided, remainder} = calculateDividedPrice(billDetails.length, 0); + + const resetBillDetails = [...billDetails]; + resetBillDetails.forEach((member, index) => { + if (index !== resetBillDetails.length - 1) { + member.price = divided; + } else { + member.price = divided + remainder; + } + member.isFixed = false; + }); + + setBillDetails(resetBillDetails); + }; + + // 총 금액이 변동됐을 때 (서버에서 온 값과 다를 때) 재계산 실행 + useEffect(() => { + const totalPriceFromServer = reportFromServer.reduce((acc, cur) => acc + cur.price, 0); + + if (totalPriceFromServer !== totalPrice && totalPriceFromServer !== 0) { + reCalculatePriceByTotalPriceChange(); + } + }, [totalPrice, reportFromServer]); + + useEffect(() => { + if (isSuccess) { + setBillDetails(reportFromServer); + } + }, [reportFromServer, isSuccess]); + + const isExistAdjustedPrice = () => { + return billDetails.some(member => member.isFixed === true); + }; + + // 조정되지 않은 인원이 단 1명인 경우의 index + const getOnlyOneNotAdjustedRemainMemberIndex = (): number | null => { + const adjustedPriceCount = getAdjustedMemberCount(billDetails); + + if (adjustedPriceCount < billDetails.length - 1) return null; + + return billDetails.findIndex(member => member.isFixed === false); + }; + + // 조정값 멤버의 수를 구하는 함수 + const getAdjustedMemberCount = (billDetails: BillDetail[]) => { + return billDetails.filter(member => member.isFixed === true).length; + }; + + const addAdjustedMember = (memberReport: BillDetail) => { + const newBillDetails = billDetails.map(member => + member.memberName === memberReport.memberName ? {...member, price: memberReport.price, isFixed: true} : member, + ); + + calculateAnotherMemberPrice(newBillDetails); + }; + + const calculateDividedPrice = (remainMemberCount: number, totalAdjustedPrice: number) => { + return { + divided: Math.floor((totalPrice - totalAdjustedPrice) / remainMemberCount), + remainder: (totalPrice - totalAdjustedPrice) % remainMemberCount, + }; + }; + + // 계산값으로 값을 변경했을 때 isFixed를 푸는 함수 + // 100 true 33300 true 33300 false 33300 false + const setIsFixedFalseAtResetToDividedPrice = (billDetails: BillDetail[], divided: number) => { + return billDetails.map(bill => { + if (bill.isFixed === true && bill.price === divided) { + return {...bill, isFixed: false}; + } + + return bill; + }); + }; + + const calculateAnotherMemberPrice = (billDetails: BillDetail[]) => { + // 총 조정치 금액 + const totalAdjustedPrice = billDetails + .filter(memberReport => memberReport.isFixed === true) + .reduce((acc, cur) => acc + cur.price, 0); + + const remainMemberCount = billDetails.length - getAdjustedMemberCount(billDetails); + const {divided, remainder} = calculateDividedPrice(remainMemberCount, totalAdjustedPrice); + + const updatedList = billDetails.map(member => (member.isFixed === true ? member : {...member, price: divided})); + + // 나머지를 조정되지 않은 멤버 중 마지막 멤버에게 추가 + if (remainder !== 0) { + const nonAdjustedMembers = updatedList.filter(member => member.isFixed === false); + const lastNonAdjustedMemberIndex = updatedList.findIndex( + member => member.memberName === nonAdjustedMembers[nonAdjustedMembers.length - 1].memberName, + ); + + if (lastNonAdjustedMemberIndex !== -1) { + updatedList[lastNonAdjustedMemberIndex].price += remainder; + } + } + + // 조정됐지만 계산값으로 가격이 변한 경우 fixed 상태를 풀어야한다. + const result = setIsFixedFalseAtResetToDividedPrice(updatedList, divided); + setBillDetails(result); + }; + + const onSubmit = () => { + const withoutMemberName = billDetails.map(billDetail => { + const {memberName, ...rest} = billDetail; + return {...rest}; + }); + + putBillDetails({billId, billDetails: withoutMemberName}); + + onClose(); + }; + + const getIsSamePriceStateAndServerState = () => { + const serverStatePriceList = reportFromServer.map(({price}) => price); + const clientStatePriceList = billDetails.map(({price}) => price); + + let isSame = true; + + // isArrayEqual을 사용하지 않은 이유는 정렬이 영향을 받으면 안 되기 때문입니다 + for (let i = 0; i < serverStatePriceList.length; i++) { + if (serverStatePriceList[i] !== clientStatePriceList[i]) { + isSame = false; + } + } + + return isSame; + }; + + return { + billDetails, + addAdjustedMember, + isExistAdjustedPrice, + onSubmit, + getOnlyOneNotAdjustedRemainMemberIndex, + getIsSamePriceStateAndServerState, + isSuccess, + }; +}; + +export default useBillDetails; diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx deleted file mode 100644 index 7168070c9..000000000 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.test.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import {renderHook, waitFor} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; -import {act} from 'react'; - -import {BillStep, MemberAction, MemberStep} from 'types/serviceType'; -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; -import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; -import {ToastProvider} from '@hooks/useToast/ToastProvider'; - -import {HDesignProvider} from '@HDesign/index'; - -import stepListJson from '@mocks/stepList.json'; -import invalidMemberStepListJson from '@mocks/invalidMemberStepList.json'; - -import useDeleteMemberAction from './useDeleteMemberAction'; - -const stepListMockData = stepListJson as (BillStep | MemberStep)[]; -let memberActionList: MemberAction[] = []; - -// filter로는 type narrowing이 안되어 부득이하게 for 문을 사용했습니다. -for (let i = 0; i < stepListMockData.length; i++) { - const curAction = stepListMockData[i]; - if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); -} - -describe('useDeleteMemberAction', () => { - const initializeProvider = (list: MemberAction[] = memberActionList) => - renderHook( - () => { - return { - stepListResult: useRequestGetStepList(), - deleteMemberActionList: useDeleteMemberAction({ - memberActionList: list, - setIsBottomSheetOpened: () => {}, - showToastAlreadyExistMemberAction: () => {}, - showToastExistSameMemberFromAfterStep: () => {}, - }), - }; - }, - { - wrapper: ({children}) => ( - <HDesignProvider> - <ToastProvider> - <AppErrorBoundary> - <QueryClientBoundary> - <MemoryRouter>{children}</MemoryRouter> - </QueryClientBoundary> - </AppErrorBoundary> - </ToastProvider> - </HDesignProvider> - ), - }, - ); - - it('멤버를 삭제할 멤버 목록에 추가한다.', async () => { - const {result} = initializeProvider(); - - // stepList 값이 채워지길 대기합니다. - await waitFor(() => { - expect(result.current.stepListResult.data).not.toStrictEqual([]); - }); - - act(() => { - const memberAction = { - actionId: 1, - name: '망쵸', - price: null, - sequence: 1, - isFixed: false, - }; - - result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); - }); - - expect(result.current.deleteMemberActionList.aliveActionList).not.toContainEqual({ - actionId: 1, - name: '망쵸', - price: null, - sequence: 1, - }); - }); - - it('삭제할 멤버 목록에 있는 멤버들을 모두 삭제해 삭제할 멤버 목록을 비운다.', async () => { - const {result} = initializeProvider(); - - // stepList 값이 채워지길 대기합니다. - await waitFor(() => { - expect(result.current.stepListResult.data).not.toStrictEqual([]); - }); - - await act(async () => { - memberActionList.forEach(memberAction => { - result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); - }); - }); - - await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); - - await waitFor(() => { - expect(result.current.deleteMemberActionList.aliveActionList).toHaveLength(0); - }); - }); - - it('삭제 요청에서 오류가 발생했을 경우 삭제할 멤버 목록을 처음의 상태로 돌려놓는다.', async () => { - /** - * 이 테스트는 deleteMemberAction을 실행했을 때 오류가 나는 경우를 테스트하기 위해 작성되었습니다. - * 여기서 사용하는 stepList 목데이터는 999 actionId를 가진 MemberAction이 있는 데이터입니다. - * 999 actionId는 현재 모킹되어있는 msw에서 오류를 뱉도록 하는 id입니다. 이는 오류 상황을 시연하기 위한 임의 모킹입니다. - * (999가 아닌 경우는 모두 정상 응답 반환) - */ - - // 999 actionId를 가진 MemberAction이 있는 stepListJson 데이터를 사용해 MemberActions []으로 정제합니다. - const invalidMemberStepListMockData = invalidMemberStepListJson as (BillStep | MemberStep)[]; - let memberActionList: MemberAction[] = []; - - for (let i = 0; i < invalidMemberStepListMockData.length; i++) { - const curAction = invalidMemberStepListMockData[i]; - if (curAction.type !== 'BILL') curAction.actions.forEach(action => memberActionList.push(action)); - } - - // 오류 멤버가 포함된 memberAction[]을 useDeleteMemberAction의 초기값으로 주입합니다. - const {result} = initializeProvider(memberActionList); - - // stepList 값이 채워지길 대기합니다. - await waitFor(() => { - expect(result.current.stepListResult.data).not.toStrictEqual([]); - }); - - await act(async () => { - const memberAction = memberActionList[0]; // 현재 0번 참여자는 actionId가 999 이고, 999 actionId는 서버에서 에러를 뱉도록 조작된 상황입니다. - result.current.deleteMemberActionList.addDeleteMemberAction(memberAction); - }); - - await act(async () => result.current.deleteMemberActionList.deleteMemberActionList()); - - // 삭제 요청에서 오류가 발생했기 때문에 aliveActionList를 초기에 주입했던 값으로 다시 돌려놓는지 확인합니다. - expect(result.current.deleteMemberActionList.aliveActionList).toStrictEqual(memberActionList); - }); -}); diff --git a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx b/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx deleted file mode 100644 index 913087a59..000000000 --- a/client/src/hooks/useDeleteMemberAction/useDeleteMemberAction.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import type {MemberAction} from 'types/serviceType'; - -import {useState} from 'react'; - -import useRequestGetStepList from '@hooks/queries/useRequestGetStepList'; -import useRequestDeleteMemberAction from '@hooks/queries/useRequestDeleteMemberAction'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; - -type UseDeleteMemberActionProps = { - memberActionList: MemberAction[]; - setIsBottomSheetOpened: React.Dispatch<React.SetStateAction<boolean>>; - showToastAlreadyExistMemberAction: () => void; - showToastExistSameMemberFromAfterStep: (name: string) => void; -}; - -const useDeleteMemberAction = ({ - memberActionList, - setIsBottomSheetOpened, - showToastAlreadyExistMemberAction, - showToastExistSameMemberFromAfterStep, -}: UseDeleteMemberActionProps) => { - const {data: stepListData} = useRequestGetStepList(); - const stepList = stepListData ?? []; - const {mutate: deleteMemberActionMutate} = useRequestDeleteMemberAction(); - - const [deleteActionList, setDeleteActionList] = useState<MemberAction[]>([]); - - const eventId = getEventIdByUrl(); - - const deleteMemberAction = async (actionId: number) => { - deleteMemberActionMutate( - {actionId}, - { - onError: () => { - setDeleteActionList([]); - }, - }, - ); - setIsBottomSheetOpened(false); - }; - - // TODO: (@cookie: 추후에 반복문으로 delete하는 것이 아니라 한 번에 모아서 delete 처리하기 (backend에 문의)) - const deleteMemberActionList = async () => { - for (const {actionId} of deleteActionList) { - await deleteMemberAction(actionId); - } - }; - - const checkAlreadyExistMemberAction = (memberAction: MemberAction, showToast: () => void) => { - if (!memberActionList.includes(memberAction)) { - showToast(); - } - }; - - const checkExistSameMemberFromAfterStep = (memberAction: MemberAction, showToast: () => void) => { - if (isExistSameMemberFromAfterStep(memberAction)) { - showToast(); - } - }; - - const addDeleteMemberAction = (memberAction: MemberAction) => { - checkAlreadyExistMemberAction(memberAction, showToastAlreadyExistMemberAction); - checkExistSameMemberFromAfterStep(memberAction, () => showToastExistSameMemberFromAfterStep(memberAction.name)); - setDeleteActionList(prev => [...prev, memberAction]); - }; - - const isExistSameMemberFromAfterStep = (memberAction: MemberAction) => { - const memberActionList = stepList - .filter(step => step.type !== 'BILL') - .map(({actions}) => actions) - .flat(); - const currentActionIndex = memberActionList.findIndex(action => action.actionId === memberAction.actionId); - const memberActionListAfterCurrentAction = memberActionList.slice(Math.max(currentActionIndex - 1, 0)); - const memberNameList = memberActionListAfterCurrentAction.map(({name}) => name); - - return memberNameList.filter(member => member === memberAction.name).length >= 2; - }; - - const aliveActionList = memberActionList.filter( - memberAction => !deleteActionList.some(deleteAction => deleteAction.actionId === memberAction.actionId), - ); - return {aliveActionList, deleteMemberActionList, addDeleteMemberAction}; -}; - -export default useDeleteMemberAction; diff --git a/client/src/hooks/useDynamicInput.tsx b/client/src/hooks/useDynamicInput.tsx deleted file mode 100644 index 452add193..000000000 --- a/client/src/hooks/useDynamicInput.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import {useEffect, useRef} from 'react'; - -import {ValidateResult} from '@utils/validate/type'; - -import useInput from './useInput'; - -type InputValue = { - value: string; - index: number; -}; - -export type ReturnUseDynamicInput = { - inputList: InputValue[]; - inputRefList: React.MutableRefObject<(HTMLInputElement | null)[]>; - errorMessage: string | null; - canSubmit: boolean; - errorIndexList: number[]; - handleChange: (index: number, value: string) => void; - handleInputChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; - deleteEmptyInputElementOnBlur: () => void; - getFilledInputList: (list?: InputValue[]) => InputValue[]; - focusNextInputOnEnter: (e: React.KeyboardEvent<HTMLInputElement>, index: number) => void; - setInputValueTargetIndex: (index: number, value: string) => void; - resetInputValue: () => void; -}; - -const useDynamicInput = (validateFunc: (name: string) => ValidateResult): ReturnUseDynamicInput => { - const initialInputList = [{index: 0, value: ''}]; - const inputRefList = useRef<(HTMLInputElement | null)[]>([]); - - const {inputList, errorMessage, errorIndexList, canSubmit, handleChange, setInputList} = useInput({ - validateFunc, - initialInputList, - }); - - useEffect(() => { - if (inputRefList.current.length <= 0) return; - - const lastInput = inputRefList.current[inputRefList.current.length - 1]; - - if (lastInput) { - lastInput.scrollIntoView({behavior: 'smooth', block: 'center'}); - } - }, [inputList]); - - const handleInputChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { - const {value} = event.target; - - makeNewInputWhenFirstCharacterInput(index, value); - handleChange(index, value); - }; - - const makeNewInputWhenFirstCharacterInput = (index: number, value: string) => { - if (isLastInputFilled(index, value) && value.trim().length !== 0) { - // 마지막 인풋이 한 자라도 채워진다면 새로운 인풋을 생성해 간편한 다음 입력을 유도합니다. - setInputList(prevInputs => { - const updatedInputList = [...prevInputs]; - - // 새로운 인덱스를 inputs 배열 길이를 기준으로 설정 - const newIndex = updatedInputList[updatedInputList.length - 1].index + 1; - - return [...updatedInputList, {index: newIndex, value: ''}]; - }); - } - }; - - const deleteEmptyInputElementOnBlur = () => { - // 0, 1번 input이 값이 있는 상태에서 두 input의 값을 모두 x버튼으로 제거해도 input이 2개 남아있는 문제를 위해 조건문을 추가했습니다. - if (getFilledInputList().length === 0 && inputList.length > 1) { - setInputList([{index: 0, value: ''}]); - return; - } - - // *표시 조건문은 처음에 input을 클릭했다가 블러시켰을 때 filledInputList가 아예 없어 .index에 접근할 때 오류가 납니다. 이를 위한 얼리리턴을 두었습니다. - if (getFilledInputList().length === 0) return; - - if (getFilledInputList().length !== inputList.length) { - setInputList(inputList => { - const filledInputList = getFilledInputList(inputList); - - // 새 입력의 인덱스를 inputs 길이를 기준으로 설정 - const newIndex = filledInputList[filledInputList.length - 1].index + 1; - - return [...filledInputList, {index: newIndex, value: ''}]; - }); - } - }; - - const setInputValueTargetIndex = (index: number, value: string) => { - setInputList(prevInputs => { - const updatedInputList = [...prevInputs]; - const targetInput = findInputByIndex(index, updatedInputList); - - targetInput.value = value; - - return updatedInputList; - }); - }; - - const resetInputValue = () => { - setInputList(initialInputList); - }; - - const focusNextInputOnEnter = (e: React.KeyboardEvent<HTMLInputElement>, index: number) => { - if (e.nativeEvent.isComposing) return; - - if (e.key === 'Enter') { - inputRefList.current[index + 1]?.focus(); - } - }; - - const findInputByIndex = (index: number, list?: InputValue[]) => { - return (list ?? inputList).filter(input => input.index === index)[0]; - }; - - const getFilledInputList = (list?: InputValue[]) => { - return (list ?? inputList).filter(({value}) => value.trim().length !== 0); - }; - - const isLastInputFilled = (index: number, value: string) => { - const lastInputIndex = inputList[inputList.length - 1].index; - - return value !== '' && index === lastInputIndex; - }; - - return { - inputList, - inputRefList, - errorMessage, - canSubmit, - errorIndexList, - handleInputChange, - handleChange, - deleteEmptyInputElementOnBlur, - getFilledInputList, - focusNextInputOnEnter, - setInputValueTargetIndex, - resetInputValue, - }; -}; - -export default useDynamicInput; diff --git a/client/src/hooks/useEventLogin.ts b/client/src/hooks/useEventLogin.ts index e6f2cf2ec..15d9b2676 100644 --- a/client/src/hooks/useEventLogin.ts +++ b/client/src/hooks/useEventLogin.ts @@ -4,13 +4,13 @@ import validateEventPassword from '@utils/validate/validateEventPassword'; import RULE from '@constants/rule'; -import useRequestPostLogin from './queries/useRequestPostLogin'; +import useRequestPostLogin from './queries/auth/useRequestPostLogin'; const useEventLogin = () => { const [password, setPassword] = useState<string>(''); const [errorMessage, setErrorMessage] = useState<string | null>(null); const [canSubmit, setCanSubmit] = useState(false); - const {mutate: postLogin} = useRequestPostLogin(); + const {postLogin} = useRequestPostLogin(); const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx deleted file mode 100644 index 78c29ee03..000000000 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.test.tsx +++ /dev/null @@ -1,327 +0,0 @@ -import type {MemberReportInAction} from 'types/serviceType'; - -import {renderHook, waitFor, act} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; -import {QueryClient, QueryClientProvider} from '@tanstack/react-query'; - -import memberReportListInActionJson from '../../mocks/memberReportListInAction.json'; - -import useMemberReportListInAction from './useMemberReportListInAction'; - -describe('useMemberReportListInActionTest', () => { - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - retry: 0, - }, - }, - }); - - const initializeProvider = (actionId: number, totalPrice: number) => - renderHook(() => useMemberReportListInAction(actionId, totalPrice, () => {}), { - wrapper: ({children}) => ( - <QueryClientProvider client={queryClient}> - <MemoryRouter>{children}</MemoryRouter> - </QueryClientProvider> - ), - }); - - const actionId = 123; - const totalPrice = 100000; - - describe('Flow: 유저가 정상적으로 값을 불러왔을 때의 test', () => { - it('초기값을 정상적으로 불러온다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - expect(result.current.memberReportListInAction).toStrictEqual(memberReportListInActionJson); - }); - - it('망쵸의 가격을 100원으로 바꾸면 망쵸의 가격은 100원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMember: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMember); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - - expect(targetMember?.price).toBe(100); - }); - - it('망쵸의 가격을 100원으로 바꾸면 망쵸의 가격은 100원으로 설정되고 나머지 인원의 가격이 33,300원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMember: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMember); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMember?.price).toBe(100); - - const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(33300); - }); - }); - - it('망쵸의 가격을 100원 쿠키의 가격을 100원으로 바꾸면 나머지 인원의 가격이 49,900원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookie); - }); - - const anotherMemberList = result.current.memberReportListInAction.filter( - member => !(member.name === '망쵸' || member.name === '쿠키'), - ); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(49900); - }); - }); - - it('망쵸의 가격을 100원 쿠키의 가격을 100원으로 바꾸면 나머지 인원의 가격이 49,900원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookie); - }); - - const anotherMemberList = result.current.memberReportListInAction.filter( - member => !(member.name === '망쵸' || member.name === '쿠키'), - ); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(49900); - }); - }); - - it('망쵸의 가격을 100원으로 바꾸고 다시 망쵸의 가격을 10,000원으로 바꾸면 나머지 인원의 가격이 30,000원으로 설정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberMangchoAfter: MemberReportInAction = {name: '망쵸', price: 10000, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangchoAfter); - }); - - const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(30000); - }); - }); - }); - - describe('예외 & 엣지케이스', () => { - it('동일한 인원의 가격을 동일하게 바꾸면 변함없다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember({...adjustedMemberMangcho, isFixed: true}); - }); - - const anotherMemberList = result.current.memberReportListInAction.filter(member => member.name !== '망쵸'); - - expect(anotherMemberList[0].price).toBe(33300); - }); - - it('망쵸에게 300원을 주면 나머지 사람들은 33233원이고 마지막 사람은 33234원이 된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 300, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMember?.price).toBe(300); - - const anotherMemberList = result.current.memberReportListInAction.filter( - member => member.name === '이상' || member.name === '소하', - ); - - anotherMemberList.forEach(member => { - expect(member.price).toBe(33233); - }); - - const lastMember = result.current.memberReportListInAction.find(member => member.name === '쿠키'); - - expect(lastMember?.price).toBe(33234); - }); - - it('망쵸, 쿠키의 가격을 100원으로 바꾼 후 다시 쿠키의 가격을 33000원으로 바꾸면 쿠키의 isFixed는 false가 된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberCookie: MemberReportInAction = {name: '쿠키', price: 100, isFixed: false}; - const adjustedMemberCookieReset: MemberReportInAction = {name: '쿠키', price: 33300, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookie); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '쿠키'); - - expect(targetMember?.isFixed).toBe(true); - - act(() => { - result.current.addAdjustedMember(adjustedMemberCookieReset); - }); - - const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '쿠키'); - - expect(targetMemberReset?.isFixed).toBe(false); - }); - - it('망쵸의 가격을 100원으로 바꾼 후 다시 망쵸의 가격을 25000원으로 바꾸면 망쵸의 isFixed는 false가 된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberMangchoAfter: MemberReportInAction = {name: '망쵸', price: 25000, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMember?.isFixed).toBe(true); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangchoAfter); - }); - - const targetMemberReset = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMemberReset?.isFixed).toBe(false); - }); - - it('아무도 조정된 값이 없다면 조정값이 있는지 확인 결과 false다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - expect(result.current.isExistAdjustedPrice()).toBe(false); - }); - - it('망쵸의 가격을 100원으로 바꾼 후 리스트 중 조정값이 있는지 확인 결과 true다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - expect(result.current.isExistAdjustedPrice()).toBe(true); - }); - }); - - describe('지출 인원이 2명인 상황', () => { - const actionId = 1; - const totalPrice = 50000; - - // 망쵸 이상 - it('망쵸의 가격을 100원으로 수정한 경우, 이상의 가격이 49900원으로 수정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); - - expect(targetMember?.price).toBe(49900); - }); - - it('망쵸의 가격을 100원으로 수정하고 다시 200원으로 수정한 경우, 이상의 가격이 49800원으로 수정된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - const adjustedMemberMangchoOther: MemberReportInAction = {name: '망쵸', price: 200, isFixed: true}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangchoOther); - }); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '이상'); - - expect(targetMember?.price).toBe(49800); - }); - }); - - // last - describe('onSubmit 실행 시 반영 테스트', () => { - it('망쵸의 가격을 100원으로 바꾸고 저장하면 망쵸 100원이 반영된다.', async () => { - const {result} = initializeProvider(actionId, totalPrice); - const adjustedMemberMangcho: MemberReportInAction = {name: '망쵸', price: 100, isFixed: false}; - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - act(() => { - result.current.addAdjustedMember(adjustedMemberMangcho); - }); - - await waitFor(() => { - result.current.onSubmit(); - }); - - await waitFor(() => expect(result.current.queryResult.isSuccess).toBe(true)); - - const targetMember = result.current.memberReportListInAction.find(member => member.name === '망쵸'); - expect(targetMember?.price).toBe(100); - }); - }); -}); diff --git a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts b/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts deleted file mode 100644 index 0e32d740c..000000000 --- a/client/src/hooks/useMemberReportListInAction/useMemberReportListInAction.ts +++ /dev/null @@ -1,156 +0,0 @@ -import type {MemberReportInAction} from 'types/serviceType'; - -import {useEffect, useState} from 'react'; - -import useRequestGetMemberReportListInAction from '@hooks/queries/useRequestGetMemberReportListInAction'; -import useRequestPutMemberReportListInAction from '@hooks/queries/useRequestPutMemberReportListInAction'; - -const useMemberReportListInAction = (actionId: number, totalPrice: number, onClose: () => void) => { - const {memberReportListInActionFromServer, queryResult} = useRequestGetMemberReportListInAction(actionId); - const {putMemberReportListInAction} = useRequestPutMemberReportListInAction(actionId); - - const [memberReportListInAction, setMemberReportListInAction] = useState<MemberReportInAction[]>( - memberReportListInActionFromServer, - ); - - // isFixed를 모두 풀고 계산값으로 모두 처리하는 기능 - const reCalculatePriceByTotalPriceChange = () => { - const {divided, remainder} = calculateDividedPrice(memberReportListInAction.length, 0); - - const resetMemberReportList = [...memberReportListInAction]; - resetMemberReportList.forEach((member, index) => { - if (index !== resetMemberReportList.length - 1) { - member.price = divided; - } else { - member.price = divided + remainder; - } - member.isFixed = false; - }); - - setMemberReportListInAction(resetMemberReportList); - }; - - // 총 금액이 변동됐을 때 (서버에서 온 값과 다를 때) 재계산 실행 - useEffect(() => { - const totalPriceFromServer = memberReportListInActionFromServer.reduce((acc, cur) => acc + cur.price, 0); - - if (totalPriceFromServer !== totalPrice && totalPriceFromServer !== 0) { - reCalculatePriceByTotalPriceChange(); - } - }, [totalPrice, memberReportListInActionFromServer]); - - useEffect(() => { - if (queryResult.isSuccess) { - setMemberReportListInAction(memberReportListInActionFromServer); - } - }, [memberReportListInActionFromServer, queryResult.isSuccess]); - - const isExistAdjustedPrice = () => { - return memberReportListInAction.some(member => member.isFixed === true); - }; - - // 조정되지 않은 인원이 단 1명인 경우의 index - const getOnlyOneNotAdjustedRemainMemberIndex = (): number | null => { - const adjustedPriceCount = getAdjustedMemberCount(memberReportListInAction); - - if (adjustedPriceCount < memberReportListInAction.length - 1) return null; - - return memberReportListInAction.findIndex(member => member.isFixed === false); - }; - - // 조정값 멤버의 수를 구하는 함수 - const getAdjustedMemberCount = (memberReportListInAction: MemberReportInAction[]) => { - return memberReportListInAction.filter(member => member.isFixed === true).length; - }; - - const addAdjustedMember = (memberReport: MemberReportInAction) => { - const newMemberReportListInAction = memberReportListInAction.map(member => - member.name === memberReport.name ? {...member, price: memberReport.price, isFixed: true} : member, - ); - - calculateAnotherMemberPrice(newMemberReportListInAction); - }; - - const calculateDividedPrice = (remainMemberCount: number, totalAdjustedPrice: number) => { - return { - divided: Math.floor((totalPrice - totalAdjustedPrice) / remainMemberCount), - remainder: (totalPrice - totalAdjustedPrice) % remainMemberCount, - }; - }; - - // 계산값으로 값을 변경했을 때 isFixed를 푸는 함수 - // 100 true 33300 true 33300 false 33300 false - const setIsFixedFalseAtResetToDividedPrice = (memberReportListInAction: MemberReportInAction[], divided: number) => { - return memberReportListInAction.map(memberReport => { - if (memberReport.isFixed === true && memberReport.price === divided) { - return {...memberReport, isFixed: false}; - } - - return memberReport; - }); - }; - - const calculateAnotherMemberPrice = (memberReportListInAction: MemberReportInAction[]) => { - // 총 조정치 금액 - const totalAdjustedPrice = memberReportListInAction - .filter(memberReport => memberReport.isFixed === true) - .reduce((acc, cur) => acc + cur.price, 0); - - const remainMemberCount = memberReportListInAction.length - getAdjustedMemberCount(memberReportListInAction); - const {divided, remainder} = calculateDividedPrice(remainMemberCount, totalAdjustedPrice); - - const updatedList = memberReportListInAction.map(member => - member.isFixed === true ? member : {...member, price: divided}, - ); - - // 나머지를 조정되지 않은 멤버 중 마지막 멤버에게 추가 - if (remainder !== 0) { - const nonAdjustedMembers = updatedList.filter(member => member.isFixed === false); - const lastNonAdjustedMemberIndex = updatedList.findIndex( - member => member.name === nonAdjustedMembers[nonAdjustedMembers.length - 1].name, - ); - - if (lastNonAdjustedMemberIndex !== -1) { - updatedList[lastNonAdjustedMemberIndex].price += remainder; - } - } - - // 조정됐지만 계산값으로 가격이 변한 경우 fixed 상태를 풀어야한다. - const result = setIsFixedFalseAtResetToDividedPrice(updatedList, divided); - setMemberReportListInAction(result); - }; - - const onSubmit = () => { - putMemberReportListInAction(memberReportListInAction); - - onClose(); - }; - - const getIsSamePriceStateAndServerState = () => { - const serverStatePriceList = memberReportListInActionFromServer.map(({price}) => price); - const clientStatePriceList = memberReportListInAction.map(({price}) => price); - - let isSame = true; - - // isArrayEqual을 사용하지 않은 이유는 정렬이 영향을 받으면 안 되기 때문입니다 - for (let i = 0; i < serverStatePriceList.length; i++) { - if (serverStatePriceList[i] !== clientStatePriceList[i]) { - isSame = false; - } - } - - return isSame; - }; - - return { - memberReportListInAction, - addAdjustedMember, - isExistAdjustedPrice, - onSubmit, - getOnlyOneNotAdjustedRemainMemberIndex, - getIsSamePriceStateAndServerState, - queryResult, - }; -}; - -export default useMemberReportListInAction; diff --git a/client/src/hooks/usePutAndDeleteBill.ts b/client/src/hooks/usePutAndDeleteBill.ts new file mode 100644 index 000000000..60c0ea358 --- /dev/null +++ b/client/src/hooks/usePutAndDeleteBill.ts @@ -0,0 +1,115 @@ +// import type {Bill, BillInputType, InputPair} from 'types/serviceType'; + +// import {useEffect, useState} from 'react'; + +// import {ValidateResult} from '@utils/validate/type'; + +// import {ERROR_MESSAGE} from '@constants/errorMessage'; + +// import usePutBillAction from './queries/'; +// import useDeleteBillAction from './queries/useRequestDeleteBill'; + +// const usePutAndDeleteBill = ( +// initialValue: InputPair, +// validateFunc: (inputPair: Bill) => ValidateResult, +// onClose: () => void, +// ) => { +// const [inputPair, setInputPair] = useState<InputPair>(initialValue); +// const [canSubmit, setCanSubmit] = useState(false); +// const [errorInfo, setErrorInfo] = useState<Record<string, boolean>>({title: false, price: false}); +// const [errorMessage, setErrorMessage] = useState<string | null>(null); + +// const {mutateAsync: putBillAction} = usePutBillAction(); +// const {mutate: deleteBillAction} = useDeleteBillAction(); + +// // 현재 타겟의 event.target.value를 넣어주기 위해서 +// const getFieldValue = (field: BillInputType, value: string) => { +// if (field === 'title') { +// return {title: value, price: Number(inputPair.price)}; +// } else { +// return {title: inputPair.title, price: Number(value)}; +// } +// }; + +// // TODO: (@weadie) getFieldValue 를 리펙토링해야한다. + +// const handleInputChange = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { +// const {value} = event.target; + +// if (value.length > 20) return; + +// const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue(field, value)); + +// setErrorMessage(errorMessage); + +// if (isValid) { +// // valid일 경우 에러메시지 nope, setValue, submit은 value가 비지 않았을 때 true를 설정 +// setInputPair(prevInputPair => { +// return { +// ...prevInputPair, +// [field]: value, +// }; +// }); +// setCanSubmit(value.length !== 0); +// } else { +// const {isValid: isValidName} = validateFunc(getFieldValue('title', inputPair.title)); +// const {isValid: isValidPrice} = validateFunc(getFieldValue('price', inputPair.price)); + +// setCanSubmit(isValidName && isValidPrice); +// // valid하지 않으면 event.target.value 덮어쓰기 +// event.target.value = inputPair[field]; +// } + +// if (field === 'title') { +// // 현재 field가 title일 때는 title의 errorInfo만 반영해줌 (blur에서도 errorInfo를 조작하기 때문) +// setErrorInfo(prev => ({title: errorInfo?.title ?? false, price: prev.price})); +// } else { +// setErrorInfo(prev => ({title: prev.title, price: errorInfo?.price ?? false})); +// } +// }; + +// const handleOnBlur = () => { +// const {isValid, errorMessage, errorInfo} = validateFunc({title: inputPair.title, price: Number(inputPair.price)}); + +// // blur시 값이 비었을 때 error state 반영 +// if (inputPair.price.length === 0 || inputPair.title.length === 0) { +// setErrorMessage(ERROR_MESSAGE.preventEmpty); +// setErrorInfo({title: inputPair.title.length === 0, price: inputPair.price.length === 0}); +// setCanSubmit(false); +// return; +// } + +// // 이외 blur시에 추가로 검증함 +// setErrorMessage(errorMessage); +// setCanSubmit(isValid); +// setErrorInfo(errorInfo ?? {title: false, price: false}); +// }; + +// const onSubmit = async (event: React.FormEvent<HTMLFormElement>, inputPair: InputPair, actionId: number) => { +// event.preventDefault(); + +// const {title, price} = inputPair; + +// await putBillAction({actionId, title, price: Number(price)}); + +// onClose(); +// }; + +// const onDelete = async (actionId: number) => { +// deleteBillAction({actionId}); +// onClose(); +// }; + +// return { +// inputPair, +// handleInputChange, +// handleOnBlur, +// onSubmit, +// onDelete, +// canSubmit, +// errorMessage, +// errorInfo, +// }; +// }; + +// export default usePutAndDeleteBill; diff --git a/client/src/hooks/usePutAndDeleteBillAction.ts b/client/src/hooks/usePutAndDeleteBillAction.ts deleted file mode 100644 index 9126bf905..000000000 --- a/client/src/hooks/usePutAndDeleteBillAction.ts +++ /dev/null @@ -1,115 +0,0 @@ -import type {Bill, BillInputType, InputPair} from 'types/serviceType'; - -import {useEffect, useState} from 'react'; - -import {ValidateResult} from '@utils/validate/type'; - -import {ERROR_MESSAGE} from '@constants/errorMessage'; - -import usePutBillAction from './queries/useRequestPutBillAction'; -import useDeleteBillAction from './queries/useRequestDeleteBillAction'; - -const usePutAndDeleteBillAction = ( - initialValue: InputPair, - validateFunc: (inputPair: Bill) => ValidateResult, - onClose: () => void, -) => { - const [inputPair, setInputPair] = useState<InputPair>(initialValue); - const [canSubmit, setCanSubmit] = useState(false); - const [errorInfo, setErrorInfo] = useState<Record<string, boolean>>({title: false, price: false}); - const [errorMessage, setErrorMessage] = useState<string | null>(null); - - const {mutateAsync: putBillAction} = usePutBillAction(); - const {mutate: deleteBillAction} = useDeleteBillAction(); - - // 현재 타겟의 event.target.value를 넣어주기 위해서 - const getFieldValue = (field: BillInputType, value: string) => { - if (field === 'title') { - return {title: value, price: Number(inputPair.price)}; - } else { - return {title: inputPair.title, price: Number(value)}; - } - }; - - // TODO: (@weadie) getFieldValue 를 리펙토링해야한다. - - const handleInputChange = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { - const {value} = event.target; - - if (value.length > 20) return; - - const {isValid, errorMessage, errorInfo} = validateFunc(getFieldValue(field, value)); - - setErrorMessage(errorMessage); - - if (isValid) { - // valid일 경우 에러메시지 nope, setValue, submit은 value가 비지 않았을 때 true를 설정 - setInputPair(prevInputPair => { - return { - ...prevInputPair, - [field]: value, - }; - }); - setCanSubmit(value.length !== 0); - } else { - const {isValid: isValidName} = validateFunc(getFieldValue('title', inputPair.title)); - const {isValid: isValidPrice} = validateFunc(getFieldValue('price', inputPair.price)); - - setCanSubmit(isValidName && isValidPrice); - // valid하지 않으면 event.target.value 덮어쓰기 - event.target.value = inputPair[field]; - } - - if (field === 'title') { - // 현재 field가 title일 때는 title의 errorInfo만 반영해줌 (blur에서도 errorInfo를 조작하기 때문) - setErrorInfo(prev => ({title: errorInfo?.title ?? false, price: prev.price})); - } else { - setErrorInfo(prev => ({title: prev.title, price: errorInfo?.price ?? false})); - } - }; - - const handleOnBlur = () => { - const {isValid, errorMessage, errorInfo} = validateFunc({title: inputPair.title, price: Number(inputPair.price)}); - - // blur시 값이 비었을 때 error state 반영 - if (inputPair.price.length === 0 || inputPair.title.length === 0) { - setErrorMessage(ERROR_MESSAGE.preventEmpty); - setErrorInfo({title: inputPair.title.length === 0, price: inputPair.price.length === 0}); - setCanSubmit(false); - return; - } - - // 이외 blur시에 추가로 검증함 - setErrorMessage(errorMessage); - setCanSubmit(isValid); - setErrorInfo(errorInfo ?? {title: false, price: false}); - }; - - const onSubmit = async (event: React.FormEvent<HTMLFormElement>, inputPair: InputPair, actionId: number) => { - event.preventDefault(); - - const {title, price} = inputPair; - - await putBillAction({actionId, title, price: Number(price)}); - - onClose(); - }; - - const onDelete = async (actionId: number) => { - deleteBillAction({actionId}); - onClose(); - }; - - return { - inputPair, - handleInputChange, - handleOnBlur, - onSubmit, - onDelete, - canSubmit, - errorMessage, - errorInfo, - }; -}; - -export default usePutAndDeleteBillAction; diff --git a/client/src/hooks/useSearchInMemberList.ts b/client/src/hooks/useSearchInMemberList.ts deleted file mode 100644 index 09f227b8e..000000000 --- a/client/src/hooks/useSearchInMemberList.ts +++ /dev/null @@ -1,54 +0,0 @@ -import {useState} from 'react'; - -import useRequestGetCurrentInMemberList from './queries/useRequestGetCurrentInMemberList'; - -export type ReturnUseSearchInMemberList = { - currentInputIndex: number; - handleCurrentInputIndex: (inputIndex: number) => void; - filteredInMemberList: string[]; - searchCurrentInMember: (event: React.ChangeEvent<HTMLInputElement>) => void; - chooseMember: (inputIndex: number, name: string) => void; -}; - -const useSearchInMemberList = (handleChange: (index: number, value: string) => void): ReturnUseSearchInMemberList => { - const [currentInputIndex, setCurrentInputIndex] = useState(-1); - - // 서버에서 가져온 전체 리스트 - const {data} = useRequestGetCurrentInMemberList(); - const currentInMemberList = data?.memberNames ?? []; - - // 검색된 리스트 (따로 둔 이유는 검색 후 클릭했을 때 리스트를 비워주어야하기 때문) - const [filteredInMemberList, setFilteredInMemberList] = useState<Array<string>>([]); - - const filterMatchItems = (keyword: string) => { - if (keyword.trim() === '') return []; - - return currentInMemberList - .filter(member => member.toLocaleLowerCase().indexOf(keyword.toLocaleLowerCase()) > -1) - .slice(0, 3); - }; - - const chooseMember = (inputIndex: number, name: string) => { - setFilteredInMemberList([]); - handleChange(inputIndex, name); - }; - - const searchCurrentInMember = (event: React.ChangeEvent<HTMLInputElement>) => { - const {value} = event.target; - setFilteredInMemberList(filterMatchItems(value)); - }; - - const handleCurrentInputIndex = (inputIndex: number) => { - setCurrentInputIndex(inputIndex); - }; - - return { - currentInputIndex, - handleCurrentInputIndex, - filteredInMemberList, - searchCurrentInMember, - chooseMember, - }; -}; - -export default useSearchInMemberList; diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx deleted file mode 100644 index 90782cbdf..000000000 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.test.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import {renderHook, waitFor} from '@testing-library/react'; -import {MemoryRouter} from 'react-router-dom'; - -import AppErrorBoundary from '@components/AppErrorBoundary/ErrorCatcher'; -import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; -import {ToastProvider} from '@hooks/useToast/ToastProvider'; - -import reportListJson from '../../mocks/reportList.json'; - -import useSearchMemberReportList from './useSearchMemberReportList'; - -describe('useSearchMemberReportList', () => { - const initializeProvider = (name: string) => - renderHook(() => useSearchMemberReportList({name}), { - wrapper: ({children}) => ( - <ToastProvider> - <AppErrorBoundary> - <QueryClientBoundary> - <MemoryRouter>{children}</MemoryRouter> - </QueryClientBoundary> - </AppErrorBoundary> - </ToastProvider> - ), - }); - - it('빈 값을 검색한다면 검색 목록은 비어있다.', async () => { - const {result} = initializeProvider(''); - - await waitFor(() => expect(result.current.memberReportSearchList).toStrictEqual(reportListJson)); - }); - - it('검색어의 일부와 일치하는 이름이 있다면 해당 이름을 목록에 반환한다.', async () => { - const keyword = '소'; - const {result} = initializeProvider(keyword); - const expectedMemberReportSearchList = reportListJson.filter(memberReport => memberReport.name.includes(keyword)); - - await waitFor(() => { - expect(result.current.memberReportSearchList).toStrictEqual(expectedMemberReportSearchList); - }); - }); -}); diff --git a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx b/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx deleted file mode 100644 index 58608062b..000000000 --- a/client/src/hooks/useSearchMemberReportList/useSearchMemberReportList.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import useRequestGetMemberReportList from '@hooks/queries/useRequestGetMemberReportList'; - -type UseSearchMemberReportListParams = { - name: string; -}; - -const useSearchMemberReportList = ({name}: UseSearchMemberReportListParams) => { - const {data} = useRequestGetMemberReportList(); - const memberReportList = data ?? []; - - return { - memberReportSearchList: memberReportList.filter(memberReport => memberReport.name.includes(name)), - memberReportList, - }; -}; - -export default useSearchMemberReportList; diff --git a/client/src/hooks/useSearchReports/index.ts b/client/src/hooks/useSearchReports/index.ts new file mode 100644 index 000000000..619af5493 --- /dev/null +++ b/client/src/hooks/useSearchReports/index.ts @@ -0,0 +1 @@ +export {default as useSearchReports} from './useSearchReports'; diff --git a/client/src/hooks/useSearchReports/useSearchReports.tsx b/client/src/hooks/useSearchReports/useSearchReports.tsx new file mode 100644 index 000000000..3387c2303 --- /dev/null +++ b/client/src/hooks/useSearchReports/useSearchReports.tsx @@ -0,0 +1,16 @@ +import useRequestGetReports from '@hooks/queries/report/useRequestGetReports'; + +type UseSearchReportsParams = { + name: string; +}; + +const useSearchReports = ({name}: UseSearchReportsParams) => { + const {reports} = useRequestGetReports(); + + return { + matchedReports: reports.filter(memberReport => memberReport.name.includes(name)), + reports, + }; +}; + +export default useSearchReports; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx index 02241d3e3..bf5580dd9 100644 --- a/client/src/hooks/useSetAllMemberList.tsx +++ b/client/src/hooks/useSetAllMemberList.tsx @@ -1,100 +1,100 @@ -import {useEffect, useState} from 'react'; - -import {ValidateResult} from '@utils/validate/type'; -import {MemberChange} from '@apis/request/member'; - -import isArraysEqual from '@utils/isArraysEqual'; - -import useDeleteAllMemberList from './queries/useRequestDeleteAllMemberList'; -import usePutAllMemberList from './queries/useRequestPutAllMemberList'; -import useInput from './useInput'; - -interface UseSetAllMemberListProps { - validateFunc: (name: string) => ValidateResult; - allMemberList: string[]; - handleCloseAllMemberListModal: () => void; -} - -interface UseSetAllMemberListReturns { - editedAllMemberList: string[]; - canSubmit: boolean; - errorMessage: string; - errorIndexList: number[]; - handleNameChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; - handleClickDeleteButton: (index: number) => Promise<void>; - handlePutAllMemberList: () => Promise<void>; -} - -const useSetAllMemberList = ({ - validateFunc, - allMemberList, - handleCloseAllMemberListModal, -}: UseSetAllMemberListProps): UseSetAllMemberListReturns => { - const initialInputList = allMemberList.map((name, index) => ({index, value: name})); - const { - inputList, - errorMessage, - errorIndexList, - canSubmit, - handleChange, - setInputList: setEditedAllMemberList, - setCanSubmit, - } = useInput({validateFunc, initialInputList}); - - const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); - const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); - - const {mutateAsync: deleteAllMemberList} = useDeleteAllMemberList(); - const {mutate: putAllMemberList} = usePutAllMemberList(); - - const editedAllMemberList = inputList.map(input => input.value); - - useEffect(() => { - setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); - }, [editedAllMemberList]); - - const handleNameChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { - const {value} = event.target; - - handleChange(index, value); - }; - - const handleClickDeleteButton = async (index: number) => { - const memberToDelete = editedAllMemberList[index]; - - setDeleteMemberList(prev => [...prev, memberToDelete]); - setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); - }; - - const handlePutAllMemberList = async () => { - // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) - if (deleteMemberList.length > 0) { - for (const deleteMember of deleteMemberList) { - await deleteAllMemberList({memberName: deleteMember}); - } - } - - const editedMemberName: MemberChange[] = deleteInOriginal - .map((originalName, index) => { - if (editedAllMemberList[index] !== originalName) { - return {before: originalName, after: editedAllMemberList[index]}; - } - return null; // 조건에 맞지 않으면 null을 반환 - }) - .filter(item => item !== null); // null인 항목을 필터링하여 제거 - if (!isArraysEqual(editedAllMemberList, deleteInOriginal)) putAllMemberList({members: editedMemberName}); - handleCloseAllMemberListModal(); - }; - - return { - editedAllMemberList, - canSubmit, - errorMessage, - errorIndexList, - handleNameChange, - handleClickDeleteButton, - handlePutAllMemberList, - }; -}; -export default useSetAllMemberList; +// import {useEffect, useState} from 'react'; + +// import {ValidateResult} from '@utils/validate/type'; +// import {MemberChange} from '@apis/request/member'; + +// import isArraysEqual from '@utils/isArraysEqual'; + +// import useDeleteAllMemberList from './queries/useRequestDeleteMember'; +// import usePutAllMemberList from './queries/useRequestPutMember'; +// import useInput from './useInput'; + +// interface UseSetAllMemberListProps { +// validateFunc: (name: string) => ValidateResult; +// allMemberList: string[]; +// handleCloseAllMemberListModal: () => void; +// } + +// interface UseSetAllMemberListReturns { +// editedAllMemberList: string[]; +// canSubmit: boolean; +// errorMessage: string; +// errorIndexList: number[]; +// handleNameChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; +// handleClickDeleteButton: (index: number) => Promise<void>; +// handlePutAllMemberList: () => Promise<void>; +// } + +// const useSetAllMemberList = ({ +// validateFunc, +// allMemberList, +// handleCloseAllMemberListModal, +// }: UseSetAllMemberListProps): UseSetAllMemberListReturns => { +// const initialInputList = allMemberList.map((name, index) => ({index, value: name})); +// const { +// inputList, +// errorMessage, +// errorIndexList, +// canSubmit, +// handleChange, +// setInputList: setEditedAllMemberList, +// setCanSubmit, +// } = useInput({validateFunc, initialInputList}); + +// const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); +// const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); + +// const {mutateAsync: deleteAllMemberList} = useDeleteAllMemberList(); +// const {mutate: putAllMemberList} = usePutAllMemberList(); + +// const editedAllMemberList = inputList.map(input => input.value); + +// useEffect(() => { +// setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); +// }, [editedAllMemberList]); + +// const handleNameChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { +// const {value} = event.target; + +// handleChange(index, value); +// }; + +// const handleClickDeleteButton = async (index: number) => { +// const memberToDelete = editedAllMemberList[index]; + +// setDeleteMemberList(prev => [...prev, memberToDelete]); +// setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); +// setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); +// }; + +// const handlePutAllMemberList = async () => { +// // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) +// if (deleteMemberList.length > 0) { +// for (const deleteMember of deleteMemberList) { +// await deleteAllMemberList({memberName: deleteMember}); +// } +// } + +// const editedMemberName: MemberChange[] = deleteInOriginal +// .map((originalName, index) => { +// if (editedAllMemberList[index] !== originalName) { +// return {before: originalName, after: editedAllMemberList[index]}; +// } +// return null; // 조건에 맞지 않으면 null을 반환 +// }) +// .filter(item => item !== null); // null인 항목을 필터링하여 제거 +// if (!isArraysEqual(editedAllMemberList, deleteInOriginal)) putAllMemberList({members: editedMemberName}); +// handleCloseAllMemberListModal(); +// }; + +// return { +// editedAllMemberList, +// canSubmit, +// errorMessage, +// errorIndexList, +// handleNameChange, +// handleClickDeleteButton, +// handlePutAllMemberList, +// }; +// }; +// export default useSetAllMemberList; diff --git a/client/src/hooks/useSetBillInput.ts b/client/src/hooks/useSetBillInput.ts deleted file mode 100644 index 4f534791d..000000000 --- a/client/src/hooks/useSetBillInput.ts +++ /dev/null @@ -1,70 +0,0 @@ -import {useState} from 'react'; - -import validatePurchase from '@utils/validate/validatePurchase'; -import {Bill, BillInputType} from 'types/serviceType'; - -import useRequestPostBillList from './queries/useRequestPostBillList'; - -interface UseSetBillInputProps { - setIsAddEditableItem: React.Dispatch<React.SetStateAction<boolean>>; -} - -interface UseSetBillInputReturns { - billInput: Bill; - handleChangeBillInput: (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => void; - handleBlurBillRequest: () => void; -} - -const useSetBillInput = ({setIsAddEditableItem}: UseSetBillInputProps): UseSetBillInputReturns => { - const initialInput = {title: '', price: 0}; - const [billInput, setBillInput] = useState<Bill>(initialInput); - - const {mutate: postBillList} = useRequestPostBillList(); - - const handleChangeBillInput = (field: BillInputType, event: React.ChangeEvent<HTMLInputElement>) => { - const {value} = event.target; - - if (value.length > 20) return; - - const {isValid} = validatePurchase({ - ...billInput, - [field]: value, - }); - - if (isValid) { - setBillInput(prev => ({ - ...prev, - [field]: value, - })); - } - }; - - const handleBlurBillRequest = () => { - const isEmptyTitle = billInput.title.trim().length; - const isEmptyPrice = Number(billInput.price); - - // 두 input의 값이 모두 채워졌을 때 api 요청 - // api 요청을 하면 Input을 띄우지 않음 - if (isEmptyTitle && isEmptyPrice) { - postBillList( - {billList: [billInput]}, - { - onSuccess: () => { - setBillInput(initialInput); - setIsAddEditableItem(false); - }, - }, - ); - } else if (!isEmptyTitle && !isEmptyPrice) { - setIsAddEditableItem(false); - } - }; - - return { - billInput, - handleBlurBillRequest, - handleChangeBillInput, - }; -}; - -export default useSetBillInput; diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts index 17079f3a9..849f6f5f2 100644 --- a/client/src/hooks/useSetEventPasswordPage.ts +++ b/client/src/hooks/useSetEventPasswordPage.ts @@ -6,7 +6,7 @@ import validateEventPassword from '@utils/validate/validateEventPassword'; import {ROUTER_URLS} from '@constants/routerUrls'; import RULE from '@constants/rule'; -import usePostEvent from './queries/useRequestPostEvent'; +import useRequestPostEvent from './queries/event/useRequestPostEvent'; const useSetEventPasswordPage = () => { const [eventName, setEventName] = useState(''); @@ -15,7 +15,7 @@ const useSetEventPasswordPage = () => { const [canSubmit, setCanSubmit] = useState(false); const navigate = useNavigate(); const location = useLocation(); - const {mutate: postEvent, isPending: isPostEventPending} = usePostEvent(); + const {postEvent, isPostEventPending} = useRequestPostEvent(); useEffect(() => { if (!location.state) { @@ -28,6 +28,10 @@ const useSetEventPasswordPage = () => { const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); + onSuccess(); + }; + + const onSuccess = () => { postEvent( {eventName, password: String(password).padStart(4, '0')}, { @@ -55,6 +59,6 @@ const useSetEventPasswordPage = () => { } }; - return {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending}; + return {submitPassword, errorMessage, password, handleChange, onSuccess, canSubmit, isPostEventPending}; }; export default useSetEventPasswordPage; diff --git a/client/src/index.tsx b/client/src/index.tsx index 17f98655f..cb3fcb955 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -5,11 +5,6 @@ import * as Sentry from '@sentry/react'; import router from './router'; -// async function enableMocking() { -// const {worker} = await import('./mocks/browser'); -// return worker.start(); -// } - Sentry.init({ dsn: 'https://81685591a3234c689be8c48959b04c88@o4507739935997952.ingest.us.sentry.io/4507739943272448', integrations: [Sentry.browserTracingIntegration(), Sentry.replayIntegration()], @@ -23,6 +18,11 @@ Sentry.init({ }); // MSW 모킹을 사용하려면 아래 주석을 해제하고 save해주세요. +// async function enableMocking() { +// const {worker} = await import('./mocks/browser'); +// return worker.start(); +// } + // enableMocking().then(() => { ReactDOM.createRoot(document.getElementById('root')!).render( <React.StrictMode> diff --git a/client/src/mocks/handlers.ts b/client/src/mocks/handlers.ts index 4189b2d66..d4347bc5b 100644 --- a/client/src/mocks/handlers.ts +++ b/client/src/mocks/handlers.ts @@ -1,15 +1,15 @@ import {authHandler} from './handlers/authHandlers'; import {eventHandler} from './handlers/eventHandlers'; import {reportHandlers} from './handlers/reportHandlers'; -import {stepListHandler} from './handlers/stepListHandler'; import {testHandler} from './handlers/testHandlers'; -import {memberReportInActionHandler} from './handlers/memberReportInActionHandlers'; +import {billHandler} from './handlers/billHandler'; +import {memberHandler} from './handlers/memberHandler'; export const handlers = [ ...authHandler, ...eventHandler, + ...billHandler, + ...memberHandler, ...testHandler, - ...stepListHandler, ...reportHandlers, - ...memberReportInActionHandler, ]; diff --git a/client/src/mocks/handlers/authHandlers.ts b/client/src/mocks/handlers/authHandlers.ts index 31532eea7..00000b1e8 100644 --- a/client/src/mocks/handlers/authHandlers.ts +++ b/client/src/mocks/handlers/authHandlers.ts @@ -1,100 +1,56 @@ -import {HttpResponse, http} from 'msw'; +import {http, HttpResponse} from 'msw'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {PASSWORD_LENGTH} from '@constants/password'; -import { - EXPIRED_TOKEN_FOR_TEST, - FORBIDDEN_TOKEN_FOR_TEST, - VALID_PASSWORD_FOR_TEST, - VALID_TOKEN_FOR_TEST, -} from '@mocks/validValueForTest'; - -type PostLoginParams = { - eventId: string; -}; - -type PostLoginRequestBody = { - password: string; -}; +import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; export const authHandler = [ - http.post(`${TEMP_PREFIX}/:eventId/auth`, ({cookies}) => { - const token = cookies['eventToken']; - - if (token === VALID_TOKEN_FOR_TEST) { - return new HttpResponse(null, { - status: 200, - }); - } else if (token === EXPIRED_TOKEN_FOR_TEST) { - return HttpResponse.json( - { - errorCode: 'TOKEN_EXPIRED', - message: '만료된 토큰입니다.', - }, - {status: 401}, - ); - } else if (token === FORBIDDEN_TOKEN_FOR_TEST) { - return HttpResponse.json( - { - errorCode: 'FORBIDDEN', - message: '접근할 수 없는 행사입니다.', - }, - {status: 401}, - ); - } else if (token === undefined) { - return HttpResponse.json( - { - errorCode: 'TOKEN_NOT_FOUND', - message: '토큰이 존재하지 않습니다.', - }, - {status: 401}, - ); - } else { - return HttpResponse.json( - { - errorCode: 'TOKEN_INVALID', - message: '유효하지 않은 토큰입니다.', - }, - {status: 401}, - ); - } + // POST /api/eventId/auth (requestPostAuthentication) + http.post(`${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/auth`, () => { + return new HttpResponse(null, {status: 200}); }), - // TODO: (@weadie) any를 사용한 이유는.. any가 있는 위치가 이 handler함수의 responseBody타입인데, 아래처럼 return하는 것에 대한 예시가 공문에 없습니다. 함수를 까면 되겠지만 시간이 아깝고 알아낸다고 해서 이 responseBody 타입은 사실 중요한게 아니기 때문에 any로 대체하였습니다. - http.post<PostLoginParams, PostLoginRequestBody, any, `${typeof TEMP_PREFIX}/:eventId/login`>( - `${TEMP_PREFIX}/:eventId/login`, - async ({request}) => { + // POST /api/eventId/login (requestPostToken) + http.post<{eventId: string}, {password: string}>( + `${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/login`, + async ({params, request}) => { + const {eventId} = params; const {password} = await request.json(); - if (password === String(VALID_PASSWORD_FOR_TEST)) { - return new HttpResponse(null, { - headers: { - 'Set-Cookie': 'eventToken=abc-123', - }, - }); - } else if (password.length < PASSWORD_LENGTH) { + if (!password) { return HttpResponse.json( { - errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', - message: `비밀번호는 ${PASSWORD_LENGTH}자리 숫자만 가능합니다.`, + errorCode: 'REQUEST_EMPTY', + message: '비밀번호는 공백일 수 없습니다.', }, - {status: 401}, + {status: 400}, ); - } else if (password === undefined) { + } + if (password.length !== PASSWORD_LENGTH) { return HttpResponse.json( { - errorCode: 'REQUEST_EMPTY', - message: '비밀번호는 공백일 수 없습니다.', + errorCode: 'PASSWORD_INVALID', + message: `비밀번호는 ${PASSWORD_LENGTH}자리여야 합니다.`, }, - {status: 401}, + {status: 400}, ); + } + + // 비밀번호가 1234인 경우만 성공으로 처리 + if (password === '1234') { + return new HttpResponse(null, { + status: 200, + headers: { + 'Set-Cookie': `eventToken=${eventId}-token`, + }, + }); } else { return HttpResponse.json( { - errorCode: 'PASSWORD_INVALID', - message: '비밀번호가 일치하지 않습니다.', + errorCode: 'PASSWORD_INCORRECT', + message: '비밀번호가 올바르지 않습니다.', }, {status: 401}, ); diff --git a/client/src/mocks/handlers/billHandler.ts b/client/src/mocks/handlers/billHandler.ts new file mode 100644 index 000000000..0130b52a2 --- /dev/null +++ b/client/src/mocks/handlers/billHandler.ts @@ -0,0 +1,105 @@ +import {http, HttpResponse, PathParams} from 'msw'; + +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; + +import {billData, billDetailsData} from '@mocks/sharedState'; + +import {MOCK_API_PREFIX} from './../mockEndpointPrefix'; + +interface BillDetailsData { + [key: string]: {billDetails: {id: number; memberName: string; price: string}[]}; +} + +export const billHandler = [ + // GET /api/eventId/bills + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/bills`, () => { + return HttpResponse.json(billData); + }), + + // GET /api/eventId/bills/billId/fixed + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/bills/:billId/fixed`, ({params}) => { + const {billId} = params; + const billDetails = (billDetailsData as unknown as BillDetailsData)[billId as keyof BillDetailsData]; + return HttpResponse.json({billDetails}); + }), + + // POST /api/eventId/bills + http.post<PathParams, {title: string; price: number; members: number[]}>( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/bills`, + async ({request}) => { + try { + const {title, price, members} = await request.json(); + const newBill = {id: Date.now(), title, price, isFixed: false}; + + billData.steps[0].bills.push(newBill); + billData.steps[0].members = members.map(id => ({id, name: `Member ${id}`})); + + (billDetailsData as unknown as BillDetailsData)[newBill.id.toString()] = { + billDetails: members.map((id, index) => ({ + id, + memberName: `Member ${id}`, + price: (Math.floor(price / members.length) + (index < price % members.length ? 1 : 0)).toString(), + })), + }; + + return HttpResponse.json({status: 200}); + } catch (error) { + return HttpResponse.json({message: 'Internal Server Error'}, {status: 500}); + } + }, + ), + + // DELETE /api/eventId/bills/billId + http.delete(`${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/bills/:billId`, ({params}) => { + const {billId} = params; + billData.steps.forEach(step => { + step.bills = step.bills.filter(bill => bill.id !== Number(billId)); + }); + delete (billDetailsData as unknown as BillDetailsData)[billId as keyof BillDetailsData]; + return HttpResponse.json({status: 200}); + }), + + // PUT /api/eventId/bills/billId + http.put<PathParams, {title: string; price: number}>( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/bills/:billId`, + async ({params, request}) => { + const {billId} = params; + const {title, price} = await request.json(); + + billData.steps.forEach(step => { + const billIndex = step.bills.findIndex(bill => bill.id === Number(billId)); + if (billIndex !== -1) { + step.bills[billIndex] = {...step.bills[billIndex], title, price}; + } + }); + + return HttpResponse.json({status: 200}); + }, + ), + + // PUT /api/eventId/bills/billId/fixed + http.put<PathParams, {billDetails: {id: number; price: number; isFixed: boolean}[]}>( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/bills/:billId/fixed`, + async ({params, request}) => { + const {billId} = params; + const {billDetails} = await request.json(); + + (billDetailsData as unknown as BillDetailsData)[billId as keyof BillDetailsData] = { + billDetails: billDetails.map(detail => ({ + id: detail.id, + memberName: 'Unknown', + price: detail.price.toString(), + })), + }; + + billData.steps.forEach(step => { + const billIndex = step.bills.findIndex(bill => bill.id === Number(billId)); + if (billIndex !== -1) { + step.bills[billIndex].isFixed = true; + } + }); + + return HttpResponse.json({status: 200}); + }, + ), +]; diff --git a/client/src/mocks/handlers/eventHandlers.ts b/client/src/mocks/handlers/eventHandlers.ts index 351993e16..81560e4ed 100644 --- a/client/src/mocks/handlers/eventHandlers.ts +++ b/client/src/mocks/handlers/eventHandlers.ts @@ -1,55 +1,64 @@ -import {HttpResponse, http} from 'msw'; +import {http, HttpResponse} from 'msw'; -import {RequestPostNewEvent, ResponsePostNewEvent} from '@apis/request/event'; +import {Event, EventId} from 'types/serviceType'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; - -import {PASSWORD_LENGTH} from '@constants/password'; +import {USER_API_PREFIX} from '@apis/endpointPrefix'; import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; - -type ErrorResponseBody = { - errorCode: string; - message: string; -}; +import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; +import {eventData} from '@mocks/sharedState'; export const eventHandler = [ - http.post<any, RequestPostNewEvent, ResponsePostNewEvent | ErrorResponseBody, `${typeof TEMP_PREFIX}`>( - `${TEMP_PREFIX}`, + // POST /api/events (requestPostEvent) + http.post<any, {eventName: string; password: string}>(`${MOCK_API_PREFIX}${USER_API_PREFIX}`, async ({request}) => { + const {eventName, password} = await request.json(); + + if ( + eventName.length < VALID_EVENT_NAME_LENGTH_IN_SERVER.min || + eventName.length > VALID_EVENT_NAME_LENGTH_IN_SERVER.max + ) { + return HttpResponse.json( + { + errorCode: 'EVENT_NAME_LENGTH_INVALID', + message: '행사 이름은 2자 이상 30자 이하만 입력 가능합니다.', + }, + {status: 400}, + ); + } + + if (password.length !== 4) { + return HttpResponse.json( + { + errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', + message: '비밀번호는 4자리 숫자만 가능합니다.', + }, + {status: 400}, + ); + } + + const eventId: EventId = {eventId: 'mock-event-id'}; + return HttpResponse.json(eventId, { + status: 201, + headers: { + 'Set-Cookie': 'eventToken=mock-event-token', + }, + }); + }), + + // GET /api/events/:eventId (requestGetEvent) + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId`, () => { + return HttpResponse.json(eventData); + }), + + // PUT /api/events/:eventId (requestPutEvent) + http.put<any, {eventName?: string; bankName?: string; accountNumber?: string}>( + `${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId`, async ({request}) => { - const {eventName, password} = await request.json(); - - if (String(password).length < PASSWORD_LENGTH) { - return HttpResponse.json( - { - errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', - message: '비밀번호는 4자리 숫자만 가능합니다.', - }, - {status: 401}, - ); - } else if ( - eventName.length < VALID_EVENT_NAME_LENGTH_IN_SERVER.min || - eventName.length > VALID_EVENT_NAME_LENGTH_IN_SERVER.max - ) { - return HttpResponse.json( - { - errorCode: 'EVENT_NAME_LENGTH_INVALID', - message: `행사 이름은 2자 이상 30자 이하만 입력 가능합니다. 입력한 이름 길이 : ${eventName.length}`, - }, - {status: 401}, - ); - } else { - return HttpResponse.json( - { - eventId: 'eventId', - }, - { - headers: { - 'Set-Cookie': 'eventToken=abc-123', - }, - }, - ); - } + const updates = await request.json(); + + Object.assign(eventData, updates); + + return HttpResponse.json({status: 200}); }, ), ]; diff --git a/client/src/mocks/handlers/memberHandler.ts b/client/src/mocks/handlers/memberHandler.ts new file mode 100644 index 000000000..97233c8b5 --- /dev/null +++ b/client/src/mocks/handlers/memberHandler.ts @@ -0,0 +1,62 @@ +import {http, HttpResponse, PathParams} from 'msw'; + +import {AllMembers, Members} from 'types/serviceType'; + +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; + +import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; +import {memberData} from '@mocks/sharedState'; + +export const memberHandler = [ + // POST /api/eventId/members (requestPostMember) + http.post<PathParams, {members: {name: string}[]}>( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/members`, + async ({request}) => { + const {members: newMembers} = await request.json(); + const addedMembers = newMembers.map((member, index) => ({ + id: memberData.members.length + index + 1, + name: member.name, + isDeposited: false, + })); + + memberData.members = [...memberData.members, ...addedMembers]; + + return HttpResponse.json({members: addedMembers}, {status: 201}); + }, + ), + + // DELETE /api/eventId/members/memberId (requestDeleteMember) + http.delete(`${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/members/:memberId`, ({params}) => { + const {memberId} = params; + memberData.members = memberData.members.filter(member => member.id !== Number(memberId)); + return HttpResponse.json({status: 200}); + }), + + // PUT /api/eventId/members (requestPutMember) + http.put<PathParams, {members: {id: number; name: string; isDeposited: boolean}[]}>( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId/members`, + async ({request}) => { + const {members: updatedMembers} = await request.json(); + + memberData.members = memberData.members.map(member => { + const updatedMember = updatedMembers.find(m => m.id === member.id); + return updatedMember ? {...member, ...updatedMember} : member; + }); + + return HttpResponse.json({status: 200}); + }, + ), + + // GET /api/eventId/members/current (requestGetCurrentMember) + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/members/current`, () => { + const currentMembers: Members = { + members: memberData.members.map(({id, name}) => ({id, name})), + }; + return HttpResponse.json(currentMembers); + }), + + // GET /api/eventId/members (requestGetAllMember) + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/members`, () => { + return HttpResponse.json(memberData); + }), +]; diff --git a/client/src/mocks/handlers/memberReportInActionHandlers.ts b/client/src/mocks/handlers/memberReportInActionHandlers.ts deleted file mode 100644 index 45de357f1..000000000 --- a/client/src/mocks/handlers/memberReportInActionHandlers.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {http, HttpResponse} from 'msw'; - -import {MemberReport} from 'types/serviceType'; - -import {TEMP_PREFIX} from '@apis/tempPrefix'; - -import memberReportInActionJson from '../memberReportListInAction.json'; - -let memberReportInActionMockData = memberReportInActionJson as MemberReport[]; - -type MemberReportListRequestParams = { - eventId: string; - actionId: string; -}; -type MemberReportListBody = {members: MemberReport[]}; - -export const memberReportInActionHandler = [ - http.get< - MemberReportListRequestParams, - MemberReportListBody, - any, - `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed` - >(`${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, ({params}) => { - const {actionId} = params; - - if (Number(actionId) === 123) { - return HttpResponse.json({ - members: memberReportInActionMockData, - }); - } - - return HttpResponse.json({ - members: memberReportInActionMockData.slice(0, 2), - }); - }), - - http.put<any, MemberReportListBody, any, `${typeof TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`>( - `${TEMP_PREFIX}/:eventId/bill-actions/:actionId/fixed`, - async ({request}) => { - const {members} = await request.json(); - - memberReportInActionMockData = members; - - return HttpResponse.json({ - status: 200, - }); - }, - ), -]; diff --git a/client/src/mocks/handlers/reportHandlers.ts b/client/src/mocks/handlers/reportHandlers.ts index 6b256d7d3..5248fe82a 100644 --- a/client/src/mocks/handlers/reportHandlers.ts +++ b/client/src/mocks/handlers/reportHandlers.ts @@ -1,13 +1,13 @@ -import {HttpResponse, http} from 'msw'; +import {http, HttpResponse} from 'msw'; -import {TEMP_PREFIX} from '@apis/tempPrefix'; +import {USER_API_PREFIX} from '@apis/endpointPrefix'; -import reportListJson from '../reportList.json'; +import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; +import {reportData} from '@mocks/sharedState'; export const reportHandlers = [ - http.get(`${TEMP_PREFIX}/:eventId/actions/reports`, () => { - return HttpResponse.json({ - reports: reportListJson, - }); + // GET /api/eventId/reports (requestGetMemberReport) + http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/reports`, () => { + return HttpResponse.json(reportData); }), ]; diff --git a/client/src/mocks/handlers/stepListHandler.ts b/client/src/mocks/handlers/stepListHandler.ts deleted file mode 100644 index d79b7b0b4..000000000 --- a/client/src/mocks/handlers/stepListHandler.ts +++ /dev/null @@ -1,113 +0,0 @@ -import {HttpResponse, http} from 'msw'; - -import {Bill, MemberType, StepList} from 'types/serviceType'; - -import {TEMP_PREFIX} from '@apis/tempPrefix'; - -import stepListJson from '../stepList.json'; - -type StepListResponseBody = { - step: StepList; -}; - -type PostMemberListRequestBody = { - members: string[]; - status: MemberType; -}; - -type PostBillListRequestBody = { - actions: Bill[]; -}; - -let stepListMockData = stepListJson; - -export const stepListHandler = [ - http.get<any, StepListResponseBody, any, `${typeof TEMP_PREFIX}/:eventId/actions`>( - `${TEMP_PREFIX}/:eventId/actions`, - () => { - return HttpResponse.json({ - steps: stepListMockData, - }); - }, - ), - - http.get(`${TEMP_PREFIX}/:eventId/members`, () => { - return HttpResponse.json({ - memberNames: stepListMockData - .filter(({type}) => type !== 'BILL') - .map(({actions}) => actions.map(({name}) => name)) - .flat(), - }); - }), - - http.delete<{actionId: string}>(`${TEMP_PREFIX}/:eventId/member-actions/:actionId`, ({params}) => { - const {actionId} = params; - - if (parseInt(actionId) === 999) { - return HttpResponse.json( - { - errorCode: 'MEMBER_ACTION_STATUS_INVALID', - message: 'actionId는 999일 수 없습니다.(고의로 만든 에러임)', - }, - {status: 401}, - ); - } else { - return HttpResponse.json({ - status: 200, - }); - } - }), - - http.post<any, PostMemberListRequestBody, any, `${typeof TEMP_PREFIX}/:eventId/member-actions`>( - `${TEMP_PREFIX}/:eventId/member-actions`, - async ({request}) => { - const {members, status} = await request.json(); - stepListMockData = [ - ...stepListJson, - { - type: status, - stepName: '영차영차', - members: status === 'IN' ? members : [], - actions: members.map(name => ({ - actionId: 999, - name, - price: 0, - sequence: 999, - isFixed: false, - })), - }, - ]; - - return HttpResponse.json({ - status: 200, - }); - }, - ), - - http.post<any, PostBillListRequestBody, any, `${typeof TEMP_PREFIX}/:eventId/bill-actions`>( - `${TEMP_PREFIX}/:eventId/bill-actions`, - async ({request}) => { - const {actions} = await request.json(); - - stepListMockData = [ - ...stepListJson, - { - type: 'BILL', - stepName: '밥스카이', - members: [], - actions: actions.map(({title, price}) => ({ - actionId: 999, - name: title, - price, - sequence: 999, - isFixed: false, - })), - }, - ]; - - return HttpResponse.json({ - status: 200, - }); - }, - ), -]; diff --git a/client/src/mocks/invalidMemberStepList.json b/client/src/mocks/invalidMemberStepList.json deleted file mode 100644 index 33ca77e4c..000000000 --- a/client/src/mocks/invalidMemberStepList.json +++ /dev/null @@ -1,100 +0,0 @@ -[ - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 999, - "name": "망쵸", - "price": null, - "sequence": 1, - "isFixed": false - }, - { - "actionId": 2, - "name": "백호", - "price": null, - "sequence": 2, - "isFixed": false - } - ] - }, - { - "type": "BILL", - "stepName": "1차", - "members": ["망쵸", "백호"], - "actions": [ - { - "actionId": 3, - "name": "감자탕", - "price": 10000, - "sequence": 3, - "isFixed": false - }, - { - "actionId": 4, - "name": "인생네컷", - "price": 10000, - "sequence": 4, - "isFixed": false - } - ] - }, - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 5, - "name": "소하", - "price": null, - "sequence": 5, - "isFixed": false - }, - { - "actionId": 6, - "name": "웨디", - "price": null, - "sequence": 6, - "isFixed": false - } - ] - }, - { - "type": "BILL", - "stepName": "2차", - "members": ["소하", "웨디"], - "actions": [ - { - "actionId": 9, - "name": "노래방", - "price": 20000, - "sequence": 10, - "isFixed": false - } - ] - }, - { - "type": "OUT", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 7, - "name": "망쵸", - "price": null, - "sequence": 7, - "isFixed": false - }, - { - "actionId": 8, - "name": "백호", - "price": null, - "sequence": 8, - "isFixed": false - } - ] - } -] diff --git a/client/src/mocks/memberActionStepList.json b/client/src/mocks/memberActionStepList.json deleted file mode 100644 index 734db4a75..000000000 --- a/client/src/mocks/memberActionStepList.json +++ /dev/null @@ -1,23 +0,0 @@ -[ - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 1, - "name": "망쵸", - "price": null, - "sequence": 1, - "isFixed": false - }, - { - "actionId": 2, - "name": "백호", - "price": null, - "sequence": 2, - "isFixed": false - } - ] - } -] diff --git a/client/src/mocks/memberReportListInAction.json b/client/src/mocks/memberReportListInAction.json deleted file mode 100644 index 2e24670cb..000000000 --- a/client/src/mocks/memberReportListInAction.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - {"name": "망쵸", "price": 25000, "isFixed": false}, - {"name": "이상", "price": 25000, "isFixed": false}, - {"name": "소하", "price": 25000, "isFixed": false}, - {"name": "쿠키", "price": 25000, "isFixed": false} -] diff --git a/client/src/mocks/memberReportSearchList.json b/client/src/mocks/memberReportSearchList.json deleted file mode 100644 index dfcb684b1..000000000 --- a/client/src/mocks/memberReportSearchList.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - {"name": "망쵸", "price": 1033200}, - {"name": "이상", "price": 10100}, - {"name": "소하", "price": 10000}, - {"name": "쿠키", "price": 100012}, - {"name": "토다리", "price": 1001230}, - {"name": "감자", "price": 1012300}, - {"name": "백호", "price": 10300}, - {"name": "웨디", "price": 1000} -] diff --git a/client/src/mocks/mockEndpointPrefix.ts b/client/src/mocks/mockEndpointPrefix.ts new file mode 100644 index 000000000..d02762e51 --- /dev/null +++ b/client/src/mocks/mockEndpointPrefix.ts @@ -0,0 +1,3 @@ +import {BASE_URL} from '@apis/baseUrl'; + +export const MOCK_API_PREFIX = typeof window !== 'undefined' ? `${BASE_URL.HD}` : ''; diff --git a/client/src/mocks/reportList.json b/client/src/mocks/reportList.json deleted file mode 100644 index a663eb9fd..000000000 --- a/client/src/mocks/reportList.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - { - "name": "소하", - "price": 40000 - }, - { - "name": "감자", - "price": 20000 - }, - { - "name": "쿠키", - "price": 40000 - }, - { - "name": "토다리", - "price": 0 - } -] diff --git a/client/src/mocks/sharedState.ts b/client/src/mocks/sharedState.ts new file mode 100644 index 000000000..d35b7926a --- /dev/null +++ b/client/src/mocks/sharedState.ts @@ -0,0 +1,109 @@ +export let eventData = { + eventName: 'MSW 야유회', + bankName: '', + accountNumber: '', +}; + +export let memberData = { + members: [ + {id: 1, name: '망쵸', isDeposited: false}, + {id: 2, name: '백호', isDeposited: true}, + {id: 3, name: '감자', isDeposited: true}, + ], +}; + +export let billData = { + steps: [ + { + bills: [ + {id: 1, title: '커피', price: 10000, isFixed: false}, + {id: 2, title: '인생네컷', price: 20000, isFixed: false}, + ], + members: [ + {id: 1, name: '망쵸'}, + {id: 2, name: '백호'}, + ], + }, + { + bills: [{id: 3, title: '맥주', price: 20000, isFixed: true}], + members: [ + {id: 1, name: '망쵸'}, + {id: 2, name: '백호'}, + {id: 3, name: '감자'}, + ], + }, + ], +}; + +export let billDetailsData = { + '1': { + billDetails: [ + { + id: 1, + memberName: '망쵸', + price: 5000, + }, + { + id: 2, + memberName: '백호', + price: 5000, + }, + ], + }, + '2': { + billDetails: [ + { + id: 1, + memberName: '망쵸', + price: 10000, + }, + { + id: 2, + memberName: '백호', + price: 10000, + }, + ], + }, + '3': { + billDetails: [ + { + id: 1, + memberName: '망쵸', + price: 5000, + }, + { + id: 2, + memberName: '백호', + price: 10000, + }, + { + id: 2, + memberName: '감자', + price: 5000, + }, + ], + }, +}; + +export let reportData = { + reports: [ + { + memberId: 1, + name: '망쵸', + price: 20000, + isDeposited: false, + }, + { + memberId: 2, + name: '백호', + price: 25000, + isDeposited: true, + }, + { + memberId: 3, + name: '감자', + price: 5000, + isDeposited: true, + }, + ], +}; diff --git a/client/src/mocks/stepList.json b/client/src/mocks/stepList.json deleted file mode 100644 index 355692d58..000000000 --- a/client/src/mocks/stepList.json +++ /dev/null @@ -1,100 +0,0 @@ -[ - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 1, - "name": "망쵸", - "price": null, - "sequence": 1, - "isFixed": false - }, - { - "actionId": 2, - "name": "백호", - "price": null, - "sequence": 2, - "isFixed": false - } - ] - }, - { - "type": "BILL", - "stepName": "1차", - "members": ["망쵸", "백호"], - "actions": [ - { - "actionId": 3, - "name": "감자탕", - "price": 10000, - "sequence": 3, - "isFixed": false - }, - { - "actionId": 4, - "name": "인생네컷", - "price": 10000, - "sequence": 4, - "isFixed": false - } - ] - }, - { - "type": "IN", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 5, - "name": "소하", - "price": null, - "sequence": 5, - "isFixed": false - }, - { - "actionId": 6, - "name": "웨디", - "price": null, - "sequence": 6, - "isFixed": false - } - ] - }, - { - "type": "BILL", - "stepName": "2차", - "members": ["소하", "웨디"], - "actions": [ - { - "actionId": 9, - "name": "노래방", - "price": 20000, - "sequence": 10, - "isFixed": false - } - ] - }, - { - "type": "OUT", - "stepName": null, - "members": [], - "actions": [ - { - "actionId": 7, - "name": "망쵸", - "price": null, - "sequence": 7, - "isFixed": false - }, - { - "actionId": 8, - "name": "백호", - "price": null, - "sequence": 8, - "isFixed": false - } - ] - } -] diff --git a/client/src/pages/BillPage/AddBillFunnel.tsx b/client/src/pages/BillPage/AddBillFunnel.tsx new file mode 100644 index 000000000..d8ff14845 --- /dev/null +++ b/client/src/pages/BillPage/AddBillFunnel.tsx @@ -0,0 +1,220 @@ +import {css} from '@emotion/react'; +import {useEffect, useState} from 'react'; +import {useNavigate} from 'react-router-dom'; + +import NumberKeyboard from '@components/Design/components/NumberKeyboard/NumberKeyboard'; +import useRequestGetCurrentMembers from '@hooks/queries/member/useRequestGetCurrentMembers'; +import Top from '@components/Design/components/Top/Top'; +import ChipButton from '@components/Design/components/ChipButton/ChipButton'; +import AmountInput from '@components/AmountInput/AmountInput'; + +import {Back, FixedButton, Flex, LabelInput, MainLayout, Text, TopNav} from '@components/Design'; + +type BillStep = 'title' | 'price' | 'members'; + +interface BillInfo { + price: string; + title: string; + members: string[]; +} + +const AddBillFunnel = () => { + const {currentMembers} = useRequestGetCurrentMembers(); + const [step, setStep] = useState<BillStep>('price'); + const [billInfo, setBillInfo] = useState<BillInfo>({ + price: '', + title: '', + members: [], + }); + const [errorMessage, setErrorMessage] = useState(''); + const [nameInput, setNameInput] = useState(''); + const navigate = useNavigate(); + + useEffect(() => { + currentMembers && setBillInfo(prev => ({...prev, members: currentMembers.map(member => member.name)})); + }, [currentMembers]); + + const handleNumberKeyboardChange = (value: string) => { + setBillInfo(prev => ({...prev, price: value || prev.price})); + }; + + const handleTitleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => { + setBillInfo(prev => ({...prev, title: event.target.value})); + }; + + const handleTitleInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.nativeEvent.isComposing) { + return; + } + if (event.key === 'Enter') { + event.preventDefault(); + setStep('members'); + } + }; + + const handleNameInputChange = (event: React.ChangeEvent<HTMLInputElement>) => setNameInput(event.target.value); + + const handleNameInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.nativeEvent.isComposing) { + return; + } + if (event.key === 'Enter') { + console.log(nameInput); + event.preventDefault(); + if (!billInfo.members.includes(nameInput)) { + setBillInfo(prev => ({...prev, members: [...prev.members, nameInput]})); + } + setNameInput(''); + } + }; + + const setStepPrice = () => { + setStep('price'); + }; + + const setStepTitle = () => { + setStep('title'); + }; + + const setStepMembers = () => { + setStep('members'); + }; + + const priceStep = () => ( + <> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="사용한 금액은 얼마인가요?" emphasize={['사용한 금액']} /> + </Top> + <AmountInput value={billInfo.price} /> + </div> + <div + css={css` + position: fixed; + width: 100%; + max-width: 768px; + bottom: 6.25rem; + `} + > + <NumberKeyboard type="amount" maxNumber={10000000} onChange={handleNumberKeyboardChange} /> + </div> + <FixedButton disabled={!billInfo.price} onClick={setStepTitle} onBackClick={() => navigate(-1)}> + 다음으로 + </FixedButton> + </> + ); + + const titleStep = () => ( + <> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text={`${billInfo.price}원을`} /> + <Top.Line text="어떤 곳에서 사용했나요??" emphasize={['어떤 곳']} /> + </Top> + <LabelInput + labelText="결제 내용" + errorText={errorMessage ?? ''} + value={billInfo.title} + type="text" + placeholder="행동대장 포차" + onChange={handleTitleInputChange} + isError={!!errorMessage} + autoFocus + onKeyDown={handleTitleInputEnter} + /> + </div> + <FixedButton disabled={!billInfo.title} onClick={setStepMembers} onBackClick={setStepPrice}> + 다음으로 + </FixedButton> + </> + ); + + const membersStep = () => ( + <> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text={`${billInfo.title}에`} /> + <Top.Line text="참여한 사람은 누구인가요?" emphasize={['참여한 사람']} /> + </Top> + <LabelInput + labelText="이름" + errorText={errorMessage ?? ''} + value={nameInput} + type="text" + placeholder="박행댕" + onChange={handleNameInputChange} + isError={!!errorMessage} + autoFocus + onKeyDown={handleNameInputEnter} + /> + <div + css={css` + display: flex; + flex-direction: column; + gap: 0.375rem; + `} + > + <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> + <Text size="caption" textColor="gray"> + 참여 인원 + </Text> + <Text size="caption" textColor="gray">{`총 ${billInfo.members.length}명`}</Text> + </Flex> + <div + css={css` + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + `} + > + {billInfo.members.map(member => ( + <ChipButton + key={member} + color="gray" + text={member} + onClick={() => setBillInfo(prev => ({...prev, members: prev.members.filter(name => name !== member)}))} + /> + ))} + </div> + </div> + </div> + <FixedButton disabled={!billInfo.title} onClick={setStepMembers} onBackClick={setStepTitle}> + 추가완료 + </FixedButton> + </> + ); + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + {step === 'price' && priceStep()} + {step === 'title' && titleStep()} + {step === 'members' && membersStep()} + </MainLayout> + ); +}; + +export default AddBillFunnel; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx index 831bb1fd4..385d8c968 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx @@ -1,6 +1,8 @@ import {useLocation, useNavigate} from 'react-router-dom'; +import {css} from '@emotion/react'; import {RunningDog} from '@components/Common/Logo'; +import Top from '@components/Design/components/Top/Top'; import {FixedButton, MainLayout, Title, TopNav} from '@HDesign/index'; @@ -16,12 +18,20 @@ const CompleteCreateEventPage = () => { return ( <MainLayout backgroundColor="white"> <TopNav /> - <Title - title="행사 개시" - description={`행사가 성공적으로 개시됐어요 :) - 관리 페이지로 이동해서 정산을 시작할 수 있어요`} - /> - <RunningDog /> + <div + css={css` + display: flex; + flex-direction: column; + gap: 3rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="행사가 생성되었어요!" emphasize={['행사가 생성되었어요!']} /> + <Top.Line text="관리 페이지에서 정산을 시작하세요" emphasize={['정산을 시작하세요']} /> + </Top> + <RunningDog /> + </div> <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>관리 페이지로 이동</FixedButton> </MainLayout> ); diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index 73fca320e..f9fc9f3f5 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -1,9 +1,11 @@ import {useNavigate} from 'react-router-dom'; import {css} from '@emotion/react'; +import Top from '@components/Design/components/Top/Top'; + import useSetEventNamePage from '@hooks/useSetEventNamePage'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from '@HDesign/index'; +import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back, Flex} from '@HDesign/index'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -14,28 +16,51 @@ const SetEventNamePage = () => { const submitEventName = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); + onSuccessSubmint(); + }; + + const onSuccessSubmint = () => { navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); }; + const handleGoNextStep = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.key === 'Enter') { + onSuccessSubmint(); + } + }; + return ( <MainLayout backgroundColor="white"> <TopNav> <Back /> </TopNav> - <Title title="행사 이름 입력" description="시작할 행사 이름을 입력해 주세요." /> - <form onSubmit={submitEventName} css={css({padding: '0 1rem'})}> - <LabelInput - labelText="행사 이름" - errorText={errorMessage ?? ''} - value={eventName} - type="text" - placeholder="행사 이름" - onChange={handleEventNameChange} - isError={!!errorMessage} - autoFocus - ></LabelInput> - <FixedButton disabled={!canSubmit}>다음</FixedButton> - </form> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="정산을 시작하려는" /> + <Top.Line text="행사의 이름은 무엇인가요?" emphasize={['행사의 이름']} /> + </Top> + <form onSubmit={submitEventName}> + <LabelInput + labelText="행사 이름" + errorText={errorMessage ?? ''} + value={eventName} + type="text" + placeholder="행동대장 야유회" + onChange={handleEventNameChange} + isError={!!errorMessage} + autoFocus + onKeyDown={handleGoNextStep} + ></LabelInput> + <FixedButton disabled={!canSubmit}>다음</FixedButton> + </form> + </div> </MainLayout> ); }; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 9f6ba6a49..914f0a25b 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -1,3 +1,7 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from '@HDesign/index'; @@ -6,34 +10,51 @@ import RULE from '@constants/rule'; import {PASSWORD_LENGTH} from '@constants/password'; const SetEventPasswordPage = () => { - const {submitPassword, errorMessage, password, handleChange, canSubmit, isPostEventPending} = + const {submitPassword, onSuccess, errorMessage, password, handleChange, canSubmit, isPostEventPending} = useSetEventPasswordPage(); + const handleGoNextStep = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.key === 'Enter') { + onSuccess(); + } + }; + return ( <MainLayout backgroundColor="white"> <TopNav> <Back /> </TopNav> - <Title - title="행사 비밀번호 설정" - description={`행사 관리에 필요한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} - /> - <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> - <LabelInput - labelText="비밀번호" - errorText={errorMessage} - value={password} - type="text" - maxLength={RULE.maxEventPasswordLength} - placeholder="비밀번호" - onChange={handleChange} - isError={!!errorMessage} - autoFocus - /> - <FixedButton variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> - 행동 개시! - </FixedButton> - </form> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="관리에 필요한 네자리 숫자" emphasize={['네자리 숫자']} /> + <Top.Line text="비밀번호는 무엇으로 할까요?" emphasize={['비밀번호']} /> + </Top> + <form onSubmit={submitPassword}> + <LabelInput + labelText="비밀번호" + errorText={errorMessage} + value={password} + type="text" + maxLength={RULE.maxEventPasswordLength} + placeholder="1234" + onChange={handleChange} + isError={!!errorMessage} + autoFocus + onKeyDown={handleGoNextStep} + /> + {/* 가상 키패드 적용 예정 */} + <FixedButton variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> + 행동 개시! + </FixedButton> + </form> + </div> </MainLayout> ); }; diff --git a/client/src/pages/ErrorPage/ErrorPage.tsx b/client/src/pages/ErrorPage/ErrorPage.tsx index a405112e7..84f61b2a3 100644 --- a/client/src/pages/ErrorPage/ErrorPage.tsx +++ b/client/src/pages/ErrorPage/ErrorPage.tsx @@ -3,10 +3,7 @@ import {MainLayout, Title} from '@HDesign/index'; const ErrorPage = () => { return ( <MainLayout> - <Title - title="알 수 없는 오류입니다." - description="오류가 난 상황에 대해 haengdongdj@gmail.com 로 연락주시면 소정의 상품을 드립니다." - /> + <Title title="알 수 없는 오류입니다." /> </MainLayout> ); }; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts index cf6bb0042..830ec74a2 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.style.ts +++ b/client/src/pages/EventPage/AdminPage/AdminPage.style.ts @@ -4,7 +4,8 @@ export const receiptStyle = () => css({ display: 'flex', flexDirection: 'column', - gap: '1rem', + gap: '0.5rem', + paddingInline: '1rem', paddingBottom: '2rem', }); diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 855c79058..7a5168d27 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -1,90 +1,42 @@ -import {useEffect, useState} from 'react'; -import {useOutletContext} from 'react-router-dom'; +import {useEffect} from 'react'; +import {useNavigate, useOutletContext} from 'react-router-dom'; -import StepList from '@components/StepList/StepList'; -import {ModalBasedOnMemberCount, SetAllMemberListModal} from '@components/Modal/index'; -import useRequestGetAllMemberList from '@hooks/queries/useRequestGetAllMemberList'; -import useRequestPostAuthenticate from '@hooks/queries/useRequestPostAuthentication'; +import StepList from '@components/StepList/Steps'; +import useRequestPostAuthenticate from '@hooks/queries/auth/useRequestPostAuthentication'; +import useRequestGetSteps from '@hooks/queries/step/useRequestGetSteps'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; -import {Title, FixedButton, ListButton, Button} from '@HDesign/index'; +import {Title, Button} from '@HDesign/index'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; import {EventPageContextProps} from '../EventPageLayout'; -import {receiptStyle, titleAndListButtonContainerStyle, buttonGroupStyle} from './AdminPage.style'; +import {receiptStyle} from './AdminPage.style'; const AdminPage = () => { - const [isOpenFixedButtonBottomSheet, setIsOpenFixedButtonBottomSheet] = useState(false); - const [isOpenAllMemberListButton, setIsOpenAllMemberListButton] = useState(false); - const [isAddEditableItem, setIsAddEditableItem] = useState(false); - + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); const {eventName} = useOutletContext<EventPageContextProps>(); - const {data: allMemberListData} = useRequestGetAllMemberList(); - const allMemberList = allMemberListData?.memberNames ?? []; const {totalExpenseAmount} = useTotalExpenseAmountStore(); - const {mutate: postAuthentication} = useRequestPostAuthenticate(); + const {steps} = useRequestGetSteps(); + const {postAuthenticate} = useRequestPostAuthenticate(); useEffect(() => { - postAuthentication(); - }, [postAuthentication]); - - const handleOpenAllMemberListButton = () => { - setIsOpenFixedButtonBottomSheet(prev => !prev); - setIsOpenAllMemberListButton(prev => !prev); - }; - - const getTitleDescriptionByInitialMemberSetting = () => { - return allMemberList.length > 0 - ? `지출 내역 및 인원 변동을 추가해 주세요. - 인원 변동을 기준으로 몇 차인지 나뉘어져요.` - : '“시작 인원 추가” 버튼을 눌러 행사의 시작부터 참여하는 사람들의 이름을 입력해 주세요.'; - }; + postAuthenticate(); + }, [postAuthenticate]); return ( - <> - <div css={titleAndListButtonContainerStyle}> - <Title title={eventName} description={getTitleDescriptionByInitialMemberSetting()} price={totalExpenseAmount} /> - {allMemberList.length !== 0 && ( - <ListButton - prefix="전체 참여자" - suffix={`${allMemberList.length}명`} - onClick={handleOpenAllMemberListButton} - /> - )} - </div> - <section css={receiptStyle}> - <StepList isAddEditableItem={isAddEditableItem} setIsAddEditableItem={setIsAddEditableItem} /> - {allMemberList.length === 0 ? ( - <FixedButton children={'시작인원 추가하기'} onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} /> - ) : ( - <div css={buttonGroupStyle}> - <Button - size="medium" - variants="tertiary" - style={{width: '100%'}} - onClick={() => setIsOpenFixedButtonBottomSheet(prev => !prev)} - > - 인원 변동 추가 - </Button> - <Button size="medium" onClick={() => setIsAddEditableItem(true)} style={{width: '100%'}}> - 지출 내역 추가 - </Button> - </div> - )} - {isOpenFixedButtonBottomSheet && ( - <ModalBasedOnMemberCount - allMemberList={allMemberList} - setIsOpenBottomSheet={setIsOpenFixedButtonBottomSheet} - isOpenBottomSheet={isOpenFixedButtonBottomSheet} - isOpenAllMemberListButton={isOpenAllMemberListButton} - setIsOpenAllMemberListButton={setIsOpenAllMemberListButton} - /> - )} - </section> - </> + <section css={receiptStyle}> + <Title title={eventName} amount={totalExpenseAmount} /> + <StepList data={steps ?? []} /> + <Button size="medium" onClick={() => navigate(`/event/${eventId}/addBill`)} style={{width: '100%'}}> + 지출내역 추가하기 + </Button> + </section> ); }; diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index d099835bc..e126d1587 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,19 +1,20 @@ +import Top from '@components/Design/components/Top/Top'; + import useEventLogin from '@hooks/useEventLogin'; -import {FixedButton, LabelInput, Title} from '@HDesign/index'; +import {FixedButton, LabelInput} from '@HDesign/index'; import RULE from '@constants/rule'; -import {PASSWORD_LENGTH} from '@constants/password'; const EventLoginPage = () => { const {password, errorMessage, handleChange, canSubmit, submitPassword} = useEventLogin(); return ( <> - <Title - title="행사 비밀번호 입력" - description={`관리를 위해선 비밀번호가 필요해요. 행사 생성 시 설정한 ${PASSWORD_LENGTH} 자리의 숫자 비밀번호를 입력해 주세요.`} - /> + <Top> + <Top.Line text="행사 생성 시 설정한" /> + <Top.Line text="네자리 숫자 비밀번호를 입력해 주세요." /> + </Top> <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> <LabelInput labelText="비밀번호" diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index e76649f43..3eb21a90e 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -2,7 +2,7 @@ import {Outlet, useMatch} from 'react-router-dom'; import CopyToClipboard from 'react-copy-to-clipboard'; import {useToast} from '@hooks/useToast/useToast'; -import useRequestGetEventName from '@hooks/queries/useRequestGetEventName'; +import useRequestGetEvent from '@hooks/queries/event/useRequestGetEvent'; import useNavSwitch from '@hooks/useNavSwitch'; @@ -20,8 +20,7 @@ export type EventPageContextProps = { const EventPageLayout = () => { const {nav, paths, onChange} = useNavSwitch(); - const {data} = useRequestGetEventName(); - const eventName = data?.eventName ?? ''; + const {eventName} = useRequestGetEvent(); const eventId = getEventIdByUrl(); const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 0521d386b..34b91a762 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -1,7 +1,8 @@ import {useOutletContext} from 'react-router-dom'; -import MemberReportList from '@components/MemberReportList/MemberReportList'; -import StepList from '@components/StepList/StepList'; +import StepList from '@components/StepList/Steps'; +import useRequestGetSteps from '@hooks/queries/step/useRequestGetSteps'; +import Reports from '@components/Reports/Reports'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; @@ -11,14 +12,15 @@ import {EventPageContextProps} from '../EventPageLayout'; const HomePage = () => { const {eventName} = useOutletContext<EventPageContextProps>(); + const {steps} = useRequestGetSteps(); const {totalExpenseAmount} = useTotalExpenseAmountStore(); return ( <div style={{paddingBottom: '2rem'}}> - <Title title={eventName} price={totalExpenseAmount} /> + <Title title={eventName} amount={totalExpenseAmount} /> <Tabs tabsContainerStyle={{gap: '1rem'}}> - <Tab label="전체 지출 내역" content={<StepList />} /> - <Tab label="참여자 별 내역" content={<MemberReportList />} /> + <Tab label="전체 지출 내역" content={<StepList data={steps ?? []} />} /> + <Tab label="참여자 별 내역" content={<Reports />} /> </Tabs> </div> ); diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index 16d710e35..702972eff 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -5,7 +5,7 @@ import MainSection from './Section/MainSection'; import DescriptionSection from './Section/DescriptionSection'; import AddBillSection from './Section/AddBillSection'; import AddMemberSection from './Section/AddMemberSection'; -import MemberReportSection from './Section/MemberReportSection'; +import ReportSection from './Section/ReportSection'; const MainPage = () => { return ( @@ -15,7 +15,7 @@ const MainPage = () => { <DescriptionSection /> <AddBillSection /> <AddMemberSection /> - <MemberReportSection /> + <ReportSection /> </MainLayout> ); }; diff --git a/client/src/pages/MainPage/Section/MemberReportSection.tsx b/client/src/pages/MainPage/Section/ReportSection.tsx similarity index 91% rename from client/src/pages/MainPage/Section/MemberReportSection.tsx rename to client/src/pages/MainPage/Section/ReportSection.tsx index 6e51ae2b1..452365ea2 100644 --- a/client/src/pages/MainPage/Section/MemberReportSection.tsx +++ b/client/src/pages/MainPage/Section/ReportSection.tsx @@ -4,7 +4,7 @@ import MemberReportMockup from '@assets/image/memberReportMockup.svg'; import {Text} from '@HDesign/index'; -const MemberReportSection = () => { +const ReportSection = () => { return ( <div css={css({ @@ -29,4 +29,4 @@ const MemberReportSection = () => { ); }; -export default MemberReportSection; +export default ReportSection; diff --git a/client/src/router.tsx b/client/src/router.tsx index 51162c775..0cfe364e4 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -4,6 +4,7 @@ import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; +import AddBillFunnel from '@pages/BillPage/AddBillFunnel'; import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; import {MainPage} from '@pages/MainPage'; @@ -47,6 +48,10 @@ const router = createBrowserRouter([ }, ], }, + { + path: ROUTER_URLS.addBill, + element: <AddBillFunnel />, + }, { path: '*', element: <ErrorPage />, diff --git a/client/src/store/stepListStore.ts b/client/src/store/stepListStore.ts deleted file mode 100644 index 07f3b107f..000000000 --- a/client/src/store/stepListStore.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {create} from 'zustand'; - -import {ConvertedAction} from 'types/serviceType'; - -type State = { - stepList: ConvertedAction[]; -}; - -type Action = { - updateStepList: (stepList: State['stepList']) => void; -}; - -export const useStepListStore = create<State & Action>(set => ({ - stepList: [], - updateStepList: stepList => set(() => ({stepList})), -})); diff --git a/client/src/store/stepsStore.ts b/client/src/store/stepsStore.ts new file mode 100644 index 000000000..e89adf392 --- /dev/null +++ b/client/src/store/stepsStore.ts @@ -0,0 +1,16 @@ +import {create} from 'zustand'; + +import {Steps} from 'types/serviceType'; + +type State = { + steps: Steps[]; +}; + +type Action = { + updateSteps: (stepList: State['steps']) => void; +}; + +export const useBillsStore = create<State & Action>(set => ({ + steps: [], + updateSteps: steps => set(() => ({steps})), +})); diff --git a/client/src/store/totalExpenseAmountStore.ts b/client/src/store/totalExpenseAmountStore.ts index e9ebcf52a..cce46575e 100644 --- a/client/src/store/totalExpenseAmountStore.ts +++ b/client/src/store/totalExpenseAmountStore.ts @@ -1,6 +1,6 @@ import {create} from 'zustand'; -import {BillStep, MemberStep} from 'types/serviceType'; +import {Step as StepType} from 'types/serviceType'; import {getTotalExpenseAmount} from '@utils/caculateExpense'; @@ -9,10 +9,10 @@ type State = { }; type Action = { - updateTotalExpenseAmount: (stepList: (MemberStep | BillStep)[]) => void; + updateTotalExpenseAmount: (steps: StepType[]) => void; }; export const useTotalExpenseAmountStore = create<State & Action>(set => ({ totalExpenseAmount: 0, - updateTotalExpenseAmount: stepList => set({totalExpenseAmount: getTotalExpenseAmount(stepList)}), + updateTotalExpenseAmount: (steps: StepType[]) => set({totalExpenseAmount: getTotalExpenseAmount(steps)}), })); diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts index 0467995f1..39fa19957 100644 --- a/client/src/types/serviceType.ts +++ b/client/src/types/serviceType.ts @@ -1,80 +1,67 @@ -export type MemberType = 'IN' | 'OUT'; +// ******************************************************************* +// ******************** UX 개선 이후 변경된 부분들 24.09.19 **************** +// ******************************************************************* -export type InOutType = '늦참' | '탈주'; +export interface Steps { + steps: Step[]; +} -export type MemberReport = { - name: string; - price: number; -}; - -export type MemberReportInAction = MemberReport & { - isFixed: boolean; -}; +export interface Step { + bills: Bill[]; + members: Member[]; +} -export type Bill = { +export interface Bill { + id: number; title: string; price: number; -}; - -type StepBase = { - members: string[]; -}; - -export type MemberStep = StepBase & { - type: MemberType; - stepName: null; - actions: MemberAction[]; -}; - -export type BillStep = StepBase & { - type: 'BILL'; - stepName: string; - actions: BillAction[]; -}; - -// (@weadie) 준 데이터 형식에서 steps를 빼내 flat하게 사용중. 일관성있게 하는게 좋긴 하나 사용시 번거로움이 있을 거라고 판단. -export type StepList = { - steps: (MemberStep | BillStep)[]; -}; - -export type Action = { - actionId: number; - name: string; - price: number | null; - sequence: number; isFixed: boolean; -}; +} -export type BillAction = Omit<Action, 'price'> & { +export interface BillDetail { + id: number; + memberName: string; price: number; -}; + isFixed: boolean; +} -export type MemberAction = Omit<Action, 'price'> & { - price: null; -}; +export interface BillDetails { + billDetails: BillDetail[]; +} -export type Member = { +export interface Member { + id: number; name: string; - status: MemberType; -}; - -export type ActionType = 'IN' | 'OUT' | 'BILL'; - -// export type StepList = { -// actions: Action[]; -// }; - -export type ConvertedAction = { - actionId: number; +} + +export interface Members { + members: Member[]; +} + +export interface MemberWithDeposited extends Member { + isDeposited: boolean; +} + +export interface AllMembers { + members: MemberWithDeposited[]; +} +export interface EventId { + eventId: string; +} + +export interface Event { + eventName: string; + bankName: string; + accountNumber: string; +} + +export interface Report { + memberId: number; name: string; - price: string | null; - sequence: number; - type: ActionType; -}; - -export type InputPair = Omit<Bill, 'price'> & { - price: string; - index: number; -}; + isDeposited: boolean; + price: number; +} -export type BillInputType = 'title' | 'price'; +export interface Reports { + reports: Report[]; +} diff --git a/client/src/utils/caculateExpense.ts b/client/src/utils/caculateExpense.ts index 8b41af8c3..2ee8c2fa5 100644 --- a/client/src/utils/caculateExpense.ts +++ b/client/src/utils/caculateExpense.ts @@ -1,14 +1,8 @@ -import {BillAction, BillStep, MemberStep} from 'types/serviceType'; +import {Step} from 'types/serviceType'; -export const calculateStepExpense = (actions: BillAction[]) => { - return actions.reduce((sum, {price}) => sum + price, 0); -}; - -export const getTotalExpenseAmount = (stepList: (MemberStep | BillStep)[]) => { - return stepList.reduce((sum, {type, actions}) => { - if (type === 'BILL') { - return sum + calculateStepExpense(actions); - } - return sum; +export const getTotalExpenseAmount = (steps: Step[]) => { + return steps.reduce((total, step) => { + const stepTotal = step.bills.reduce((sum, bill) => sum + bill.price, 0); + return total + stepTotal; }, 0); }; diff --git a/client/src/utils/groupActions.ts b/client/src/utils/groupActions.ts deleted file mode 100644 index a6347167d..000000000 --- a/client/src/utils/groupActions.ts +++ /dev/null @@ -1,27 +0,0 @@ -import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; - -import stepListToAction from './stepListToActions'; - -const groupActions = (stepList: (BillStep | MemberStep)[]) => { - const actions = stepListToAction(stepList); - const groupedActions: ConvertedAction[][] = []; - - let group: ConvertedAction[] = []; - - actions.forEach((action, index) => { - if (group.length === 0 || group[group.length - 1].type === action.type) { - group.push(action); - } else { - groupedActions.push(group); - group = []; - } - - if (index === actions.length - 1) { - groupedActions.push(group); - } - }); - - return groupedActions; -}; - -export default groupActions; diff --git a/client/src/utils/stepListToActions.ts b/client/src/utils/stepListToActions.ts deleted file mode 100644 index 5fe1bb3a7..000000000 --- a/client/src/utils/stepListToActions.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {BillStep, ConvertedAction, MemberStep} from 'types/serviceType'; - -const stepListToAction = (stepList: (BillStep | MemberStep)[]) => { - // (@todari) test용이라 임시로 any 사용할게용... - // Action을 사용하려고 하는데 serviceType의 기존 Action이랑 겹쳐서요~~~ - const actions: ConvertedAction[] = []; - - stepList.forEach(step => { - step.actions.forEach(action => { - actions.push({ - actionId: action.actionId, - name: action.name, - price: action.price ? action.price.toLocaleString() : null, - sequence: action.sequence, - type: step.type, - }); - }); - }); - - return actions; -}; - -export default stepListToAction; diff --git a/client/src/utils/validate/validateMemberReportInAction.ts b/client/src/utils/validate/validateBillDetails.ts similarity index 85% rename from client/src/utils/validate/validateMemberReportInAction.ts rename to client/src/utils/validate/validateBillDetails.ts index b4e6c2a9a..a77a154a5 100644 --- a/client/src/utils/validate/validateMemberReportInAction.ts +++ b/client/src/utils/validate/validateBillDetails.ts @@ -3,7 +3,7 @@ import RULE from '@constants/rule'; import {ValidateResult} from './type'; -const validateMemberReportInAction = (price: string, totalPrice: number): ValidateResult => { +const validateBillDetails = (price: string, totalPrice: number): ValidateResult => { let errorMessage = null; const numberTypePrice = Number(price); @@ -30,4 +30,4 @@ const validateMemberReportInAction = (price: string, totalPrice: number): Valida return {isValid: false, errorMessage: errorMessage || ERROR_MESSAGE.invalidInput}; }; -export default validateMemberReportInAction; +export default validateBillDetails; From 9bcbace8817660c02c2f539d335fa66d33be33d5 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:04:31 +0900 Subject: [PATCH 230/273] =?UTF-8?q?feat:=20=EC=B4=88=EB=8C=80=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20OS=20=EA=B3=B5=EC=9C=A0=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#548)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 카카오 공유를 사용하기 위한 초기 설정 * feat: 모바일 디바이스를 감지할 수 있는 메서드 추가 * feat: 모바일 기기에서는 카카오톡 공유, 데스크탑에서는 텍스트 복사 유지 * style: 공유 텍스트 객체를 재사용 * fix: kakao api test 환경에선 돌아가지 않도록 설정 * chore: cypress-run node-env 추가 * fix: cypress에서 kakao init을 호출하지 않도록 mocking * fix: Cypress.on을 이용한 에러처리 무시; * fix: intercept 메서드 수정 * fix: test 환경이 아닌 경우 initialized도 읽지 않도록 변경 * fix: test 환경에선 돌아가지 않도록 부등호수정 * fix: window.kakao가 undefined일 경우 돌아가지 않도록 방어 * fix: 다시 blockKakao 복구 * style: member invite => share event로 컴포넌트 이름 변경 * refactor: event layout hook에서 share 책임 분리 * style: 카카오톡 공유 실행 함수 이름 변경 * style: useEventPageLayout hook 파일 이름 변경 * style: invite -> share로 용어 통일성 * refactor: isMobile 한 번만 호출되도록 변경 * fix: 변경된 구조로 인한 오류 수정 --- client/cypress/e2e/createEvent.cy.ts | 1 + client/cypress/support/commands.ts | 8 +++ client/index.html | 5 ++ client/src/App.tsx | 5 +- .../KakaoInitializer/KakaoInitializer.tsx | 15 ++++++ .../ShareEventButton/ShareEventButton.tsx | 41 +++++++++++++++ .../src/components/ShareEventButton/index.ts | 1 + client/src/global.d.ts | 1 + client/src/hooks/useEventPageLayout.ts | 23 +++++++++ client/src/hooks/useShareEvent.ts | 51 +++++++++++++++++++ .../src/pages/EventPage/EventPageLayout.tsx | 45 +++------------- client/src/types/kakao.d.ts | 38 ++++++++++++++ client/src/utils/isMobileDevice.ts | 8 +++ 13 files changed, 203 insertions(+), 39 deletions(-) create mode 100644 client/src/components/KakaoInitializer/KakaoInitializer.tsx create mode 100644 client/src/components/ShareEventButton/ShareEventButton.tsx create mode 100644 client/src/components/ShareEventButton/index.ts create mode 100644 client/src/hooks/useEventPageLayout.ts create mode 100644 client/src/hooks/useShareEvent.ts create mode 100644 client/src/types/kakao.d.ts create mode 100644 client/src/utils/isMobileDevice.ts diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts index 5b4a93884..5de7f4592 100644 --- a/client/cypress/e2e/createEvent.cy.ts +++ b/client/cypress/e2e/createEvent.cy.ts @@ -1,6 +1,7 @@ import CONSTANTS from '../constants/constants'; beforeEach(() => { cy.blockSentry(); + cy.blockKakao(); }); describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 flow', () => { diff --git a/client/cypress/support/commands.ts b/client/cypress/support/commands.ts index c51d00580..70c8524ea 100644 --- a/client/cypress/support/commands.ts +++ b/client/cypress/support/commands.ts @@ -21,6 +21,13 @@ Cypress.Commands.add('blockSentry', () => { cy.intercept('POST', /.*sentry.io\/api.*/, {statusCode: 200}).as('sentry'); }); +Cypress.Commands.add('blockKakao', () => { + cy.intercept('GET', 'https://t1.kakaocdn.net/kakao_js_sdk/2.7.2/kakao.min.js', { + statusCode: 200, + body: '', + }).as('blockKakao'); +}); + Cypress.Commands.add('interceptAPI', ({type, delay = 0, statusCode = 200}: InterceptAPIProps) => { if (type === 'postEvent') cy.intercept(POST_EVENT, { @@ -49,6 +56,7 @@ declare global { namespace Cypress { interface Chainable { blockSentry(): Chainable<void>; + blockKakao(): Chainable<void>; interceptAPI(props: InterceptAPIProps): Chainable<void>; createEventName(eventName: string): Chainable<void>; } diff --git a/client/index.html b/client/index.html index 4a21293f2..5252bb218 100644 --- a/client/index.html +++ b/client/index.html @@ -25,6 +25,11 @@ window.amplitude.init('<%= process.env.AMPLITUDE_KEY %>'); }); </script> + <script + src="https://t1.kakaocdn.net/kakao_js_sdk/2.7.2/kakao.min.js" + integrity="sha384-TiCUE00h649CAMonG018J2ujOgDKW/kVWlChEuu4jK2vxfAAD0eZxzCKakxg55G4" + crossorigin="anonymous" + ></script> <title>행동대장 diff --git a/client/src/App.tsx b/client/src/App.tsx index c3815ad2a..4535c6b8a 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -5,6 +5,7 @@ import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; import {ToastProvider} from '@hooks/useToast/ToastProvider'; import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; import ErrorCatcher from '@components/AppErrorBoundary/ErrorCatcher'; +import KakaoInitializer from '@components/KakaoInitializer/KakaoInitializer'; import {HDesignProvider} from '@HDesign/index'; @@ -20,7 +21,9 @@ const App: React.FC = () => { - + + + diff --git a/client/src/components/KakaoInitializer/KakaoInitializer.tsx b/client/src/components/KakaoInitializer/KakaoInitializer.tsx new file mode 100644 index 000000000..d3ed82bab --- /dev/null +++ b/client/src/components/KakaoInitializer/KakaoInitializer.tsx @@ -0,0 +1,15 @@ +import {useEffect} from 'react'; + +const KakaoInitializer = ({children}: React.PropsWithChildren) => { + useEffect(() => { + if (!window.Kakao) return; + + if (!window.Kakao.isInitialized()) { + window.Kakao.init(process.env.KAKAO_JAVASCRIPT_KEY); + } + }, []); + + return children; +}; + +export default KakaoInitializer; diff --git a/client/src/components/ShareEventButton/ShareEventButton.tsx b/client/src/components/ShareEventButton/ShareEventButton.tsx new file mode 100644 index 000000000..ff191a4cc --- /dev/null +++ b/client/src/components/ShareEventButton/ShareEventButton.tsx @@ -0,0 +1,41 @@ +import CopyToClipboard from 'react-copy-to-clipboard'; + +import {useToast} from '@hooks/useToast/useToast'; + +import useShareEvent from '@hooks/useShareEvent'; + +import {Button} from '@components/Design'; + +import isMobileDevice from '@utils/isMobileDevice'; + +const ShareEventButton = () => { + const {showToast} = useToast(); + + const isMobile = isMobileDevice(); + const {shareText, onShareButtonClick} = useShareEvent(isMobile); + + return isMobile ? ( + + ) : ( + + showToast({ + showingTime: 3000, + message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', + type: 'confirm', + position: 'bottom', + bottom: '8rem', + }) + } + > + + + ); +}; + +export default ShareEventButton; diff --git a/client/src/components/ShareEventButton/index.ts b/client/src/components/ShareEventButton/index.ts new file mode 100644 index 000000000..27b5883aa --- /dev/null +++ b/client/src/components/ShareEventButton/index.ts @@ -0,0 +1 @@ +export {default as ShareEventButton} from './ShareEventButton'; diff --git a/client/src/global.d.ts b/client/src/global.d.ts index dbf6320af..ddc00fc99 100644 --- a/client/src/global.d.ts +++ b/client/src/global.d.ts @@ -7,5 +7,6 @@ declare namespace NodeJS { // env keys readonly API_BASE_URL: string; readonly AMPLITUDE_KEY: string; + readonly KAKAO_JAVASCRIPT_KEY: string; } } diff --git a/client/src/hooks/useEventPageLayout.ts b/client/src/hooks/useEventPageLayout.ts new file mode 100644 index 000000000..227ef402d --- /dev/null +++ b/client/src/hooks/useEventPageLayout.ts @@ -0,0 +1,23 @@ +import {useMatch} from 'react-router-dom'; + +import {ROUTER_URLS} from '@constants/routerUrls'; + +import useNavSwitch from './useNavSwitch'; +import useRequestGetEvent from './queries/event/useRequestGetEvent'; + +const useEventPageLayout = () => { + const navProps = useNavSwitch(); + const {eventName} = useRequestGetEvent(); + + const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; + const isLoginPage = useMatch(ROUTER_URLS.eventLogin) !== null; + + return { + navProps, + isAdmin, + eventName, + isLoginPage, + }; +}; + +export default useEventPageLayout; diff --git a/client/src/hooks/useShareEvent.ts b/client/src/hooks/useShareEvent.ts new file mode 100644 index 000000000..4a6ae1923 --- /dev/null +++ b/client/src/hooks/useShareEvent.ts @@ -0,0 +1,51 @@ +import getEventIdByUrl from '@utils/getEventIdByUrl'; +import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; + +import useRequestGetEvent from './queries/event/useRequestGetEvent'; + +const useShareEvent = (isMobile: boolean) => { + const {eventName} = useRequestGetEvent(); + + const eventId = getEventIdByUrl(); + const url = getEventPageUrlByEnvironment(eventId, 'home'); + + const shareInfo = { + title: `[행동대장]\n${eventName}에 대한 정산을 시작할게요:)`, + text: '아래 링크에 접속해서 정산 내역을 확인해 주세요!', + url, + }; + + // 모바일이 아닌 기기는 단순 텍스트 복사 + // 모바일 기기에서는 카카오톡 공유를 사용 + const onShareButtonClick = () => { + if (!isMobile) return; + + kakaoShare(); + }; + + const kakaoShare = () => { + window.Kakao.Share.sendDefault({ + objectType: 'feed', + content: { + title: shareInfo.title, + description: shareInfo.text, + imageUrl: + 'https://wooteco-crew-wiki.s3.ap-northeast-2.amazonaws.com/%EC%9B%A8%EB%94%94%286%EA%B8%B0%29/g583lirp8yg.jpg', + link: { + mobileWebUrl: url, + webUrl: url, + }, + }, + buttonTitle: '정산 확인하기', + }); + }; + + const shareText = `${shareInfo.title}\n${shareInfo.text}\n${url}`; + + return { + shareText, + onShareButtonClick, + }; +}; + +export default useShareEvent; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 3eb21a90e..1f33cdc01 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,17 +1,10 @@ -import {Outlet, useMatch} from 'react-router-dom'; -import CopyToClipboard from 'react-copy-to-clipboard'; +import {Outlet} from 'react-router-dom'; -import {useToast} from '@hooks/useToast/useToast'; -import useRequestGetEvent from '@hooks/queries/event/useRequestGetEvent'; +import useEventPageLayout from '@hooks/useEventPageLayout'; -import useNavSwitch from '@hooks/useNavSwitch'; +import {ShareEventButton} from '@components/ShareEventButton'; -import {MainLayout, TopNav, Switch, Button} from '@HDesign/index'; - -import getEventIdByUrl from '@utils/getEventIdByUrl'; -import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; - -import {ROUTER_URLS} from '@constants/routerUrls'; +import {MainLayout, TopNav, Switch} from '@HDesign/index'; export type EventPageContextProps = { isAdmin: boolean; @@ -19,43 +12,19 @@ export type EventPageContextProps = { }; const EventPageLayout = () => { - const {nav, paths, onChange} = useNavSwitch(); - const {eventName} = useRequestGetEvent(); - const eventId = getEventIdByUrl(); - - const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; - const isLoginPage = useMatch(ROUTER_URLS.eventLogin) !== null; + const {navProps, isAdmin, isLoginPage, eventName} = useEventPageLayout(); + const {nav, paths, onChange} = navProps; const outletContext: EventPageContextProps = { isAdmin, eventName, }; - const {showToast} = useToast(); - const url = getEventPageUrlByEnvironment(eventId, 'home'); - return ( - {!isLoginPage && ( - - showToast({ - showingTime: 3000, - message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', - type: 'confirm', - position: 'bottom', - bottom: '8rem', - }) - } - > - - - )} + {!isLoginPage && } diff --git a/client/src/types/kakao.d.ts b/client/src/types/kakao.d.ts new file mode 100644 index 000000000..4d72a9833 --- /dev/null +++ b/client/src/types/kakao.d.ts @@ -0,0 +1,38 @@ +declare global { + interface Window { + Kakao: typeof Kakao; + } +} + +namespace Kakao { + function init(appKey: string): void; + function isInitialized(): boolean; + + namespace Share { + function cleanup(): void; + function sendDefault(params: sendDefaultParams): void; + + interface sendDefaultParams { + objectType: 'feed'; + content: { + title: string; + imageUrl: string; + imageWidth?: number; + imageHeight?: number; + description: string; + link: { + mobileWebUrl: string; + webUrl: string; + }; + }; + buttonTitle?: string; + buttons?: { + title: string; + link: { + webUrl: string; + mobileWebUrl: string; + }; + }[]; + } + } +} diff --git a/client/src/utils/isMobileDevice.ts b/client/src/utils/isMobileDevice.ts new file mode 100644 index 000000000..56e54f984 --- /dev/null +++ b/client/src/utils/isMobileDevice.ts @@ -0,0 +1,8 @@ +const isMobileDevice = () => { + const userAgent = window.navigator.userAgent; + const mobileRegex = [/Android/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i]; + + return mobileRegex.some(mobile => userAgent.match(mobile)); +}; + +export default isMobileDevice; From 3df58fe4f0b795953305d42fcc5e3f38470bc889 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:12:35 +0900 Subject: [PATCH 231/273] =?UTF-8?q?feat:=20=EC=B0=B8=EC=97=AC=EC=9E=90=20?= =?UTF-8?q?=EB=B3=84=20=EB=82=B4=EC=97=AD=EC=97=90=EC=84=9C=20=ED=86=A0?= =?UTF-8?q?=EC=8A=A4=EB=A1=9C=20=EC=86=A1=EA=B8=88=20=EC=9C=A0=EB=8F=84?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20(=EC=A4=91=EA=B0=84)?= =?UTF-8?q?=20(#556)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: png 확장자 추가로 인한 file-loader설치 및 png 확장자 선언 * feat: icon에 toss 타입 추가 * feat: 은행 선택 디자인 구현 * design: 은행선택 grid 반응형적용 * feat: 계좌번호 입력 플로우 생성 * fix: 콘솔 창 오류 제거 * fix: 은행 이름 변경 * design: 지출 리스트 갭 변경 * feat: 참여자 별 내역에서 은행아이콘(토스) 보이도록 설정 * feat: cansubmit 추가 * fix: 스토리북 prop 누락 추가 * chore: png도 jest mock되도록 설정 * fix: 테스트 환경에선 상대경로 api, 브라우저 환경에선 절대경로 api를 호출하도록 설정 * feat: 은행 송금 버튼 생성 * feat: 버튼 클릭 시 모바일 환경에서 토스로 넘기는 기능 * feat: 모바일 기기 감지 기능 구현 * refactor: 디자인 컴포넌트에 맞게 디자인 외 기능 외부로 분리 * style: Bank send Flex 컴포넌트 이용 * style: bank select Flex 컴포넌트 이용 * style: expense list flex 컴포넌트로 이용 * style: 사용하지 않는 import 제거 * style: fileMock -> imageFileMock으로 파일 이름 변경 * style: 사용하지 않는 코드 제거 * style: 사용 방식이 바뀐 코드 임시로 주석처리 --- client/jest.config.ts | 4 +- client/package-lock.json | 35 ++++++++++++ client/package.json | 1 + .../src/assets/image/Toss_Symbol_Primary.png | Bin 0 -> 925412 bytes client/src/assets/image/banksprite.png | Bin 0 -> 48163 bytes .../BankSelect/BankSelect.stories.tsx | 23 ++++++++ .../components/BankSelect/BankSelect.style.ts | 31 +++++++++++ .../components/BankSelect/BankSelect.tsx | 30 ++++++++++ .../BankSendButton/BankSelect.stories.tsx | 24 ++++++++ .../BankSendButton/BankSendButton.style.ts | 12 ++++ .../BankSendButton/BankSendButton.tsx | 33 +++++++++++ .../ExpenseList/ExpenseList.stories.tsx | 8 +-- .../ExpenseList/ExpenseList.style.ts | 19 +------ .../components/ExpenseList/ExpenseList.tsx | 33 +++++++---- .../ExpenseList/ExpenseList.type.ts | 4 +- .../Design/components/Icon/Icon.style.ts | 1 + .../Design/components/Icon/Icon.tsx | 2 + .../Design/components/Icon/Icon.type.ts | 3 +- client/src/components/Design/index.tsx | 2 + .../BankSelectModal/BankSelectModal.style.ts | 28 ++++++++++ .../Modal/BankSelectModal/BankSelectModal.tsx | 31 +++++++++++ client/src/components/Reports/Reports.tsx | 13 ++++- client/src/constants/bank.ts | 32 +++++++++++ client/src/global.d.ts | 1 + client/src/hooks/useAccount.ts | 34 ++++++++++++ client/src/mocks/handlers/eventHandlers.ts | 4 +- .../mocks/{svgMock.ts => imageFileMock.ts} | 2 +- client/src/pages/Account/Account.tsx | 52 ++++++++++++++++++ client/src/router.tsx | 5 ++ client/webpack.common.mjs | 4 ++ 30 files changed, 430 insertions(+), 41 deletions(-) create mode 100644 client/src/assets/image/Toss_Symbol_Primary.png create mode 100644 client/src/assets/image/banksprite.png create mode 100644 client/src/components/Design/components/BankSelect/BankSelect.stories.tsx create mode 100644 client/src/components/Design/components/BankSelect/BankSelect.style.ts create mode 100644 client/src/components/Design/components/BankSelect/BankSelect.tsx create mode 100644 client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx create mode 100644 client/src/components/Design/components/BankSendButton/BankSendButton.style.ts create mode 100644 client/src/components/Design/components/BankSendButton/BankSendButton.tsx create mode 100644 client/src/components/Modal/BankSelectModal/BankSelectModal.style.ts create mode 100644 client/src/components/Modal/BankSelectModal/BankSelectModal.tsx create mode 100644 client/src/constants/bank.ts create mode 100644 client/src/hooks/useAccount.ts rename client/src/mocks/{svgMock.ts => imageFileMock.ts} (55%) create mode 100644 client/src/pages/Account/Account.tsx diff --git a/client/jest.config.ts b/client/jest.config.ts index 51f170e38..5cdc6baab 100644 --- a/client/jest.config.ts +++ b/client/jest.config.ts @@ -6,7 +6,7 @@ const config: Config = { testEnvironment: 'jsdom', // 브라우저 내에서의 JavaScript 동작을 모방하여, DOM 조작, 이벤트 핸들링, 브라우저 관련 API 호출 transform: { '^.+\\.ts?$': 'ts-jest', - '^.+\\.svg$': '/src/mocks/svgMock.ts', + '^.+\\.(jpg|jpeg|png|gif|svg)$': '/src/mocks/imageFileMock.ts', }, collectCoverage: true, coverageReporters: ['text'], @@ -48,7 +48,7 @@ const config: Config = { '^@theme/(.*)$': '/src/components/Design/theme/$1', '^@layouts/(.*)$': '/src/components/Design/layouts/$1', '^@type/(.*)$': '/src/components/Design/type/$1', - '\\.svg$': '/src/mocks/svg.ts', + '\\.(jpg|jpeg|png|gif|svg)$': '/src/mocks/imageFileMock.ts', }, testEnvironmentOptions: { customExportConditions: [''], diff --git a/client/package-lock.json b/client/package-lock.json index 553386ba4..95211e1e6 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -57,6 +57,7 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^4.6.2", + "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "^9.0.2", "globals": "^15.8.0", "html-loader": "^5.0.0", @@ -12405,6 +12406,26 @@ "node": ">=16.0.0" } }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -17223,6 +17244,20 @@ "node": ">=6.11.5" } }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, "node_modules/loader-utils-webpack-v4": { "name": "loader-utils", "version": "2.0.4", diff --git a/client/package.json b/client/package.json index d4d501217..8c308b08b 100644 --- a/client/package.json +++ b/client/package.json @@ -56,6 +56,7 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.3", "eslint-plugin-react-hooks": "^4.6.2", + "file-loader": "^6.2.0", "fork-ts-checker-webpack-plugin": "^9.0.2", "globals": "^15.8.0", "html-loader": "^5.0.0", diff --git a/client/src/assets/image/Toss_Symbol_Primary.png b/client/src/assets/image/Toss_Symbol_Primary.png new file mode 100644 index 0000000000000000000000000000000000000000..c6105618f9b7893cfd027665c9db86a08d595f00 GIT binary patch literal 925412 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ⅅFDv9_ryl3gr9%Rs$J>J@5%+d@55N;SSSuuOu6 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

a!qgT8BRg_c#?m6 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

$E z#HTFprQ+Fos!2rQpNj`vs@!K7Kjoeu=bd)RMc>ij-RtCF!Mskrk!5x?SYnTKO?RME z-jSDAJHrlW@s?D}3FJm73y*sy5D@uDN31#-zKcV+j zFhBA{%)wzPf>sJ;m0Owb(!0s0BF!v-XVZqhRI_;Uo1pVQ&w~S%h>x%;)_m{H)w~@E zK&NZK$n(=g)?_=`)mo?`$ugVHGOkk}-ZJiz9Y#tgNCw_wDMohvE;X|6QX!*H5efDx zhfkvbn4{w(#~Zc0As!CE&xlQMLCyEZYm^6`X7Pg>zw0 z`IH#hmz8!M(P%Uu1V7r^jb%c_O2uwTqEuo9sWr6I9K$0tH0lK3p_Bf^3hR0cFZ&|B zQyP7)Vy!y$Z+5DPFdOT~#re}*+Vg|m%8h2$omy$v+O!9am+2Kr(E|bHWVK)=F3d3SzQAPf#M$Tf|Jim$+^jxY*CkmGlGd4_rB2+LbIhLH-r!Gs$&& zAe6FIS2^Q1cJ`GNM!c)?L&_`3RaDn4G%X_2UL0YbnxO7K_&9j8@5*Uuf9<_95p~+F zh#AIr(kac)t;X?#Slgq|Ql>Qn=`2148_M&B3_%m%uf#FH8qRs5U3$wk{arJcsz7Qp zeCWl*gV^=>tHyY?a|<^6pya+j5WD~Vz28^aU&Px_X4$_nntRd0WLMKT=ZFxZ^Z8~N zo78{QyrVkaLRA4-i2$g`HY%IPW9l9TvGC)pw{KhBL`BnS_LIqvwM8x8@sKbI>;fLsoU}|J6A?uI{VbUKtCN zoC`@oYpHW0v#wEPlLk)Y?k>9}g28nfdsV-^YKZxU9jj=97c511Ub>n#_zqJ~y!Vd0 zD5> zHLK)3tU9~5wfFcXx+L=4D9wFqaK-ZEPT22_vDLlyIe{$^RrB5O-~IN_OddJDvW_2K zID-;OtMBt6w0;FX3|AA{Q3<$dh-rwWe{Kt#ESR*;|8x@cKAPa<%BvSBdp{&KzooOR zpJl9<4mp0r#d+8)@ZLyb(KFKxIOSbL9lU9p9EuITd}?yVLn7eg#)+oYg!H%2CRI>z zmv*~$O-1MU?27cMjDaE8szOA7%P<~aiFl8GLD3C2Z*S1$<0I?pf5}#PDshNge z-IO<7k3(YnhvJIS)2$l0wWR}PKQ8c2@sy73=fQw$3?TpBVAss&%2e-@rdTM7q0B@z zSO*0otq}SXE*byK_ z&Xt^>b7=poz$(MEonZK^d_(goS;>AQx|0Xo2CVmZwEQ%mQkJQ<)}s#Yg`ozXSOq_3 z9gI!o57F)O<+?dyjU@?tY(@!2hhe4iEEfav+}lVNsa_57C6+r8s!Pxp21sUs)T*u( z%+=2WgV^Dvwy@aQ_8@Q$mK!n$JE~ZcIlM39uI_!}Ip7+%sYy;>VpAFwZPo zAaws~BK8_Jarl6Ze2_lH-&nj&-BCD;y54P#<-+*>LxfySp^}BVW;r{VKi>||xg1SD zaTtw;02-QmR5;pV7kEH<1k!%+s;9FBMl^Q83{kbv-X&XIy}6?u@HDKa^z4@YftvO2PG2 zzmv0H5Cm9GIl@6Azye~lk6k;x)V=MEqU z{MjZI(|@hYr-rlBcZU9DjR5OT%#?WQOBeR{~ZRNvhKNfh7_i5}*jV*Og40`ImX>O`S^D#{!ws%GC_p2&Xf zs_{Efm{&huzKkxOQs~fq#x|HO!W7_r%Tw~^w;U<-yc(-Yg?IBnt4sO1(io{lK$!fT zBzdSt+@Ps6QxX7>XJEg71n>C|6;3rOr2cTlPuhMr8uQWtZw)_{&4Gt_KE0?tPzpf# z4Bs~wUpo_rka)`t7rjN8Csnsjat-ed52(H(8c*7bh-*;VqS!qubWVXH)Lt7i`}d-m zEOU_!I*+&RI61>rxsrb`{5QTym&y1aC!_^l#c&tAn)qs^+02*^4zqo!!Aef!`0bNc zx0lt^Mx`j0G5y^XOF{TI!bhtMY=1fMeN6cif-hbIL$jVqY{^th-F;aeu(Y7c$5KTX zGmxBKrg_&Qtkj)YQ!90Ox43pljA(u1?(lt`1a8R4<6q4+RG(_vxTJ1?1G^qD^Y*E< z=0p#SBP=!;cXB<1ReZA^e3!U9o@EjrsTgPE1<}jUWwN;~ht7`bpgAahF5V|kOz~{Z z;3X{qpF;#qYV6JoL!!itQY1o$%QUSccM)l|%IkXpoiYG-~jKpOS=%=-;I3 z@_`c7Fibbwea7{tZOQ%?A%?zz~%#oD_`^66b^^4XkUxrV9TXZ zCLMIP&aE_@yz-3So0~4I; zB+OZ!E=apsVbz>w?$@2MJ~~x`{EK0mJp7KJrplXUvP#lw47@#)BB77;U{N{IaGLpz zZ$RR^zp!^EEIGAsyPbUuy$B?l`q5YJx9)!m3_L!Sy?~?7HG0vN{m1ch+LS@u$WK zaWlt2)}*=1(~@h}Y^$wu`%mJ}m%YFAjm_&P?MG@;GQd$G=8RvQ4dq!2-C{|Ku95aAFaDKvOTV9m%}Q)MPaaquyXl4a@QJTFT3YIZvV%tZ}6~;<$%9=lKP^1Hm+b z*BT3OQsY}Y#JX47BY(~OeJixJe4=EssgBhAiKl}-?iuSI2ug1@XD1Uy2O)2(Y;wKZHH;rRUH7gen0ZD}jf5u_eZsD-jCFenJxffbo#!IQ2Pnc`9 znV9*WnrRU7PR0!?qee5RU$N{s_^w4?slIZReY%>BVV>ad)>evY;2uDMcky+ugXW(b zAyNW-G$Jo)R+Ka^8HPvF$1i`Y5uDgxqm?@V!GwE-!zqOujxvq z#t!pnOC!vbNHJ5PM=l}~f$_oZklrQ-1BaCN0Xkmt8?JXb4wJFU%17ogN56Bw4*FzI zu&c3!o6n^ArDCwjAWD%(>5m*Hb6-i=7G~km;Rte+*T~l+gcXQcQr-2yxbA1Evww9| z;#RQPSXVN%g&r)F*t8vmbP6vhB5eJuM+5m%)l+X-pJ$;3rm#dVhC^H(v3Xk7AAgH+ zL&fM3JcaDhm0(D=ywIck*%M^;H=fYUjK=EsdCIL|K6u7b5TRY{G z{V*D2DWMq|6I_uu`)?Cn)PTQQaF#L13I+nJWL=zr?Kh3_!jxAsc?7D&6E# zL-h=gU}T+?Qq=o4_Au#*l~|$vu!pCt3sS7Dl}PV(ZHn~)mE~*gP`D6Bv}Z%AZEqkj zmGqC?e={jDYhz||$ecuV4<4{l?|(jI2mfdD5)7v_rq0WqGeZYYE7V^+>;IXF&G<;O z7nJ4gnebgq2R{1K)myyFmNoJR;J(AJRUf5LmlffyX^l>}`!TCF^+gRe;EL0TYeLB1 zzC|b|-QKo|hil?*B_>CNQ#sCQYpFC!$boM*m^HkgQ0_Y%qxnx-JDwydD{q;ueFgAS z@@}nyD3#6F-^?&n!H0XKHSe30i+U&jOoGZ1+fsY@;EAB7;09)1eiOuPG{lG%Rl&r| zm@8dyb>Ckq3X#^Z4e1lLK%qG46&nSR^fRMubiVC20RieaF=qW;&~!GVRS>^_fzG>itIF$%KROnhvv+t> zC)BApl*3U~>~ne1u9t65#VzL#S70zXKxl zl-=JG9w__A3JuLhbbx=cu7jz1dShY{*f{?nlVyse3l9=jY3F?pbObPWP$=3(R=#Ba z<(&$h#Wm>X!M|TdY>@)q`P;qMAS2+5EcN*zw~ME&QzKz#t6Mw3;UsH!2j_DG2CHv^ zB3@>*Ykb=loQLVS;L6x57-$?Yn-F=vMRi%n|iB=ECbW-riRdTL2hbH z`J8nTRBSMOaLvK^yV1)6Zqj1NTTcd-zI$VqeE7B2WEQVhB{wO~9pV~nJ$`OfZ}x_5u6>(K8}A{&TLW|nt(}mh zJ$tdq+UX!wn$Jvy(k3m)u_CM5KO_YFkcMex50H0COPa!l4@#c_2=K0b06fY68sdv~ zzilduMbPDzFBRfGML^`o)KzoTTa%#&{Ybrz-?QjYtE7=AH*Qfw1MvpJtoia z0#2q^7kNH3Q*R1pIM*XFDxW(uOVEXbNIj%tp-#EhLSI z3{iS-z-*n#xDn6wswBc-=(2Q9;07)7Le|*d7DfNx~=(2eX=X_JwS(2K|XO`P^U8 z-PWfLbJ%@xSe%+$)@O}SlgCddcRq>~(>mtUkNG4?SDcY_o-shwKM(g}0dh z&87Y>*-qcIv3RYq1q^o&Nd*Fvp}~7~jPIWn^B`YutY!I;)N%!OXoF=SR&-;8Ko`?G zYiWq%Q=j&Y>D;ioaP%ddMf1fE1fmzqlcNx1wbvXaZx|J{ZDA5Ws*tmOe#opHEbbUo zc%z<%twXo;RhltOoPPZ>fT>m62vQ(`85Ueyl;NEZXN*vU@C50?!HY|w@r=vuW9xgC z?wKcIt2$HOc-#Lx{YCr7g0QVi@Y{h9nTY?13hJP#>p!|JVs`m_AV3* zW4~Cq2a#*_3-yhlBr%(t724+0g;T&jlapzMDv_-NQVUd1gG_j4re*y2D8%iais=49 z;4_rxo1eW5-e>D6UMDAMmu*54PK4Hn{~8og0r9o~ao*Wc#^WpNPYv0k_RWKh2SmhY z=mdVr>KwRQvY9~X>CvX!5ByU})Q>tU_I4{9POpNF?m?U~fyHvR{w!7U#+HLqo$NY@ z2Mfi8UIDn_>rVW;u~W6b*AG{?#hcVR{1*Zy{hzM2II)d7UQc>^LI$i{}44aGd`qw zPNFS*JyoE_R6p#RxaRuD)yeF;=*zax3Ob7}%~RrohZa%t$4aG$ADlDkfWp^su5}0U7419(W>|_c4n-QNJWC>gBXsrQQ+MK#080iV8c4N}hdD z<-9(Qg`)(^%`p+P$SnZ0J<(1f$@RpVxrJHLK8FAz20w5&E=hF_FpI2|3}s!BhvQ4% z6N$E62l)bWL(d1ef#u5Rdqe5 zOah!*4(EjP{^nmf7i13CcPTj%50|nGV0ZwSp%c$(uu6wFyND4tR=omzbW&-2UI0t7 zJ6yx!r(CEQg*|8%?zOO&VE!14FhJIlfD}POfiz;==8{hOGQdiX9?-aVwMUt^)JB-d zJj>i^TcC_L*yWyV)~_$vkyecx%(bo z;TVOIy)3zvjSLc7WU&*0C!(&{E%XuussGIcX(P6v0&Aan%!m$KtPnyg{#ZGfEd4-i z*FpNh{3@$(x2GJV^P@I3r(X#qsNQ9Q>H;jQ6__ojbsI}Hl>vQefLjeA* zu@q8^1jovcCmt$w<5Nks=Rud5`fX+tlQ@<%uhDQeUFsTaa!HCk*c-1HuAW3h-H4pu^lmmg*YCMk{N=+X>xU<>&a{9v9+#v&MYn5M6`C+9`+)S) zb%TuK-LZn(eOD*rsJByYubnIF`vR%8ob4=zn%yR~MoWJ}Ni(QK4HUFs!sY zmWzI1PFyfQnv6;3Kz}@?R2cb|CK6SxvoMS7!uo4&oY@G`WoHB=wy5G^hkPYZlRBM zByUDZ0WzzPp%~bw=mv6VCZ7BI_o4L$iPDqHt)qbrmA-2eP5M%e<2+$ zxc&uu46C~aypC_;gE%y+pRq2IW~MU0CZ{H(CiV099;rYwWO1zB?)Z)X=#==x6q z4j>R3bqNr9GyXIK+rc35qxBVNYWL-Z>s~&#_$+>xp0p5%OaC42&jjsj^PiptLqbPA zkDZuoyF38#4#uOOg7uu=nSHWH^xcY(Z)P1IK78fyi+icR1vtWPWlCE17T*TlV;L2o zvR-pKNQn!XfboQJo3?8Ov%bdtS(8d1M&IKXMDq^1!~fy>t0^+$%C2%*Vb@HH#{0Yh zV8-mxQS_li?o{TDzR1xACu^rv=V#7ujTc48iRD%GrRDrfCGgJj@6m(DO3>P$LK3?B zYTJuI)$C$UjoC!2cTdk9Ee<&1`&}D#L>p1>y~+22zvw1S*Z-{6X(K($+4_q({N5si zD7Fe_m=~;R|he2)L#@#w$h@^7JdQX7A)0}4vpxWlG-xFe?7Mw6ES#3z$R9^nt0z~~I zn62B>MIA7)pRX&qt#Gxz-l7A{D#Mo6f5<%AF9{a$dZlC_;~=R&0F3mp^v322)L-NF zrT)|mcsA44G8XSEH*ixyO$7rP+2+&oYxKAhl{3rx0<3w{mVRgDOV6`CMB$sC6U9ek zIXb+gf5R;Id3=FY%%kBauLQp^c5=V?_R(K*d*STnN%jkhTHDJ3Xp+(7o|yR%@hV-9@3E*$`OMFC-dD9fSt^xvR&Qu_FpV{N-!t7)5VUd@NY{YJ!@Vvu zsNoR%aqE5jm5alNe^Y%#cih4}TED)a3Pf$&hj)j)*%L>31pU-Sg4eGB@||FiYwh}I zon7|jX{p)*Jwkqwd~37Ud_)xUPDWiTgNu_@-3x($bad>aj}&eR_ls(NmrwfyO3GH9 z9u@ zKwjayJW5AA%AIJ5JxiB~b!qu`f%O??0gi&rl{*>v@6o0SBqv&&!g!9IQPy^_e6?`) zUyN$TD9j4EbRLe~GazMS>0~u;+MB-}`t0=btv2+BL@KT|Gw7u4i_K$stn|pX6<5X@ zvrR#}no-{&nVe=9u<)ks`Ck`iHzL?lSK3|qFbUq*EQVxo97Q#`uD<*8r)l3M^H5@^ z{nwbdZ3-;dr9=z+a&|Gg{n_uqzZ)b+RxT6P?3^Na)Er8d=*Yyvg`~XR1 zMuDAbB|2}b)T?spt+Twjb4OPWpu2NF`Dhi@R)~d4VAJ*?4y{UHn{6d(zN`&AdlwQoQ;xI@ft>Z`>Kj$3{s7=TKbCD{JNyrXc)( zXE!$H|3ZRE5`LjvWI*J1JNxrdSmbr?F9`J7XhL_g&ZreL%`uLenc>(q>8c{xr0a-> z-kVpF9muGcTI>^i#Z;PZlS>upWvm<76f$B#>v(^nG_}=s^@G7clov9ddH(9rE8%wm zh|H{^N14-lPaJI$Q5@W>su{oiIsSnXh?=c#rWKlZUuD?e=hIS^>Fcdnuaw>DsfN#N zWVn^=^7ZPz!!F2a~rPe>gQ$KMBlHfg9-e^8C_&aFs>;vn%iwMzd%7XtIw5Nr~fH9|>} z^FF`tFW~6cmW?9d3RAl~3(boS{eUIOZ`+X-IwP`+`Q;Qbb=}hE(>K>+{*+nFK7J!S zn5w=G2{_kDl>)ZtY?Vb3O-CicQ~USAD)I1^II(+6SFn539VGs-`(9FVy@Gtc&I>iwn?9zV8Q|JPFLq_%f2%4W~sK=;!Yf{ zy=~YweBxhpZ|TcWOe{kuEG~f=&ZutfWDw!FWTrYa1r%QweT(KgZAPeqmA%AE@D>mT z6EwyACSE3bo)K%{Hp++xa*~xfrN8dgdsp6En0)syVX{mCqzBfFun;b#wtm(L-UWfx zm?UEnTpRCFj3<2;zs8tB`=z&-IQ4+@*H%ga6Dzu|2Z5N>&Xu~ows|=}(lCC-{{nyB zu}5i9f+}61|8eLsZ}7U|^K2+cV9R={IrHP46Gam@sf1~EclHxaG)ih|MTL300f8+Y zJ}rL|`SSe0_nekB5aA{M`b>_q;NyC7ucLeuEgQMkuv;uOJpAokhT)32>Hhiz?+*ts z63$H&u3{(gFh0NC{Q^hWIaz(Er?6$XyW}+seNpV^-#DGgL%Hu;b%>Dlyvoz>)-BOZ zYq=HXx2y0#f@sgp>*%W{#lXrmurd~sXd9yn8=Knw`83LjV`0SKww>IDMnnG%T0DZ> z>{FeI8$;N%qrabhqnW0Rc>_9%X#HDpD#D#VXS1}sW+e@G-zR7o__uq z4Nh}Ev7WrLK!4`-Li`Y}Aj%Q75LkxJ#F*{2Zmxr2=O@!;jzF9WKtGMr86wlIeeMag zOSUz%d1_D@9-t?&v$HV$F@TRFaxh=!BcW(TCECEFB`AU7(=E!xzpzfl-p=u-dPuA4 z^rol5_AD!wFO*XK6I9-KjM2^sMWq>xU@IK2+RTi3d}r^tnI@!!aJj#9-d)z2%Zdgk zQ?rF;;hJ}fC^-d{Rhdgs-gTcGmqW&oo8&aSB2oDcIaf_>h0Xq08zY$y!~XtzVz5%> z_*YE;thD~IqvtO(;%D8v^S5*+1+vE=02?thAcx?wLPN7o)8v$jbp=wa5T$DCEYP8` z`|Ce$(l4H_dyRwv_aQ|N-yk9X^l2^Kc%!`4ZNoG(R7X<;=)W_iVF$5GdJ7L5jVwQP zFRv+r$chmBk0tM;pGp{g=wG3^x`tM8{(~{-^z2Kk$=KUEDWgNh`-(QQ&u+gzt>p{u zTd9G zZvxFxMLc)_Nk2>>B=|mHL-7QfZ@H_zcLlCyDg@UB45aVQ+|#m3itMV*sd{rZvVuMA z!(H}l5{s1r5F}l zdU|#Jk@FaIS!wAx!(T#J*`aS6B()WaremQ*7^ScxCd*3IZY=4a4h8T!lP4dC(6y?A zU(U*J>HfHuH26|Dpyim3e0gy8hX6%>Dr}ogM>6WUyZ!Xl1$8q|ZQekQSZ03cxA)ZM zQ9sAj1~bL5lv#76Sl5a}_7(N1`S(WnTWKnlgDqw6RL7dQKx>wN9H}|idV%9-rEtyJ zRi(E|ElvM)l~p#VUR{LAPe;HHuXm0qJqqT(vCY#2|NYA~j$+j}LiN0_-W`7fGRFk^ zm2WQ|R@dv8;3f39{)+}!kXoGS9i=>8Uuoi zS$@wrV^d#ssWht8wW{-m;1AXLLl$I@PPfe${@9Wc?s=4>HYam zk$1TY9ir5P!emOkuH@3twzCxvSxC{2AYIN`w7&2xHpC4!w}&`dIP`I&%Mrb$ANbLf zHZ6mbdo=a~%i`SqDI=S>_*Uf$gU`a2aDxP?Jc*(l4vFKDXM)03$It*m<&}Hz8zYxd zE3cIgm7J|NXm_gjcsf@e@ms>I-poXsA=Ief{!8lAKu_=rtv^cH;}U{1&8#|pY9W&q zGehHeWkvA;@06jy#Bh_T2P>O_Jw7zY>HCCLVtR*6JmNlN7mo_wJMG1!gvgZ#p2l{6 zeQ7=$^x|y~gyqJ3L$J}i6?sntE#k-0-}~> z@X+#OW^+M{`pxV=&xp3+(Ch0aRM95--L$)uwO;0}Mcd=rT(k9v1l&NaEZlbbK8YIl z5xp@e#_IyZA?^4WagoyUC1C!C*cMj}?Zy?AR2=Jx%CQbh>&RNG_Bn+xCY#U(vr7Zs zKY(pPv+JhRc#$gkDcDNEmU^|+_g}D>R@0@usrmNy=rD<*-QtkLeo__BAGQ*Fl`N zB7DZ&G(VnYWI<&>I)SIHIe1>6ax+I0!{!mXcn;k?cn7gVFl4*^S|h%}YM&n1y>T}} ztqt>&K4c+7B~2exkg}j`kKZI#hNC)bg>hYDy#c{iagN4YW)QV>KR74c2z1kKTF==a zJ7Hi_(Kh|Xwa^hT@p@bLK<$&`k>FTKGEy73w zgy#=abwb(wH(+jJ!9iJj`0T*}u$*@EWX!8Z&5+W%3!esq)! z^AmfUeh9oK-)zit)$;vWeqliV-fmq|g^So-0pyehvZ62JP8OO!pUXXa#?qM-WoDz*6#0ivE-ki)9XI81`J^+QwZKO`ZB$DYdI|+2BCzz%2j5DIShP-Z^U(I`Fn!unvRyj>tlB zPVq(eC`cTjhzt&fy{M<2yM!PUl$LHg(gxi5(0<2Q;fJ%BKBGMZ!(2AsQS3mzBjoT+!RqY}lZx+&)DSyeglJ zWo?>@X2|eke8t&|l(Lyyb1wrnfI_(sGKxRw6#vV>bi{`F`UItNIDBCmLDfj+3iU3O z&UsKlFn>+o8^iUf4o!JbvG!F;nemK7n!35r9eBfOndF8C zSq%k0OF!Wk$a+eg z95Rmc!)xm&rN1_DDDL2Zr?9EUjery=a%KgH(EH2W?Hwh`s58*=*FO@A2T_)sJB2fk~V7jrjH3veQPGPQg-MvGWI;(3)>Lqcl(mf zi*Lz%aPRUTvaR*~J4eNQ@K}1*!noXC}RM}kZI81Qy(cl`#334aWUlzGP^hBr zc`*Jz5l0H3t+d1h2zsE2nH?qsv9@Z5xC5u2+H97~Jrte14h@$9Eq8g!yJmPxu?El2 zBNWyB2?SkmwoqiwIC8X+-fEaPt;bfxQz_cfDp33}@CPHpG2o2p7*}NJ-gp$}8Z6du zl8hvHi2OQqc=NdbeaeHVN*&ilN+6tRF@SWopIe^+ zQSbwu)9W4%Y4@_Twir^wzz|ono#{>buqV2X4*if_O)1@CQk~d-d=J&X4J9rU%|js| zfFZ#x-LnN@4RKUJ_7hO`CFk@(=HE}>wapq)Z)X~(B>30n7jZ7XGr}ID^+hPU z?otzFD5S~%zrKP7Wbe(qHKxreqmAeoJ20n2WBH)u}7=_{q_?gk!L zQ@7^T;%{*>Q1psk+&NyUxeiy&Xg8*Ayh=@`iEWH*%dF_mg(A(3zi`A=NR~gg?!FYk z9c^QlUb$RUH78A^T-v8dMdJI19>~B%EFMU@hw>!te@i#I^yPJL<jk`m-^axD%KZa#qT)L@!^VIkWot%s#7ba(l*5S*^Oi+nG90- zC2tNvQDh-H#^ZI})aL~Vb`}FSw45q%#Q%A&zHkg@%4d4nP~&ecL8{*7zy9})IPnfx2%1h^X;+IgZg*wDS;^2`6;Tws7Vt3QHo#sIF7wFSZQ$Ys=aJ3X zpOEQGBeqL85nZ8^7(Ob*Pr1;&p)e4q!il%vxE0@xC#)a$c=z3WrssE}S25j!Q;C{3 zf6KU~Pfy4Gs6*e2Z@NRWt84yJOi85b*p;rKQ89+W5|0#a)(yn*QqFys>yaH1(O`S#%#IEZCm2CjoZH|LZDvCLEKL*%p+*4w-EcYc?$6d!-3 z-FU#K4w(y{h82UlRT9X(t*;gzCoP_HA8WDlt{HWB>g6?U%&b|ftCea=66K2#(DPqJhV8$fjAs7hXWss^=Nh3aS2F-UjL+e!S)lzO zKEm+d@3Qgf$SC0WRgrIzFIm8Y&rX77y(>r2pNnh7MHTXfuzm)*gsJ<;gg6$5Lc^|Y z+lP?2R}Tel(aO|pW%Eb!MRa~~*ToS8nD`#Y09=eX7)vtU+pK0*gVf3|t&#$0c>o<* z&z=2ezkksks^5>FwbK9$@L86y0quhfDW&!6?)jPS0pO8>`S;>Pch7=2?OzXi;z(IJ zmt=48Wl3-U(^O-%-%zCL_AJmp(^XR%y0kqy1O@k(b+> znVZHuHUt*q>zedxrh+}Q=9975PyX=J*Z1yrU|iUzLMScrk7gr+3>G0BPyuRIr^S}5 zp460FUn?h+Ji#6eTI(-AZGzJ`5I&$qAVCG?9q6Vw^@Dr!S-&5lHL@C1dA$048S*$PvVBK2k)--hW z^T}m=HuGpyO^HlV<1Aw#l#7K`5y-(oU zuCPz3MzrLN*bu-43ck!2kUb~~iZrte;*E}@zS@JI;T0{P^WnXJut~t#< z5OBjTaF}f<)FRp*-1nv21HU0VhWwL3GfT67lQOGVuk3ldN;4q> zQKrmt5Ghs7cR4_+$g5gws*_xAnY143OJAO3W68dq$i)W!dekL8xD7_7?=Mqrmkiaq z^-Bwquu?U1P$jE) zZac>r8}MZcI$V%7b)eT+moq*L9zX*y(0PJIF5k{};iE~m+Fb^WneOGV7yUz@{jIPO zd)E_sO!nIQPM?gY1m2`_wY#WISFM{?YnC9|EPx=P4}JVCWoG@8cgchIf!kbvY5Bp? zP}kNGWP4qa>xD~0B4xDvmf?TM{H?i=_RL5R9IR05>Sz5h5uZKF!8Sw=K;t&6t#7FM zgPuKs&%t4-f`57<45@Nnhr_&k-?%gyUp%mR3Z+`FcSzGtr%3~nvsqqAj<~2N+T;wj z$w!aRU0vrU&XPYyt5=|PPL`v7#@#sZRG(Al(oW7^fZ3?$e%fmi2sXArt~`Zme6n${ zsINHe`ktT7lPj=T^D+gSgpI*!s_Qa%^wL(umDyjbfP8cN;;7u3x&M`F1-<~=1m!$f z=k^Vcklq#WHHgaGJ1akV$3VHL82-my_BQW;;Gb=~h_55Af5oOvJw)ex+n(Dth0NQs zavTRgvtk)J-HCrn{NR+J5n+O~#goRpCU4Ee!f6qMW@F7CF;tY{hu82kLCVIqS1>X% z&)nHgnVWMhQ3yD*n6-X9vO@zpC6WwV{%V8{b2F>i`#Wg?9*1h*rjd8Tu@-8QkHtfy6ZsJL zJRA5r^7LknLMGfqR1me@J$!2ve`Gj{5Pq@*-JhYWJh}*`1F`{CBoL|ubBA%2Ktk=D z!ifI~Xj`PyfCY3&$fg9lTDj^xEG-@yf&7t=xp_rYEk-RDVU6_g>7IC02?`-Fkb++F zUO#ooJ&Rs0XzSa+cKtRxHSj2c@#hcTxQ16IGOxJL#CBFw>Xh+@7q-k^>RD6PcS4!* zr>k8JIzhO$Pb6wqm=VTfwR|!-Y}N#-e>zE0t`bSDb^9Uf#k~q(tG94o6b8pt1w(C3 z!o*NfcR)97fgWcL3(!C8D|TjlF(z z)$&D4hujDHjeaL!H)#);9m${6iev77qkRo#>j};&}l_lq)|BQ}A~s+048S%>(BWh5{6N4-a_sRB(^=THDdjIJX5x z)vKibh;HzV*94Lu5mr-Hf+vaJP`?;LN9kr>r<$rn)Q4^`n&sTwOEdT1{3kmIY%%M1 z#NUJO7ENn4c~p0$jK-}*x203qRRLPrVTCf&|HKtI^~cYuLa>gFp}L`>-s+#~XgRq+fOkgE-ODO_dQeMb}ol?4^WJBo4GmIznI3avTdu7_rb}UPq$L`=m+I|@?qv}MU=q} zbR#&@m1IRbMzExXEX+hz-s{Y$r@E$ZUbO8~dM+0X4fbSbJUX-3LKVnZw9@uhfcU5v z^U%`;hk1vS^{>Cj{8*G&`g25uQ^2X3%*8NH65kM6zZF(1)Ja+F)q@r}n`^VBD_~A{ zpCt|WJz#Dbzdwi%dqRn=%B3ft9y$H?qTFrdxotGWA2mt*2~8XJy|Z9CiroGAz~>H- z0e1fnhj7Vxq<#C75QV|o_sU6th)bXD7|-=p_OR7N|ZJZw+Wpq}eW z$n%km-I4SC(9@*Q6U@ap`U2K)^#5zcXf?+F3Ive~=FwBjoO!kq1JcG?tYjy$*RC&X zZ=KLT@4pttNP^}tg+^(vm5#ng*mQ`{csR%1^VRSyBWvTD+BvcvnM$NEa( zp=qw0x$Z42KJcvpqi7o8k|M@<=cwF~%9%I;N{wuM`N>SWkn9Y96GPCEl9Vwo$T>aQ z(p_B3dv~8_=jSO9G}aVl#J!L}s456?2@JLQ?mQ=~JxhLoeYSGuGv7W`NLTcR+d<-@ z^_2M@-z(|%Mlihy7vVf)NGZ8Vyh1gup+g|HX8WuR|4pm*b1g$B4U2bDF@|qN$%#hI zT^pRBSV*Dgerx1irD1$Ym%UEN{HW@f?aWQAsD1^fbCR}tHru876Ivub@R?C&Jk zYBg30W}e~pVKrN{wgoD*?lQj((%7NligqP#xMj;Ebx3eq$l9Ha+Qz4lT?GQf1IayH zIX$bx5>;LR-;wwcD#6Uu4~6pnC8zAU51bY^O`bn3*mONmsQZ1(da#TCaK+NfZdAT) zZf*{#&C)qE-WB#^;fvvwTVVlDe^Rn3n-g<0RsbJ&-94(T5aEo_k;VjE#yR%X9f;yv z()y^?GAfgdTQypZnL7LYK2Y9uM1JiKEZ!AABzPU^+Z+A7Pq6w1ag1IwhSXCN=&aOYa`f^#A^klcG|j zgHsNb%9)(XVK(Jdcu|q_DTkJv4>NNZIw0qAir9*r4|52yIh1l{a+>27nqh3&%xq3S z@9*#P-~N5>cDt^}b=~jx>waG;AHSq`TR%c{ScF{^!qN-jdEsNUZ!h7yR}$>l>l`(0 zQ9*V*|A5=|cVih}jAxL9RDg=bnUMmR`jaabJU-gk7wT?Cs+2^GoZh zsbVTIDNu#gF82AJj~Q-`shHxg3%l#ILgB2oK$Y4$Vegwx6z6{dOuT0maa?)Q*JbT~ z?&OMH82cE;^i=eRrK`s=Bo+SoORj=v4T7dhwE~l=7z8W1M-zf|bIP1{Wd1s*#d~x| z%?}=${u0>$9Zqd(2%O5z-S?>b{y)j=_y2!KM|lZ+|1j7glQ&P5Pdi)hgtPQ@ z%S66TKkRIIG_))cSYhQNRa@A0_k+Xsd&{uXM1uXpj!^xIis z+Iu&ZlN~>~r!+XOUTKv%C&KmA(ZIzgbNfux|Cl|sOH)%P`;VOBygb~4L;5=DW*(6m z--4#J)B1>7PmWTGtN1kpgJ<8>J~7a7%84>C zYaDPj_7V>UVfUGH=92B^2xS2LGuTQ^FO5s2QltzIp7J=hwj0F zlX!5E>Xp+4lv5p%0z>H6-I~3uLGFOt!x3QeN`8(BXzX?9Y)w@u3Dbm2e1zy>kK9-0 z7!Kw;xN*9L4-iMM!}NCHNfNh|Xh?6Ef&TF&nBVi7O$Ccz*f8$#LdkweyA+Djdv5Xf zgv(mc>+6|Zt`{ZQ$-EYju)jrTqD_U)s~@tsMZ#4P{QGr5w2&}o(~3hcxsPxVF9i&>0m+2ieIlk z*WCcrDPDK@?-^*A6h&Actx)%B@yM7qfn$~JNcI~oW)TFdDQ$0sv5v(xzu}{;-_>(rd@}57sxjN*${(Kyu zOZHVTAYZO!OfM>D=(>N?wVEf~zLy_0Uw5#6cP5k$uwe`FT>LNkyvl^3R(o$8HwU=h z*0kw5N*(y=Q7r93Ks7se1$lgXROPdwHuzh{{U&}JYVwjvdz=q>|8cmf#S_CAhlNr= zWjuTLWqkYXE4?#8h!qaK0;9^qQJz|h<6CV$M!5%it9jBxta}|Y)2b@%|61>hMr<2< zGUi&B1Q;UMMEW#kD5K)so|`2pgo}VD?AXCYRko{Vn71XK9IuV~`7JFl zxg*Mf7uq^z@sYy8E}(3Am!LXW+gSLa1@hpIH_Wk5i3s^wwVw5IC*;(08Nrb?NGSNC zU~}I_c0}sMx!JbgR-uQve4C~>+A`O=$dOan9~(yF%%fgGW<$h#;E2dMUtA)ow^q=C;u?w16>@HZ1}m3 zOhRY&w>{dY!EY3oEBU)X9=AN4=OsWV=9=01hRHv0tIev*U5?1*``$-HaM}%$;~}pm z-sRqs__G`F%Pz1>*$8iEh$?b9|0NK~Q{rVNHgyB#DD}&s^V*p(5X&dP?B^@OyV8HJ z@$rJU{!8+sW^8jucQY;MVu5p!(T`?D-J2BQy_LMJcxD0&HA9nOe)Xp4ku>K`4*Yrn z4f}A)B>D|A`oinz9XGggK|IU(-=O?Q^25W4c6=;fLM0_$d0G1xRNiX0ODGr}39bO) zQ@Mx&!4e%@1N^F#GS)ZTvNM0XRqR7ZcW%HriLvr<@X77i+5T^Se@bV3e;CkzABy!aNcg%F~V=Uew(lJBY?Nqui5yl%hELBSaDAVC`6@|eX zlxw)d?DJZc`f-kSz#7j9a@>uo28M!1NO(<3udNcwy%SXS%DSJZvTX5*;H9>c|PtZroTVhH`Yweft={Sn+b_j7| z%6O3WnaVV55?kI!)@Q6`Iv2e*;{m;AX;RFJ?w%lOz`j>>tR-zpR#3M91AU{>z3;yF znC&Y$|4SEg;#qX3FvvQdwm98#WM*|auPC;`@1FbT$iE+5!QG_?7m_`7*fm;5or;EL z8@3%ID6UBpp~Gp-vO#SHAzZns?`XP^8#Um7gMBo8QCt5`?K|`P+O5aFqI&;jF~jQ- zs>ath5h?Cv`1l=QLIvhnJs&0UNPeK8Ufrgw0}hh^ivjX0o1W{u8;~uXfQY@~ z07XU1y>~6_IyYvpH`Ec~EMa|O$Mcf{)mK}R^a^m-@mQSmZLWb+{~l>x(Okzgi0{9( zg_92qvVw_mbXXWJYd1z_r;fVDd)F(%8c zO5gB(s|f`fRmDTzDK`z>woeoz{kKGf#?|>TEEBnjbilAAuAtix*0SB^e>^m5zD^kk z=c9xpRS|s`c5^3IF%1ADmUgv0Kv~SWPdFtBN3$ojI9H_U7kN$r}f-7W-#CDiUXK#WAL3H0);K!Y5i?je??%r3wmA>Vi+Z0pfHg zUI?p1kL4P<+H@Sb24s=kIb1<^P9Mkqh@^71w_}jBdcG3bXrq4V0Du%VhXxbvvDgbv z&X<;!#7fEs0t~taMo+#;{2mX@iR=r8g(D90_tqB|P(5^;9Dc_9QUp5Dkx;o}n|;%h zaNu={!yH=Jssoqw2a#3!j= zt#*@>=#A@mMYOY9o>o1;#92(5c1{jF^L^Chv_$aK$dPWtaE&S2%`=4weAqlj2`Kf6rGwIe?ag{Es^QVsckhuiGTSyGshN>ZvR^h(&UAni%NbKFsJ7aO6=7ga4 zA2dW+6dio;W1Q}L0m5;E(nuZJ`xFo(^(beN83Z)KL#Y{LM94N#Gz(af znEW(qRLqlJzUPR=ORv$V;FZzi7VO|bFp}d?aC5!xxj!;e0=tRaFXER~3M|!`mo4=Z zi`F@g(wSeq^T3H2_?cW&{J)2pj@%#Wik>@7IH1AHKb`NpY>wADeM$SxV7~6?K-=q- z@G#|;gax;OHjRHTb@nTUFFzvD(`(Emk9v_OIBZ)%nVf8!Ez}aF%v*-FjKw6Q{k9@&0Z1N{U-*E+)<)}R6#Gjif*yZ}pq~9{! zfbG@Gf2z6n&Unz(-)60W>Ajl3grg*Gr(^9wxLO6R%8{EdWcv#(L4s+tvi*5Q{o8^F-v~hk!-zuaihgdEXRL zqx&LaM$&Ry5D}@%vZrk~Ku9EN)qZmoda?N1BlCS`;5W}b18=Nbc}G%${P-&zkWjs4 zaRBiBS0DoS7kQ-?qC!Ul5N}d)#J&oqYUx}a+f9dIe2LzhKeZdYZ`vZB_Ub01+anwl zP#B-2picvNX3Wi^(qiU>rzN(B23RT=&mlK>PiaC=b0YilGob~N!)Lv?s+P)WOne(MdSqnLc5bHO-||c3^*E+Xd1fum4}%F+ zO|pq>1>X3W;d55&P|;~658>gvQSMVh7;m+lI`F~zya|Mg7ljRPn^Gzrcc<~gO}IjF zmiP+1>1~2=k7aTfbJOCG2|8>({Cx*>NN8SbU3zmgF`I#|3j8yNvWF~jzm!$~Me?p^ z{YZw2nJ<7yInYO^qkrlKoSE)dk5hA-8Q)e-Srs@x{^DUL6?AA7@?Tr7CzzX^p9bmh zUnYK2aNvVRMd`WOpOQX_Nc{2do0axMVat`y$%1%1)<@wvrz~ee=DcAWnN&;oTg=FX zIwRBQoSDRdtNTG5(uey``CfIaC^DSFM%(niKCGb}kErJFY;{QavUyRa5>#BS$aov+ z4g49g$*nmkxR?~te?%u zHXO2?QzuGxT6(0{_@lNG5W5+AAKzNA23(C7P5&FARfv#B>hNs&w;?y|`zbo5q#Z@D zc$~M5xJVdf!;$O9GuLX4Ays4KAGmYr;6NxW9)cJqs6Gx0=y zqFZAErBl7MEDrA9r3pR|{MS}Ci;a^sU+R{yT+6KQgz^m9U!9V|^93O- zoRUd%G3I|si1NAF8FV)AO&yLZ>dEmu)cm=CenCVVZrt)m`pv|J>ZZ_Lt?DPsGa55; z9fEGUORLsyEXnYwjGBeRcvUyMBFROCd$|#n8w$y-y;v)`vG)@XoV0Xmxb`!3>cdej zlX00XMzV(|uLncS_qt286n(^letp()J*)ipTG46DEuJ+rDX)J6(Hl9gmF*dNmCa1U>O zxL_;8^Yt@u-O9N;UfU`Du>VC!8Cl+UgZ64uP|wJI?vnA<6-^~RXTPkPt}?pS@uIWD z6P$m&6Mke!zJ750ySNp!Q*$x=`!mf{PshpbX@0u5(WzsDALHkeIya7a)=i3cyPc}6 z!@jl`_4oLp&A+3reg)->Ji3`CDh0&}scc5; zVqqg#HCmq9!$E0I=US?Unv(IvP5@ovWj(;FeD@emDS(TsVjnD-SfS$Rw%_{e}59uxWP)R-t#CN9W=D%O*u!M;r z1a3#Y&35AbGCERgxFsBVZYxr>Flp>R4z{TO;~4N(T@1dyj31E;@wky;^Nok z*DN*HJG^zn80Y4Gzv`YhffcYP{_ieJdKld_2aV5Mpc2n~d9|2(HOr%EkVCJV z_*a>$Q)->{8Ml*I)2T~ynk@AhfNNXG5op&ZbRNcNr2IpD{>6~y{wC`iHgtD)eY)`7 z*DVgd(1ysLduF%lMeiCPYtOah=G;*%VxL@*8~pc0^=9A||1y&Lz*11a@_$r%!^qoC z*NXSPzRLf4&pC9j)(l7?DVOFKvl!XncddL8f(cacKeqLVJ!f#>GV z(&KS;G(2_&lkG^V*uM1UarZgZ`har|20Wjy?XsNXZnO1$&q&QXG!GzofOqUbtT{T1 zx&KjHgkbEiB22GiLaFhGi@S%z|69P~ak#Kjo&Ati<7?bUn^?#G7UK>9e!!BX9R6Cr z^JaDqq;z7^f%4N4%>)z`yXHhg4QB)&Jf#vJNM3FqU(F7v_jX;;VATi|%H3LZFTDz&@K{p#7El!V%A#>N}W~F7?Ai~26*1Rr#oL2F(hPoW@9PZuL zeVv43CocXtkwIf!i%f#@M5rM!{5P<5iZQe+7T*3mvA-_t_G!axM)P$3CqvLI zctz8m!sK^q^b=`MX8i&S$oz&*+9gYut!pWFxjxx%&17n{6o1IwQo>!f(@?}x{?^Dix3k&brxw(y((ZnLl}3vGle zNbi1X4qd9R;>%9DzrBCtCe0Ltx~mcWW7q#SdJ1>S+u9lnwni;z1r@nU3h;7u&bI@x zEA6;nx>!wRjV{O2Vwf0WX-;u{=I0rylF%?HGb|5Ij}-8&o$Sg&{dS-LJBWOa1uANb z`^(;Ys)IVX!PUiBDuN`Y!xP4cs;$2f#Py>uDKg&yu?BiZ3q*pB>a4~Uon4{x1$F$? z(GpeT;N0}VNQXnuM)u8xb7Nh;5$%3=j11DK^jEdqJD#73pd0%SsU-yK{xhPJv_!{8 zE(K5g)IXWDF-7;jo;iWpKa&o2@Fun?@=UaJ7fk-Bezx(IV^47Y^g8Ny>GqK?M_e#+ zbcbdsGW2zOIs3@IHjVNreZqnZ&L6Ebjn{85R`3+a;j#rE4>{R4owgr@ur*SpYdCLS zT7jVlkr*Xxj~u7tw#PSvQf`j*0GShwYJwR4!xWRODJnnO3Qp8-WrmFNTIkcn`8 zB@N{mnJINtcop0idi+mio4SfsZ;YLxlFtTgw8O)BjgLb}tL>>RA@Ssc=}cEt+Jl>i zV5{UIo4)}#jdQ{!u?Bs!xVRHaAA=G0!xtLPcs-JDwD4Im(lWL$QjGe787ODcWloq# z3q(SrzT{u2`MnU7kLeI#1P^GdMdhKq*Iui(A!+3WG|brnZ?T;@?-X{s<+ZcUo6f;p zmc@-BU*~I*=(R~M2RS5AS^{XwZ^8U%f)m&47%PDPHxAjvZXiRW5&O3>1^{@jyyk9C z(|ZS=Z70GdVxfGY>19+S%>l2ybuoG$ZVrYM$L1^fT?Undvpj)O)_8jDAU4!sTK6jg zEB-p+AMmt z6NaFqR~$zS+yxGh_mF7<@zCIJ^`|urkyg|rY-(oI<)-k;mBH35=FaD)&YHEmWwg=M zSav)VGNsy71W&S9{(Q;r)K$-GmeO=x+jYmiq z;MO2WF$os!P_DLG^lEYO-H#){tU1j5TeoJ9T*Tfj?B{;kG&uZGm7DKQFe<2&WXF1^ z3pK-$5S-}~CEp0>hX>H3f zOIiXUu(r3f4!BEN2HxwEYl6}j3ZkSTd(E;{ z4}TEI9m!zQ;K^eH!b_|5rB}Y7hyBoS?zb-ZU~I=A<1(ORRb_977_@$*e59}Vln0kY zR1T;)>7n%kOIRX}(aB*jP;mzaIa*TrW-XAmhlbZU>`y{d-vYmokt)pj z?)V+_ysR^5U70B>>E5i9h0dB5@|WLThdD?@+2IN5o;XcMQ@`;)OHEIdbz8)r`w||FmlAD&I9jDbwYk2W?14OS1tC&cS5W`paj9A+mt5GLUHjiJrv#`Vb2I&wcz_ z3X(unqN!BIq@Mk>XBj(C-8f#TDAl&zc-z#!T>%rkyjrT>2dKUsN$?1tM0jW{&u)++ zs|JdyJ);8fva=F+$R-W$$l*0ZeNvisBod*vY90hB=oJkln^<<7w7*~_8J{4`Y0x$d zIob)>vRcl*W#Yw;_;B;T64!3#zB8B}g@})9++X(T%T}m_3+rX-we|2~~+#J@* zPKF-kB8T)P{(T$#pzRVvPAtPLS}N*%ALQxuhZnkKh$?5|P>g3kw!%0HDv}p;g7Ih^ zw{k`Xf}@}2k=y3D<{>ZUJ~l872TrbTIU>F6yW>b>N^r&ouvO{c zuKn)TD42@m;`oA|KahtCrvSNntBqT!B1I0`mJt# zxi=EaQY*!;B~3SOirMU@-m~5MS-!rjn$WpYGaU_?xx&t&_S@FXA~ou%THvm>US9=c!|?!=IsG1Uf6eK=fK}_131_#Jcd~XaF714sF`qP!0y_*_ z@TU95ZXpvV*Fu0b4DR+f*pGz{Rl_s)3`xb~zxsQuZ)Spz)xa{Di=o_cY3pdSZO@Fxaf1XYlv+ zj98}{|5Za7eKe)tbKdOm@4g4DX~TVC$s#J>vSc@iHP2!K>y&Wbnie%`!hZ&NW$LJy0 zbBcCqcRw=E$?i3fGBj@XP__VcMTGsrOg>HybMc3t%HBjkevj2&xw*ZL+Ryi+8j^nr zT|IsM;{&@>Wk~p;=m6WcPcB<KZv9WUAX!t59SEWM@w#{vwg-rd6=Y^z>< zYJ0lJ3IMyWP@>}BT|~l`z4ic21~*R%ot_i}M|We+zy`ubzEO~^iIPCNnPhx;3foy# zj0FDLxZJ{Ds|XXSbIB?tJjIV$mG(04WO=S=5!CF!fO^sLaKFV!zfQu}RzfdbO zIwA(_8)g^nQqPx?6d#V%e>O~=To`s=0kiM-q#%MNEv!zj3@Wwu5CQkju&`nlNW6*@g|()c*=~~NF)$U zXjS8+lPP1r#>Bk(<@KBZ9$uIi_x}dw`Nl>DmlO?XaljEOQjZYHfe>&GfQAIgSlpgkzp3cvk z=6Z*l%oqq-WK8jhQKj{+Blae@WGF!OT5UM9L1HQH94P&Vvmf*rMLzwuG+^=@|6a0v65U*B@>8Pv8aZ7(-f z$_N4aG<<;| zkb6cUDAyLy;#1vpEoffP6luiL_O2{mvefa86sRhx8ic=VwkGry?T{S54PQmy8}4HS zMs_!BZZXnz`E&2aG0PJHuG)Fo@Nt|1J5{4=!+(GZsVd^6NlF;nW;iYTd&%@?*F47c_8y0nwZpR_T(ZQ z^!MNS6Zx&T=R^*5Vm6$Es{<-e$mo9yee;6R6nctdIDI4c9*P{C9*MgTZMEK9|6|IX zuEO7=&r*HZrr~$O%5hWA(+QLImg)55&yeudoVSpoT1flF z-wbR&vyjc{LRunziflnuhN<772qu2$E(VQT&*Y}(Y;OF$M{!f+_?P@#{+)2>TUOZf z?TDe!c-z+j*A54<=x$YK2vSV<>jc;)ugsTb_om#SS9YGCNOwGb=buYe=F>STd8aJp zm)esbCXs8^`mSl7DHVP^e;Ra%QTq?=7OsDnb&~)yvb+bW<*052*fU{TK0qe=7vZyn zC9MQ#IA|nLoZ_J?M}3LxR$JS!IZeD|@z3ntS^t(9kNDeDsgxc4j0i5azL7K|-9BK)d%Z=J{% zs+F4MO)t4c75IIoU_*lHRM-pRAE1E@dIK2)cQ?*Bej^@i2_k(;XR$`dO_=8>B4?G! z*#ELaho(HS|I%XZqx!dT^L{Ph1Xb!}_S0nAf1v!5j@N*%P4bFrpFV)c742itT{Y@6 z$DZ%|dGXwNU?u0=g)J><+->w<0DGGej@@?VqBP%YBuCtAwgR_|1r41WxvA2Y@BMz; zfg?Z=p{q7?4Vh8jqC}4BXRmw}q#+V14sWsXuM}5v2V?w{n~Pnhj@5z;L*g1Ca~sR_ zSlU6!b8=puU}JKz!?=2V?S4nEchvA@RB**w$FYBd33`pq`T;9|LDxHD;$I)zXH)7! zpM6lywE>gNxNoKt!FT&(?OY7sJ0yPByp|yA(p=foa)YY#1S`}@PY{&}K4@Sp1&Kiv zi_dZqn(?p1phTB3jj(BJ_Pyn{FP@Rli19d9wr_Xs*X3K`6XQvf`F_Xk*qIZB&!P%1t-wBX$yJ{!KMtK% z2A!eD05D3_7t%vyc=_`H3+LE*KtcmZ@oH+6!qeGx^V>WVvbXNbB$mZ4oV+mpJ&kv* z*w1#^WOWtOOhIP2Hr+PAD5vh{6Ct4S(tAX4FRelE15DF{KFn}3lv&AHU|fHQe(Wl? zy!9qFURV0M&@~4EIT;z{?UzsC%ZYWbMUFwxO;@@jr{Tm$cPiSvY%cR#U7-f%B3BjP z|DXy|>E0`%=NiJ6pDl5?tF)1}wA@%qbgIPAuQ7n+zy+}Zd~UVQNFSP@HH5*NC)rcU z$+)A!i&T_M;ek-58S~eU`y7UG0+g_d^u#bfT2xF2WH%2xJo8jkzbOI^dzf>dGpB)| z7^A(r;tI>_a6zcp9c(@3nlcH-JNSAs3o2bqm?~QQbZB&q=1nnq$uVRe6V}}EBj8Ve z1NDVNSo7~BLjwA_lsn}OJ3Eq6jGp5+_j2ZOIK?*!EhG89Q!enH3p38-{C53Vjbi`W zH^GpQ+MQ}wq9DimpTB~xYjoII+m0sl$+bBXD78`}K$B|?#hKn_c006xw!e8fsz8Lp zBPQ?}=KbcZJ(fMs@`!2{ZkaQYB;P&IcPt($bchLpx{i=a_^xn%H=Jmn9*>@5Wygr{zDOw>?MBQx))v2>;S2fVpC@o>wV7GmPpd7cH^ zCD#sx#Q<8&zi3{<46Dj8uBpnT2WmjL1T+GPv$Ks^tv0PdIBWqx-qhoYYzRDVs_ zn<|qIe%|ZhRH{MBNC^M$Vbje^?&ppSlKiyZJ|yVF<_VSK=trern^37FdptF?0r+Sm zqN7~@bE?uc$z3CQ?Fsz_hc(P{-Dij84jlJ+krmPMxY!<@!2D-Gqf1<0% z$=mJY8T1AA&eJNs?(;DaJq3w{oCsg5P=LkJolU3tp4HWnVY*ZI@%-nUXdSZ!?5_;I ztfiLruEeOC&Y`Y3N!TNu!_)g;My3s?UO|0YlBTPE!;D)TNQvWVgK`CcO6TwhdG*WG zXNe!^+2|G}7R)7kr<~Gy`@r;mi++L4JwDjATPPUm!%=KF>)DlRL64O_)6e0D>V#h< zkT2RAsd-YH{ejm}cK3C%!H0Inc9zd#^xhnWE--ajwsMYwDLUV_r!0_ZZs~yt*l%I4 zlpw?tU?CiM>1|Auwr&~($sfGq2yCtfmywmRSC>1&PAu4sw(96&nYn@O-#`J*@>g4s zOzGkR1UM;p(@GCE`*EiS7=*Q4*&n|L;_Q?a_Ll`t5iIV8^Q-=4Y5d%6w{wR4(=FTU zA4^;;R44x4wRt*~Wy4q%ue_ZPU1k8)j<;x0*A1kZ%!QH^YzU-n~o_VQG6 zcU?*^DBz|xYl0iAK}6k1Akt9W2L%7HW5qs2vRuAod!zw@g-$S+;$e=NY3?NV#kdn< z()flNf&u7t{GtE*=U>vR4`GDw^Z-Aqz;x7)NMq~nN4qe^g0x*tehYzl`c}Noh#jdB z-y#z8-$?o=mzEc6p3s)j1u@bR@I?QBaQ=&!$DI|FS3q5?`xxz~Q_`Q2W0aGf;4kQz zHgg^)JHn*Xl-({eF%l6%3OzDs{BhXm>y7voarK{A8QPbpbf*G9RGBCp`Qwdgy;?sLbfo}dQZoTA zkw@KUa;u#eh0*HOTT1~(SG3gB(;XfEt|y80vDJ+x_9xSEGX4*YG8IZx-(QgZ$o^0P z>_24Jun%<-GSF<5))ZzEL)nk z{V`huqQAVZ)G^%NFcx!J15JR)M^+xz9HFsL3zF07@R+>=ZaIo~^H$cQfh5`t2F@I@ z&wJ&G*^TE=r1rYC-oN*TT^wm=-(7kft%yJM63kS4XG3#7e$Yjekk8IxqWT}&z9@cY z@v?UP0{@s&3@qyJgP$SDj4CRSQmrz?UfQVIT%|7%HHRIRzQf$w7MmLp^-Y@C=}5LF ziZL5KaMXUy_FFa~-K6e;B>O0AH=$>GcDTED0PG7Z_|iyvyVn2`!&=WYekDTMt-(#8 z$kPb;$wi%7MlMXMCIUy(A>`PJlK-N!uTDQu&vc(fWM^5np$J&lHl#-W2c~5@hY#M% zoEH3^hRPCpXwHErXXa>pclMW7dmRY_S?lfb8>YFKb2MPOA;VvwFmgk`oUYrNe)i2p zTMP!d7Jv#a*6~~lDZSyT`f5^D>cJ5}p<)HD$F!5EH$6pT{o8F${n(7a>GlLfCi*ew zpG4CA*1SijmA?DGT<8zp*{iHL^MEzZeb>7~$o}vMwRKXUF1_0%uQrEIHg#Vwa#&+x z>~xyHM)6tzDL&E;?hcXlioZ3MJ~0|5d#bgYyA!;}k(U_-kO-HCt*ZU%#wqrOA_Cu> z+OU#W_hJIJVZXJ%U@g(yODysp@F7B2>v@q%Ie7ch0qeo$?B&(=R8^74>fz)LGm4c% zhK-*?+#tKQM5xzeAh}ebfad1Chbc(5k!+rvs;eTqsA@GOf9y-N+gJM76y~2&O5X@C z@L6x8idj%A+3!}*VNmO)B^}co+AV{?+0EeCNEy zUR(VzmCWUPYAE~7rW!xPEi1ZgtRi6WwzL`4;^Okt@XgE>a_G;}8L0nz#XOAI^6n4& zt6gBz9xYS?^q40DeWManaA`QMrCh+Bqzj^U^*2_Xe^l}>{diok z)DoT7ElY=!!~*x~S(~9dJ_Yfz`I9qYbk?#OHsN%2OVO>l8GQ_3w(s?Q>ML4rxHkRF z`OOxu4Iw+=HZnqxDM)De*1Q%yneB4vNB9GuE+#qc#AtK!&w6y8Y1nG_ZX#rDzc*5V z>~+xYNFPB`Bl0;L1$V03SD1~^#^+?Gg2u*Blq&1#^sfTa!*t$};mqX&*r6?T!@+A# zQtUW(v~_=LQ1-v8O)Q-U9kTOnBdFrRT@9||h>jaK>)MMqd6%OM721-! z1LZKY#`*Dax0RL~o+r)81KhTkvv_XlreV93LibxLcDL%2y1)&FaS^Do%gvX9Fb0JC z{V?%J<*|(T$oJ6ApDK?&dIMMuRoV?I{p=QvZQOa?swlI`o$~_gzKn^s5?xvh5G*l= ztNLhdz}0B{t3Hf@nP4}ohnHrQCWBzL;HA3T&}v|v!uMyirW5A7VwR~s??7lgbG>CC ztlxvwsBI4eimWm~O*o(9!?jMY$Bng-Z%tlv<$I$zC#C$j%-HctsU2eS&TWyQP0yVB zYu0(jRAGsb@WZT|BDSM*FM{Dk_haLZ@S zL(_xgGEd(%evJ7fIdfInQM$8zt-<52;dx6@B0D)U|9+-2&cn3-w+ZQ+0=?0>y+sijC)7-?1Pa(&fq!hUuz6DIc znZ>6wbjK_M@E8lR2;8ieus>7dXO8YzT&vQ5K1FimG zo<)oT!8ru|6`z{MJ9Lbd7OP*|;A{LefG&E1q=-KTGNO`%(ks;W?%;cfl+j(Ue5%UjzqtVIkXnR9;u&(MzHR>YhFkI|mWO9(p z#jdeBz9uZVJbI;H+&UjzGhz08^I%7FGj%7y3n*{;%%NyHY_9O9{7c_!n(wDlFTb{W z`Ss#|r})>62d=fs$kw@dTq(t&*!GEL{1b@Hrl#RsY|mQ!)@|vLf;KFk=C>xf#tw5~ zD?%op&M!kJo^xzduGwD5oP=)bx7(J!$~+OECV@+y+1tBf&vigJzoyH3cA&N{m-H>i zVoVvkcTk5G)>@`=#-g_Zkp0*W`M;q}+1+EMy5uSmD|2v<$VFzvF9=U7z3A)au`->o zn)+N$j#!%Dsq5fbQF#lOA{SilX7k&oGa|ugdn!NwyZ8~cTOf0KHAq1pq0%=u2 zk=^ww0d8SzK^C9^brAU$UoSB^IW{Be;LtHhCl@N5iI^$P3T{r=t%$cE6nfLMytB9I zP=0EDED7_XXZA%K&j>hZ&}ju*%4c>IE^0F&}*+^hpG3( z23rM1Z8|r>v!MZ90ar3Em7{{Lp(G@9f=z6zP?zj7Tcx$mWkSPMOP54~J;IIq`{$C_ zJaakim81{haxZ62@Beq8g{l}E>v`&InR!@ApEXPy38x%44^B0#N&2hSqGRUXGIDC$ zi4*%k6uPbQam=hH!@T!2v*l;1M72M?!SfnD%sn$7-ti1vu?`UV z96Y9vOr?^V zewE$l2|P^{c(m!fX%&MMts0_L`0_j|z*SW*K$>KfKi!d%s6Fhd6PuBZv5dJgwN5Mu zOHcc-d_||K`QGF^l1c8#yFcj-$!qQ1+P5#foF3Nv+Ov_(uCFUfcZP|JxqqIz?Ckx| z8PbF}G8+N#Gmf%%h>v~T50u>Y>_{Fd3EUaBt8dW5n1()Kp58EX%F>>{LW)q zHVh@jxLl*?{mEg%)RKb;8qxB2@&k!?6g_0;g2DG7&bSi_86miq2>W1Q2nouq5mSnx^!%kzKbL@EL0Rh6$`l*prd9# zI6y`?W23$d&My{gNN0WSyi3{@dG5b@<9I7<)^OQCbNx(}lF_;lEcZ%T@2>u(kE>agrfc?3D#QR)=Aqa5#I@Dq*M{vWX^@c$-U_T6&wqNE2DY3z8Wh ztD%);BOxKthg!?{6TWwgX|Yf?Rnq;W^J}}%Kf!y&5o~fm<->9xQ--lYUFI`_meHDY z8{vubMiTQ#)^VD*yG~}~n)*fkpMhtCBprzCH1f?SFk&i9%Aj~3SARL}_(v@6A-|@^j*0tMH6GI@4IcD$1-K!Nk*G8?N z`dA!^fcJ`-eUW# zM#`JiXXpww&Qs*wR;Vq3#zT!k%9bErvgNuG7%;&e5(T%@k=|+9DilET!oOi=H)O z&EJz~p2>*l*M3%bUulrHfdMAzjmtx^1GE)#<=!*AjeF+?NV*5Ojt%$6Am&%&D9!sm z<7#X=WDn$E%dfZ$GiS%cbn#IfhickL5<_^GpF*2B;FGjKB;_} z*mcBRUNC}N69xk{zYl&r{!CSWVO_doy+e@1Lc(BYm*?EAcb+(X5qY8K)X=X2^tC(= zhygJoQR+C0bwibp$y%~QE|=FsFM~SS^#L!xisaGKO&Mt`-e=*7n-;QPXbR+D2mr9& z{2X4k=eQbtDR8Lg*428QCc06!Nd26KdA$YOtI2?h8WIg`3^>Ph-VEIQq(37+H;fD1 z!)@192j|NSFJ?hbXw{HL3J8%?Lq@5frSh4$w3GBN7)@9?-o5*dblG86>dsRe5fvBUb=$6ROyDy;}am1vzPKjbX1r+VZwrw^6QTYQ30k84jmp# zV#P^xxFv6Wg8q8PqkyFU9z}vn?7OT_?k}uPlY?EyxleWb$%(sqCbs8UiDy!YZEX8F zFDtfF*JKT(Zpw{2-eGR{llX#Ht#$dLBMOJ{o7Kq^y2>%m$wP$ndNU*3s|d|OqmxE= zt~Rmx%85(roLzfWF#VA2`B78XFq~6?fctC0mc`6XGYFai&6IcfKts~Q&VN}pSo!n0 zt^d}W6gYniTPemKFqHPzUv-bB`gE3N3+C}YYm%wl$?1>~ zM(p9T@lWWjAprp0W^;_4f{YF3nvag*Fhc7f!7pT^8>8^>Ec5`o7!l1~GUo@}4A)nK zKiAen+etTiz6P3O^2YGLsj@AELjXN-Vlk|r%K0g7d$<}2dk6?QAljF1OtOyd@&4&j zuv`qVRvXTU62DpAg3eN?*UCg;5I#`c(u*w${mMtv<%q%y8iZjqJR1E%+M%m?VrK9) z01|ch{7Z0j3|L>-Y^@wSrBp?buhfI;)Zoz67Q@uO8!0(2U7NXAVSF zKK4tOUZ_MwS!Jq2?01_fzB2#mHL&CbTo#-4)JJ>=pDaZc_|OgBHC8iX`2DDpN97GOz#kVhY(Yz-2V_=bw59c>uDOv zuBd!*w@_Br6@*(6ei#MTB)*gFuf%>Efj1=`m@Op`*nVZ8DqF*(hIe02vC^#sPpzLO z$OlygF1@n&S^9lXzScg>oYI1Yw1$}-T@*9L8u`awC+O^^H@1=hgwrk)nGzo=pd-O5 zb#cEvQ48Pnq}A8+23ZvgjUCVy=Tv}7PmgM(^!Im-WOu{pGEH5x2OL-$)z2Ht!qX}( z)KhyL9}lwrr0RDZscZ2$J^R)ENAddmO-QCQ#FRBhqsv}c%<7{17hb>k0OU`iO>vO% z%VJ~g)%&J^Hdq@etRnQk3L;M!>n=fUS&zO{j0xe^_=)$4mm9mg=}rkRl!jXdf>o4Hn`dJPpSx~)=v9APuO}CJ^Ymr2u(g~9X>azWKK=2k*@aLiM(3)lMr$A9 zroWA+{1dEz`NNZgt8lPzEoBn^c+*zu*XsMx$mdiZTRgeA@iB_=tb=oe=0h2xDL@2S z>)YCoiO=2azK<_2y=jed^n9cIKEmLaiZUW6;|d z*AnBF^se&<#{;F!$T8X0vm{4n&i>E(?;?)Qp{M9@(U-No8gJP>XI;MrJrVK`iHtc6 zJYJbqcazn-Js4{ke^%+NOuWQLTyJD7`x>epm(nx zgDQfe{qu5++1cp$wWX;-nSrPs1Eh`@DiPg0Cu-#t9V&&SBaSY*MkX_ND#Nt>!I|N+ zk9YE0h>?vc3YW_wB!N)(^PBzcG0riz(MV%|@F$oyzg_rMP#Dyn{8x%l;7MA+b(`*0 zhQ)3IqZ3eGx{W%M|L%_k`WO$pfO!dy*N{H^NZqbg!c~U^g-i8*Otk*gX4{N4P*20O zYN1r-)rR#LDggzpEwrJ}E#54|IRqhT6s_*1nmV7ZMon)VrMWiTeg(LpnE6_$HdHVB z@bj12E`iO%^o*uR#nNpPr?IdMpMfSN@P}u^@6svHmC9=hcLa01*#W$4zDlwYY=iW0co|)_MI0#(>C#RQb|74L)Rg>`#mo&e0nX;rX>Mbz3 zT$@G zPeB_lRC~}*#rX^Mr(a?2tldI32p`<9%iL|pl6zGYd#wl$0HTfZmuypCrg&|(4rjF_ zMNC|0-nx1s>jCVLPnmS)CQ&`_%mxO`FV;6hYwA_2B6i-3P{z*7UBrpeuhvdB?bhDf zf!z<89Ux>S{r4jDUX@i=a6U&rp4n;cU^v=|Uz+QzJ*JW_!aa8~w0>Ik4b?{?tQ+z2 zPfQY8MRxZpXx_q*u#vTCwn&^Epq(298MW0TgZQ`vbv)^&K&NTxdqAfk2e&K4klJHQ zAx`UC`0Y&|qk35DmVswshb`-X3yFe=e_bR=Fwa*kzK;Id*3e6Kkc&`KxiKTh`Hc}Z zN>aRnR`lKCL&}B0aJ~-1^*Z9G;aW@tuE*Cqci2v!J`ozBN6aY)V1K^a=K7-gdk#PJ!vpViYL-G9OuqO?OqTlHnKMb! z9ke{}f=;e@=}80PBTx7GwSbz(m06{chPq!VPiT zPdb0wn#pVamwG{*w;nO*-v8V0zMqiug!SNg0|WnRhOjm92pgDs{-EPu>AUdMTQdUY zj&c7sMdC=twCgJFJ-0ai&OHq0+_As!*7>jQ{KXrt?GQNG0y(at^@@=+FXW|k;;!ef zn>Zcwm_G*8%lWB*O_jwClAmaSas6Mu+pJaIgt!I&L&=OV`>uo{K>?w-?=XjrIKAkN zjQWI$fdHvAwd-vALVq-=0;Dz5D|tW0v!fgDN2*Vp@F6%ZY)Z*=EQu^BF)RP)W1uYl z*WAeYzvf2Y?@nY)%n^Q$ze6<;bHYvZraX5-&V1bC<}w4PQsB8wZ)cwEWuuEvF`3I; ze^iGvH>>)xzB+suA0gCc^@RLc&^qCf@W%$sVSYFkxmKtq{_`5YsoF;s>9>qm;M4!g zBkN8CpFthtG~Wp}d&?%dwIrCI;3TC5-k$n)rWMHOtoJqvW3Z-+A{bQI@VyIW|);DXw{Qyf@_E{%#h?U6$FmqihO zQR}0z6k*1*d#y>ki`L{h4XRV=eo&voJ3A-Kkt!cU!{EC@gzuwU#o_WTy&fEsOQu=W z0IARbz0vV2b?l=mufFy7a6+~K#xG{?yyQkop17KrztgN?c^SRF(mpMH-Mrfeaq2zp z1c%`4n86OO&))4W=VNDHp6B}=0d>MCUgB)UPFY-V=KK(}rF!XP7U)u}+PCKb2juC6 z;hEfZXU^=Vy(nE(T~&*x4qsY!<`2fS`hk0kHCeJy7{ngCMrfEeQy+MS)pzuK|AQ$O zkZMh|cTn73$qsEJ8PyH1cd2E*`W5mb>NsnVRo18awFiy6S~3=Vi`Blv4@J$=kzLAu zz4f=CqAIy$X> z|Ly{txBsUv*7#LI&8law(8j$bd9hkcW?WjrvmF9fSv~$K%i5NV z>CV=+wh7h3kkG5Y{RL=whMsFVRJ=0g2oL`+@bchhH4>p3|Nkzth}C1ziiFWE%}|aX zJB}8Q>BxzQitX;Ia9ZIfBawJDQ1}{if_x_6aQaJEnMKz&#UA6L)ZaxSsNVa&-v1;% z3}jwFR&OcCOgS0Wo$y(@SbgY!1s(7tT8Q)rL(_LX9%DGNKxvBi_=S6s%9-->sj71W zSN9jo7jg-7*l`(#!OGotTf3UNXs&l;VO4g;eK%hRo4ij1b{EKSwoTxe70=&yWU zndiR+kCq(>?+8OeJj2kG?%_blZcj`u5p9FXgHnG2Q?{Mz8$I|!#1-(61D@&uTGBH; zZk~&)ZsjeddWq6?Lbeu9y}lfLJuwlaES0P73eFLuHZ&^nlXbV&6Num%ME9}GHVgaf z3Xab8_bBBpY2kVdX9Tt37d2;#?(x~#?WZ<^A^A^g&66`f3r;k)m1-dp-MiZ;e9`-^ zFl9%#34H~kA*&V~F;B7UAr#hubdbkKSU;tNMw3iIy$+a=2On~g52BAW$vo#{4jZc{ zSg{Ge)`C`dGR`D4JP%?7ncjDX(%~mRUj4>uJSl)81P7&@%5a005N#rqgvj1B-2ii=)ZJ{N-H^V@$C7(UQs%D+f7be)TB*9~M;lMBEL%_Zr z%`x`R8rX*;`!eaiK|xQFY<#=(wP5zoAGqICPl|S$+Csx@TjQE|g-m~2QM{ly$v=}3 z?Ka6C!xr4r)5mptm!4h_SLYy=vdDA~YMAPKXaOD8-Eo zzCk*!#`gfi?!dexMh{K=H;)zQ*NJjFYecUaZK*%)GP3v`oW8Rjr{0VcQcN; z%=X4$^`FRjxkhV@;(Yl?p6IzI2|D&d_|=?nPBuwpTeRy+(INJ zU;D1rU$$+EPOW^@*x(+tHusY4Pf%Iw93Lt^*fyG5i)N)=*A&c8&xJ zq4(A@zCUyiS4NcsItO~wux+Af{;k*Dn;yqCfLiWBlkDzdu-*oEH zXKXNH!Vm2hStc~^iT{I%*~E}L@V*|8yVh7^SW-#zRqfP zhE21lGggmGKE5~tf28cG7JpzoH+IHC0U9$aNj;Wpy|;L9-V2j?sQ3`vC1L?E`YLU| zI%*~lhmCB`NICqCqb0l#o3)g|u2wzYz z!=_y~vHvMZ`$MkjzF;}FFV)X@guF?;?p$hde48(%Y)w1sI7G=px~Y5Lts5S5P3A(@ zrykUyZVic}x(O6YSkmY+#WjH z&2MA73@leJowl~CVuM$DjqQ*xq*2oxhpG=GdU1?ZuHiyucEqrVfc3n?%cIKGS+O*96twFF5P|of{LI6jHP?wl21LbeWgr4;U&-riaUVd#s zFHbD5FGJocTaFlcJ;?Dg#q2K{uPCE&{l-KVh>Ol;<7sP^g0EL{!cS8F?*A>>%_q$1 zhh$lVA_jA*f}W5LE{&7Vtp|s-0Sho4bl?DhEfe?s(qJhpG*)_QCx&>qtNeVLvar zSfJgzW?`dWav7)Vi`7K!GhZ9oaorf!T!91jlc}|#x=VK$Ht1|#Ila7uz%TpAmCeNG zro!!uE1OUCzP|2p@6Co?ozzdf25$-0TAs!MR)IrhrkUDT;Jzt^h=@F=i}bBckAn+l z-$NQNsx z_vz{{bdt_d*!*F4{!yA)!;ug5p`%Dl^ZAkgos<3FF}0cL|0*O~2U|Tt*!@#SDN_GL zjT){8_Seb3a>$hXkyY1h60j-dX%%cau5`a0?`CJ_zmvNIJ{^@zDokjaa2!9-cC4ofP7`@dEvuB6p{?w;f+T2D=a;!T(b+UZtepiuy18qy01bgp{ zwG6gCPuz}PR~I>SaC_jQ415S~Y`vy%Fq^#7~`C*sS9PwJ990QBl0XU@HOPgB*+R!v!Xq8@D!@N=5 zcGY_%xd}r>M3ZDak_>pah?YLudf|0Exs!ME#d+FD@bx@cFFuo0hrlTvb?}v{jVTcV z3pD&8TY=@`4?W%1H{Dl)?k)*XEV+I-`cJ3-l_Pw3o>0`4X^e9BSzoqSQHbfh3XPl3 zYccA9v zrg>VruJPgM!cO-MRi_L3V{t@wy==wOhD1PfiQH!60J45ux}!%If=$a&`|nlvA@Se9 z4yx3Ll{rP{R}%c%#(c;BQ_?8M(BS+rEWG-t{(6ebIrwBvW-$NjzgJ2Yl>1akO2so# zg#sBr6*}{+ia&=Xc&`r4=o=P93*qYQyZ@Qeu1TcGPBLJM@BC30VGEZr1|L>E$HS0CX@rX|K2O!%nZ zBJ0(bbUsz2e?_2}EdXzQQW-P^I=q3ovQpeEwBFr+v9*=p>yAGI))!N8rela6Ot0EbQWwoq^lTCxAv?rmW{zXSU|@uXCAcyy+DZ2 z=TwFaw8RE;sbo%%D&B({#s5S}!Q&Vr$f^ZIQ_4^2pO{L1mUIhQSnrVH`0LQ;F`Ev* zn_RUPP3LB?Hhhv?xm8oE;5_pXZyjXQ3v`g4llpmkH<{&En1&dU7~}M@-|jM)q-VD+ z!<$I}YRS>l;8FV68;+eNyX#KWFHRI|uSjKrUWijMX}f>7j!JmG&quzs zg8;pn$tG8T^awU!ZffHmD$(uwBG%$-8(?KqS$`> zr39pO@wHT2yNyR|YeJI8Gf!9oi#`FJ=spB&?6I6{4cp%rP(*N#YJShBMojc*EkuOJ&H6JA>(F49|$eu>ev7D$Em$ zBcxy)u1)bHn*jJ=ym3UWZB{6{g}!$3-*5 zo-Bt!di5_sfMq=>DJ_}1M`mQfSw4TLD*9n7sgqaEduV;*5^aQ4e7>OqMomuH*kng` zMi#6YHNpU(jJAVyt&a>#k-mnRphvc6ZWdm=7H5pS{7PvO^j+!Q+6MCPl7!+y8@KJY}6bk$tiLWCzDL?7O&BEHss8ptF( zJJ2BEB0kT&h3Jl+q4KVjzW<1T!?sQwm{HxLnV3;HCIbJ3= zL>j9bNeyYk6SXY9KK$j1Bz0d{fIrhK-EbUj${Lf!TmI7M`X$nHo>_`Hiby!>`(GxF zw}Ah@nY5XSBZ|?4eVU;6>2BJe_KZw-td~t)2S*EAusj+cd65jU{v?miLlRX%X1CI} ztZ;=%3Y|@z&lqDN=4BfrVZf-Pixt<@#EMhFaQ;c7=o@?Vj!Wz9%S-ye%YQ03m@A@M z$+$l(0$4SyC!ap0AB=l77?C#Tcl7iWJ2sE3Q}(9-BWoKLRQ&JzIV*&J-!s1D&U+5q zfasY3sZ~z7Ne$D(t?Jr{>7`(wzap~IZ9r1^;!MX&N(j% zb+eHD@d#Xfpxw@CCc{Hld<_8~Tm6I#?4bZ5M~YV9TTaQRmk<`ebmKg)uTC!g!Mm9J zASa4mmaZ*eTj70{mJ2t)wfmttAZ@W9hK+XuH2FjYbYkQSoxCpzyurf;1||#A+)9We znD7A|Oj>+Llu!69Dk2Ex+5A)5xWQg@jcxaw2FluHfqXwx7sz#1goqjVOriGk+RqTT z$(4E$5Hpor(dx#PE868MDHkLV5q2@DT=M{i6;xtFD0aiZ+ol|*y`M+1+}xk_d{IyB zPr-Hh$?kj!m#7J5c9}uij+H5mohiqKHAc=TO@1Hf*57DjO2i_=D6RHIhr%tZS(G}; zdONX@7)C%p|kns!ZD}+@^SRYabif zRu`@RwWWalQJ&LbzW$TspK8w{*#xbI?toiZj?@x)DpZ13(L=9DbUxSR@I{wj= zGcX*{>DW>48p$U0)iQ(Eep8)s_FTD-eVES50CB@J=AW>e1?h9@jY;d~M_Rg{g4w=g zJH=w;qs9Qz^6$=T^t?*#u2qwSu8#)uOxf8)X|G_Hfi?e}d-)5!cz#FKoEG`M>h-S( zM(AvV3M{x_jvW#Y{3@Ll8)*ls6EYZ8T3t#m(!Eyo&Rb~zfChhk41u=b%pCIW`!B}M z{l6Id{Tf++_GpONwB_FtUCwQ0u4RP=VDIN?EJ2OZ$cp`*$3u4b7yV5f4JK@ zXDhq<$+qn}zF9YwF0JX#n&DF8u?7CLF=h)+8*)AEoe&l67k}GEO6ph0dF+pI{#?FS zv|`K1mRNiJ=60dl1pXlO$*H7sffd`jQ-9%h&R4#DXM-ihf3pvJsP)50a%>LOaZYI?0Q~rg;rB=%0ollJ;jelku_OFQ{eH3*D;i)?a`;(U%TBIa%QU+pRT_xzPCEP zwR!k)ilgJwe38~2{chmNTk?(o#?rZ)R9nElUn#XsyrCs|b7g#eAT;?_DX3!|5KcJk z4YwywI|$|L2mug@Asuh3a7lzz=v?NOf%B(JjF-)&xtKm8-TpjRdU9s!HF3Lq?VS6vs`*k4{>%njfkL_UpQh?PTo`vkTF6#R(cb*rF@uwGo2)Gs@qFRv%eBk%{ zx5{vlrzQ}wW#258_zv$dg1gO$Bb%eRt?04nYei2 zHMpLg;y^B}ji1q2;%RK#?>PP}WS*l6LH^XmuTqM4z16h?al&Tx9(waL z4t~Z;KiJr?Jk|BZ=i;T{mT~)7zBk+4`kA<;^` zwG(zufwj9HBh?*_$bnmR0qO?jkotw%II3T-8AB$-LXi#DTud{TU|ST8y9|b+(Vw+< zzTH=JldeaFJckK8gd6Ym(4ucF6+@nAp81wi<>Pu{C2H^*Cn5_XdVSr5a=@T@Vva=m zkR<#6M5zB4a|=%XB`-m@prJ`3X_-!W+y`~#wiA*2lZE+wp8+n5LN<=WUUDrsIi(U? z8nbE5Y)t_{H$`$D%Wqf037OADNUdvIINF(fyHElXp}58F3jbNY1pz*N=A~t_FZtts zuExmGTs9Y<)Z23<2>=S-x6?L4^AOK2CTL)e8~$FT0jyWQ(EKb~w7 zewXhRaA&gyIZzKJ(4(wk@QafM)qE!pHqzFE&Ah|KAC5fch!1d$;9<(J;s=1GS8tG7EG zsM%}@^{GyF=$j(1p=?{O@>8B!xy5zArFipW&)05>&#OAlT56G1p>G{WuPlK4&+QB` zoL4H4#PhAWCHL+-O@YMP0H~UOg->2E{w7^H!`P0Ozeu2h5a&&O z*LnYjT+i&L^UzelyOq~NgvxZ7&lh4m@a zL9}l?P`{ha$EXVr|DwC9+x_dOyfd}1sVhzJUN(U*nBwd*qG{UYP^iN^pZIr|;z&?_ z6Y*ir`tRKNB+$+v&!uDKq^8saStgOQWY%TY=nE1q-4-dNhA4IP!^#a_sK z(`2_OPtSQ>_CIshwM*Hd)B{hw0Y_T#%Ic$=p{ED^s_1Y*p(m5Ps51`L(zDiEY*C&!0F?2OPG$ zVl?$ksEj+vbEgFtD-5Fk%nyah`iDPIg-kt6pE*$~?* zi}p4nSpZ%XWC9B9oTv(*ZS%&gL7ePZFROB|mCTeEhl78KJ_j3BswIk_lY~@a3?rT6#zV77026Vk4 zXY428>xjIC-8%Gfp0WM7cv08gXeb0vU;e6H#4^v#r$~>%wQjWyOaNXD_up^x?BJi4 zD?$4l-6D_e$tgdaq9@+n3`+fq`JxmIsvzE^Hhg)$1 z>1`axtfPYMX#-bujguK-YXjia+IJ5Kkc@h^I{iB9jrc;S0Xk;V1@nZ`$k@fY@Km=82(&7GE$lQsKUs<))aKo#BH!%S95aapzRl238N0dL8~ ztU6$84t?Y!{FUdf+rpvtyod`9LztW|8;(OD z_r1F5m>3j^VH`V;K}43TD!M)vxk2>g>{*T9{KmIxPB%f8tW+$uokbdWhHYc9wge z8ZK$#p~;#Lu)Hte?mNAP%Nrx=InQa-jMj6)`YZ5Wb`P_i!QaQGAZbHt*vwH!;AU+~ zQyTZ_^97NMs(Q1qG{FTjEQxh^%?Q;qtfi5)av`Gtp@x3mOOd8C6ZXInFqHvF@{~^7 zXaoLpV}aa}J@G1F|0lM|sTFrn8(#PK^`;Mwyfd=mGxSi=t}aWxT2;QM z?B1ZeF&-0g%t`O=gDdS$E>CPcnLefkpq%2S=+^a-U2eN>frgLw97uu2Xxw7+{*XJt z#H_hYu%t%%Ci(Y7#HR${?z>vrxlf=d5L1}uV84va7*fYPDk_nE1>x@qH^sR2?DELr~_i=!Vp!igMN;=2D| z0NISY=&0X0ieAt70gc*|4m$wnX1OR5>J>J=oNKm}#FpXC3r+E0RxU0&(zbdEqpitH z`cpH$K(FY8>h*K_J!5A!9lq?0A8n|k;rC8G!M(5OmX?<{kVkg;IIIbn{{&VSwvZIy zafON8;CF9a!+h*t?(sVc4aiqF?fR-aFcDg_h=(S?R{h|9!snTG0du>+a54UdG1MBE z4|hf0=WD~!{cDEcC>uMe*r9qs{vjUP%Fkm&8P7sUnU>Dmt}x(EX`r3B-HGb;R80B7 z1te3oex0)IYv-V(@y*PE3Tvp(qLTWL3yI z9mEz|DkycH`j=M84`+^A8vO5%w8ww2U^c+~?s~CGBgbJ<1W!29sn!z_L)a6*%2oYd z;q@IuUis3!bh_@w(qs9k@V@ZpY(W)G9LiGD&<;gX@O~r*LNYd|O=D-oQNKK;JpB1= zxsATs)iJ?I)!{AMBgZT6fXV{L-X;D8C`eU>!#=2wp9zTc6R#c?%xHW&_DV`B9bMVU z1Ye)jeR#4G{hhlIhtlb8+Wy0Yoq3|8(+>{I)5#oA>e%v3>HyJ|$|8Q_zm@e7cDs)? zq95;;AiEyh`4bA){^U=rs5Kv79`3a73D`K%nr;Tp&xrXHc20R$t6WwYLnd9VtJ~E= zMQUN@!0*~MB(AU{I*fSb=3ve%18gv=2xNe3N>=by{LSNq-*6OHsVnSnLv zqppL>j`G>D?U5XI^XMm^5v>aOLj#EFq-+2}<2)4DrOMk$I9Fgh{iHp-`tY+;FW?!o zu0t|+G}xfVt=5!ViE8G^f{REMBN8{=XClmF?t+7o9?poEBlhf^EXv#*jLS!)8>WCy zl|l;>QI(|2F+Hr*G{hsEC8Tq#L+;sIlzIN`SfY^q=fau~GS&uV0ws&dNXqkWalt~j zRuP3{^V=kkj_SnL)VrCRDYd`1zDj9FczBl64!6Vq2Rxph*U)1@51@|tftxVXN%dGF z`OKAb|8}Elw%#fvw90dp15VV~vFCNWiwfU9)dFEjGM;}hUP`O#3JTlMs>d)62t^y{ zr9gGsjZ+fG!i@N0I?`la9q;_Zt&M8%HGNYSOWoA=o4w6{Z`V~B{7#}KNUFmzlb+Y% zIP#}tdhPFO@E;*_wu<@n0RM>(7M;%!b!@Rt%82zb*>aQF@gL81%qt4+7NsU>b=8Z> zwk&y9-=B-}8EYDZ&mU_~JZPW!VSgkP_?X=Fz4P!X*-0Ui-VSvdm^_zV!;=Kvu55iA zk+4`bPn4H-f?I^Ljv-&}&=KjBG9BJhoX!XDD=QXj779ffV1G(Xt!_)7j-tyfF?_Pg z;pZisYz`#>WhBxG_z57cw%8Ml4FvBKdxWk`R*8= zL6qi9k5SO97}?!$+GX`~Y4)IRP06H_zdZKCzNYkPz1rN=s7Fgpo?m5%h0BMTR&^cm z>eQ32L=@ibr2A`?u4xjbFLlEm{@nZ#6t6%H%Ep|Qx{2IzxZ^@yJhyqE`2>x_|A?K= z(TcHFMvWPtu1W*cW)x9X9xB|?9RK-o3f-a_ z7X3kSdyz1tr~T*Q?~lHMD`&%`uuPI}8%YA0qkUibMffz*(Zcgy@dm5&b$0v8i4jrrm>&u(L% z#Famye6||9Gh!R#AXX;YzZJY|J8iUUZ+g`#i{0}X)dhPpYT_s=g-BU~J)xQtBZ05c z=^l3|V)2{6-&gm zSE^8K^Xii|0IEybP8J~8bNf1WA*FNf-HK%yfModTiHVc*`RbNcqoVx#KS@s~bf8*h zxa4&bWbN2<8!=#ud_kIzKxk*N^!RyeY%l~o8dfaZNV1eIy|rWH_z>K7TPFE5 zJRqQ_btRm?Em|sDMIEqd@(`}~1>113FJr9l**>MKntpzTl&ros{5)p`cPaZo1Qp?d zEGImb;f>TodQAYI9$jQqiC@aB=KPMA1@%`;u3I*0Z&p_v%b}RDEkc!vlWHr+FMqK) zP-|}Oq0c{Z|D}vs+-6O!y!3z4x+s|g7NdOhjnL79IncFaQ_A|N`7u|HN5y+7ApG=D z{uN7`vAYJfXFy-SAFMdJ&n@AljTP@~+I!1w!^w?kML-PuA1|C|uXlFNU2Y=TjuVFp zdnUoRb|>cVP_6ti({RQ)zOY9^|FU+z+zSSTzyd$6+{yLw%QJ$w+ZD95o#8k=Wd+H$ zRz2p;<6tc%?xz39_(h4xUiKLySW?5#hgUy1JKsifTNkRZzZ>9I;<7SOulcAdPjB?A zk2F1usO*6f!>+%;$8*0~cZhA{oMoBAPIaD~9oB1b6ya4ZirkU7pf*IeSaw zP0Gn4>&!&1m!Q(5#BhuYSVZO0YBQqG4gz{WO+RoF2DdgMM4ot@SccjSP41T1iH zTGbna`7NHmKQ&<&7W^(gU~gD#aG!R5c(1rtr|sz+cgI%gSY~ZY=gd|~syI?WTKqHY zm^a4t`#Rh0?sduFz&R_NqX)T}`NQDvJB3ZQL+e9O2$yEoS9tiUfV4RR$I)>mNNXE@ z^A*fdcq25(e*Ea1Y);+3V+Z%zKE^m4NW31!bq+Q7EjqSf*gPaRQgd+u9FqdHpy~h% zZN3_j7Yp48{t%kap+qdGNYB+NA`_(QFz>L!HjspMKINQ(B* z0W^DDz6>!8KDVvYwn2zYaDU+58TCtJZ#*O_xO0nIS5ITHLtf+mYc=UfGJZ%O&P^VL zDfZnJm_a^%7+wT*dhph-U}7(ge9@BXogOUW%H7|Jae+u4fX&uelS}Qm;a`Kx+d6b+ zDkF2?oftw@_{rvoT&lxM;}hfvcP=Sgso5N@uoGy>^;@g9v)Hp`70#=QZon8>C1hWuBB_X z#seHX9`s^Wq@5PnqGRRlb_YZdNgT$~87k=}=E2D(P*mFw+2PdfHW zYMmKW_-ad2x(ak;)pifvUp+CMJ<;s9Ry)cJa}0+>DgO@YJv`W;1g6k50yb{pCERAB zSS2dgVW-RyeyD(6ryY1pAFzQ0pNQIWs6tWy`ot{z&nr`8FWO^Ay0fs7H}Temi*eNi zwXufTps2{;EW>O(>TgyZNVezU2=P(8GrqHB?{gkzGF+L=sO_-kMsf*Ewj1DRbt3%B z_qKaARD5s*5#K0Vd|biG2_H{BjNa5G$}HWfyO|eOODG(8VTvHV zKS(M+SOX{_Z)Isa9_*5$59*mWYd=6<(UdN6rGAYL5_6L2-unkPl+YGHRZg~V5RKz9 z@x;|_v`~?k=f~twMo=&Vw?z)iByF7Z07{H5_z@z2gja%c*oU|BjFtVl(n-I}6CZ5$D^OU#d~au zUrh7mVWt_u41BUVDH95q7AC)!&BAL$bc?}#_^};$sladuUN0Y{TurR)j%8rQKyE_j zqVStn-5|w&1pDQt4ZyT)dCN7O8nW=m0??_X?^38lV)jhu19YjKlNqaf$l+(C_X3>r z<64khiV9S(T5+hr?jML`Xs1ds)l0dP76AjEtfTNZJvR}x52=Pug*+MvIx`P=GThlm zu!ynTTG#@D?THVvsW8Dhb{ZU3xVcb@&O(9Es7T6MOGK?RsNf&&+}BI+`e^{1;8OG*Y%DjB&&RL2$lC-A`(C? ze~(kZwE-T^?V%N&R@&1A((55eEnZgf;ysGI60ie9djG8J-<7k;zD@hHjTe|pS!>m9Pe$649A~plicJoA~MOg^GeQjzxAq_Du!j zI}igc1ii4T#&)eoF*DxWJKlz*BS864&O->wC9gH{b&Zsh&{xS5Dw(*D8_4x@){uH5 zs1@X}ElgG@>EB!KuV6@WIm>${NYRzK?!?-ZNj0_HLR)XSL2*I>TTM)jv=x1zK0zCv zMspxJ>&NJUyuX=AN!S|lLE$$?vLp-(@1 zmpP(S)r83nCD2t)O)pj<7yP>W^3=6YZ8MO2;MP~e2c7r*yXghH`+zncEll{B3>y;Z zo$xN@V616rp0VV_ti8;?W67bUAKk8#c0Dq}#)+o;gt5(>!q2j-W!MWOt^3!JhYo1G z{_SCR?pn{nenz*7gfjA9XCjKFdFIgG#UNCjH{}jlWsUlhg(whEU3jI)JKH9>5L3_hBsw(7BIbM?pKSP(j@k$YjA03YPtfw8DKW!8{ zL9i6v$!&SkyU?RrYn>1mZfAd6=`mF=Ouy;r>W1KCTPasPbZ7U)73qc#$qrl3q? zhWr*Y6Lnkw%}6)+T*`>scgTjcJZax{1J9SVwAyRE2YNlJL+rmQJdQIRx|-Lu*68%h zLJ45E*ALJoDdoM7dbu-nVBZ+}%ff78!r7e^Iv`6Y;^fEx?2mws2eQpqL_Afh37WI& z(rG5rjb)Yrc_`e0Ny4YmuP=QIW~Ec#r`g_q0Bj63&RGkBgZD!154HL8AP+Ow_;W$k z3=>bp&hlYpcWuam_X51Dr48MY=Hc0qh-)|UTx1pZBp_HskM1G2@|e*50{ef_R$*R}n<>)Jl=_v`h1J|08@ z6ZoVh^JSmgknc~qeW70Kh^LzVp2wV`%g)w6C%V+XHZZ%@=T@KfhX%C{1-y2nwLZMn zFC+LlsCK`~Ksh%@+Jxea9>(32R_n;RvtN-lBKzhs)YH?gVqGA#Z-^#Dm$lE;clfE8 zT7w0q>W+41Z5ISE^K19z^2t{co)@0gH0}yE)9xDrl4c|f0uw|w#Ss7n9M%@RHKkO( zqXlR#hQcQz8gZEMS1`Pzf%6oAU-|%68J&a~&kq5NkE^!NvmAuCAUn}zQcA0ypmvet z1EgQ$Z{bTJ0{iz@OmRAwP6Wn#g{EEHNON#AQs=c2z?Vkvbu^?sv|NU5fU_>?8xdYa z*$_P);pwRVu#RdW! zjJzce2z#-x5ultF3AL4`+xIVLED?+H!TxBcYiM*LFJ)+X*RxA?Dgvb(HDH?k+gZdssC@d}Qf*AllP!nHH)_3S*D$T>M(cveCUm3le{pLm1fyJxf0lLAkjM z7xlV}oe-v^L7)@ktpY1pvAafk82q8%b5HyCTyjlQ%&HO;j;$|dK0drx)kviPq({+B z&Xt;@^_lceq8zrj_ExT%I(IqE>F`D9!(ohSK@Zq|Rl?C%obAu846mhKnBVm^Dyd9# zJUpWTL^_*R$#_cT;vV{q(!8TPO0`BKtS$*aOkSNfRSuHI1i;L<2#?=N2PGp>u7~Ar z`;9UOMKRlhn8WVGChnDpmNP5TKiELaJs!5G>;xZ1-s|V5#Fv+|UYvAl4)+dA>U~^# z#iPkK9w}#E#q7T|QGo0w?avo;;mJ>F1~#Z;7+edUnhjCWy4ae)eDc8&XT13Ndy9)& zv}eL|g_*x=zVnZ5eMY4}+Bh8xdc;-+Nq3swrR^ka2#ufSGvao}-qc9H#z%7!X&0o$ zUh{Lhd3{WQJ3=eyJu%CsQYu_r^Y;zk`t|kQ8<})Zjg-f~y}Ew)&i%3Bdn{^Od)jB> zpAK0JQt-ogi~q`&qO>Vwg(N%=7Vk)q?jOV_ zZ05agUfn)0@Z@SalcnfPsPx7W-iLyuCvUnR{;{F|-f|e)c*V~6|5Uz7_N+4)*xzLZ zPRs=7-gJwo`DR|f?yE$CFRCiN9b9O0W7bx9mkQ})QnaVyoW4??F|93k%*%gxEU<{| zPz5ZAbF8h;`MMtV;#4r^`7$*^XUe7|QUQMESH`Lzcph?C(}HRig(mSNi(-t#e5|%4FKnFrys@EZDp;i5wgMB85 z35DV;+WtdSV8dZ4`SoGIg_i`ujK_V8Qo}ezxH9<&{pfak$5-x0PG7P$0+n4BInLZb zo_vJRd@##!z7yauc^u#2@AUZ=)pA$sN^5}6c%jILCHD*hnqwm|+EA(_V2e0={)WRf zNz16>N3^Ro?V*n&1@&elPc^Ohp?I??Yyh7}K?;()*pK@6WW?Jm|Ax}o>E?m9e@>yp zc?Ri_A1EtQvpgPvRh`#r9k)GE?THu_fYNDSzj*-*Vyv1_KWJKVQWX=AY_7OX!b?&@4V+0%FtX~Lln)acjgtZro#(d7jjAABu!sV-TJ@_pK1=YqG97QTQXJ{KEg|V(->QJ?>xQ! z*iNlEWeKY8I{(IX&M?_-{gi9*=C}p5zxhqm8U#AnnK5o1MUMuOMrt~0q-2;iNcx)` zh+7&{=eA+UvM&*km0;MgZ8mz$Q~yU*`dmivy=0Yp2j&anT?jt$)DD>Lp^E3u|JMfs zcvC#~gR^01sTBS?JHAnaQR8qGF0y&u*|&evCm z9sIMb^fS5gYVl!`xaar^|3jOE&&oFiYKLBTJ>k0t zjHKdZW|kJ(THSv#-xwkwerLK|w4`N^_DA`~RsxShhWyZFG>LxxS|u`d<1hD7Gw++< zAnr+aOY1T%nh|wR*l+29l|XI0m5bVh9Q7fM|RF!4wC1VP}&uH z+Eqq*1X137Z}mf@YZWf+*t%VplkQ%#TYwD+sMaq2VTjN(ikP7Gc*i`>I;nK~YQmm_ zt=?em-5>67xD@y+bxY-=BQwK!_ zx~{fNIn$AMOtt{*Lh*LuWqM&!O)b0ci>f`{d*6-2odfmL`Z!KDZNos}D4G5t>1dgE zFOL&T)Iyvk%t1@;XUs`zNPcPIa|r`1$%1@m9g0Gqw^)Z|^??uGJ!Q6^b1v#t}&me}cG1DD)Mlu1|iYypBmVgg-`cPVOL+Q#H+> zUvj7VakOy%gJ08v%}R#>R5`;jeLKGz6GC@7lvKGtLRAd+uQAD)>je(L>CFoeX~|J+ z9=(Hlje_TDb=r%~wrfZ{f5m7HGe&%d@`KLv3F0mErC;Mp4 zN{C;5+Tp+MQh;x0AqPqV5n7+@q_Z4Graa-Ssu72Zi%FV_g!dH!fT4-NTvro6i-p?? zqWY|-PzSN&CqV@Rh;_Z(_dODx@w!e&ZkktWy@xq1uJK{7e*_md7 z_{)?Hppk%DzS$wBdmqxHuRGK_c2B1KBRV|)KyC17Q zu9BA6Upql2Sj{9vxafu5|L`zxm~LSWco~|1jdJr(H3!&u=K0)NmR*c!7jX5<+2F%J zS;1Zg{pEn_fRr0o&9}2r6!$d;B&EfQgV{|{`3PQxIIRkd#A7ws9DP<<#;5iiB(h^~ zsm;z%rckd~&CHI39p_aY9D`}-iY;#~=G|j_I|#*1fB0&c1a(pGQ+y(>*7kywpr`!- za%|JW?;h>;K)gcq&_9{2KK%B8A8`I)ShM%9^nCA)NsE4oJ~2ha&K=5UXc}vE4; z*h&q?o%q?hbFF^;?bRJ`!;jyG^aPK5IzH9u5=EAY%SXj6QbX;h2NTY7Yhjb z)&&+;GkzT;Qf|e$eVFUyhnv$rB^F+G2M%%^{ERcP?{sL@En%jMRWc2gIbMV(Q1Cu~dPEeNV`H_?^ zG5+wRym(!v_^a&>QbbWiD;n1FaoN0AfJaE&7P=g&X3=FGQurU$l*Kb)j?tlZ&r;yH5`E7l+)~bTl2}dOMQas+J0GaZD_O@L~R}%hL=cMec zGVb@6UabX}fM&j{eHj=@toZlmOCEP4*v!Vf5p4y4G|%doLVPrxaUM8r-83GJvTW_R zm7x zu^M&?km8sf(afiQ$`|;WZIATcbu@tYEtMZURt(g-psT1=N6;+=#D2-Gz=U586!}Ab ztoU(6H#bCwQMkX_X6-e4R;|kJ*WzRaV#z%G*X#-K)Kd^K^bu~!J>vX3^FFC7_Ty-4 z{^dv!smyJ6(RM+$$?;xVSPAICUJBk}+|v_pz4nW|L()cs}1J#V^&meL*%YY9&>u%1Ov=BJ`Z#7`$7fctc&j{bT<2 zMsC;um1)o|(i>_L=8~VFCig%2>CFF|ny0hPpDXB2)~0}AfwcC+`{~Z__b9N3<8asB zLdz^l!!4n(TMtuBf2&sK!Zd=ar%5Hp|C7A3)HuYdzT zko_3lFd6tBI{^%{iD@(B4R#9^PShP*%t#2X;%%^)`_b3K`)52d-7ft^K;@P^8E0o? zP`T4wr3+s}re*Lf`fp4$q(K{`?=Aii7V`%U3(1^)T%0UO+v-mftEC9jx9y>h4u zW`Wy=gRrZf`DE=cJ3kbq-RAshx;w#v>F$+;@$4hET2Q&xK(|KqKh{whwhQZ<^>!X zFhZ@c#h>{ES6o`rNeqN5QA*e@uRr>}+~q0=hBrHD`{RZVc47>J+N+8dq~MLY!fBz1|0B35{P6*E4wAU90u>JiKw|= z9Q@&L!GBJNeS^~_+Oc6gAiregc*qyVsBen#4qkw)V#V z<@(D`euOjkQb&(<{@Gj^SaFUwq7 zWNx2s>TU;8mlMs;rYWXeuSg`t?w6>t=m5{?42zu+P9H)6<7h>?U6mDCq0bF3)$}xz z4{>JaJA#*7j;wVvX9IIe&3Dj@EsA3xf1Pz!e`{*(D?KYdB7Sqt*kPI6C<;kTW(|z(0bJS#F+jegZ=qkZ%ZKIC| z7q*paZ{>osy?k9=qti9n?E3Off|fY^!bDY3#`!}P#P6+4z26EWk{^l>UeXv~4=~Ij zJAxJWA}H0$F=pq?Mc`{4UkGgv$oXS9))W z6qxLE$TJMg$Y$!--~!*KjCvwdJDXaz*o9#QlNsHE>V!h}$B5XLjrIFfHY<;O;O(|Q zzd1O9VRrUy|2BU5@OBHu>UhuG#rwJ+x(P1-O@sqWbn?0%-&y)rs4d{xW|MOhT(;kX zcJ?+Y=m?KcFz(VCRem$)mPNMy!w|dZkJ<|lxO>GRtj4TaYsF`L7FtkTQyDD?!X;i7 zfgdMdApK@pOG!76@>*mM<3Bfq3IFQZi*)z6y!pg4tuDF8oALZ{if$^)xX~Wtx1=*p zF|z|So~Kt&-}eBgG*Wv`KKEf*~<$xKfnG%X> zm~Ne5{tR~tB|vEaT?@$*@!uXI?*FQQHH%Ed(-odHXSbU>$a#`@M6-?P+a>7nn<6;FkJrXZuhy_GfBC&ojQiOC0Zxh* zq~Xv2jaLTLZ07uIrakzJ{h~k-WMUkSSXW%6TK^e`1g%3AReVWiU35)6QTp3$hT*9G zl$BIJq{Duc4E#8S&6P7a6N$)2thE;u)&Kan+L)O1LqZT{--{-z8bVACRHOlj7a_4* z_s_W&zIvX+r{7*CUyMIX$&ZNl4lOt63*0h6Y8sM|0J03BVVlK<#jJ~if6)C?wiH=aLTDn948PaFnI6nC{c+PA@s=bq?CMsQ=y`rUk@Q-h;Z z#Sn5Wr?fB2#=rS`tpY~1{IeZWfZkwNlRxMSwCWMRCMnnh z?tWJs9+{gqpCW+q-%%xH&{?(=dKvYPgsIil;%K{?w9u7taj{}-<=%?xBJK_WXbx5!A8V3pL^Z&*~_EC2PVmJBkV zD?Hj0^n@B{kL4X-{TngeEx(tiyf0PlY{1{z=Eze#_Wj+k0K#;k|$z zPV-`?MeYO#kibC&rSSI$e{7^uCBENJD-y6tbJsfukYS>RweRNct7n(7C>`MfqP8if>gP+8 zK{nTyG}MvCoAa(^$~SaoWQSU_YNE8w=VKWc481|j2m$UTu;%CFmv7Qe7?+@|E{@Vn zJ#UUK=N|Mt8XO{?z;PJ@nzBF89xV5(lmFdNA5l z^@P*M`Y-Ib=SuG<2m1)J9r|w9$bMDi*7@tK<&MK6XX$|#x6I;>9M0hJJeU#v3`S?~ zKSjAG$xxFD72(l{fC4$biZ%cYx2~`mZHPh}tD-`!ubHUsynXEv2Kw1q@#j^(6V72%^{7cJ_#3t%ggy zO(T-s4zyBg3Eg|MbE~~o_lrIU=x1nK10f`3H);qz4Fp)&t6;T z0SwgMW!tK%SIi4<9KOZh;u)=(+>nT1Yd+K0HJg8S&yZAL(yKnt1)E)CYr+n%xShx$ zDmlaa#c8M+l*=CIJ*c*=idi=4Pb}mIyU6wTcawC1rrkn4QmJTz>SJ9=butXcl9S38 zFfz|9eEEEj`PTx7`df#;qMm?4P5jQC)L?tE(|9_vGhi3vqM0 zww};@xez1Mm=!g<%#2G@j5dCv^%31ef2TP3oT~Ze?z~t`DLzG`soV;36%vS zEmeqv@EN=_VgA4L$^SBS054nAV8Of5bj&&;9O$$kF8F9X6E*`Y^}pb<05uO;qDXK6 zY~MDuW0OB&_6E}Re^ z_HKq2`fEPKo%_XlM0_ox(C<}!;>Dx?Feu~a1MUK#PxkBX^X?>|v81Xi-G z`kgn>b|e8SAqf(?JQP=neD6jnrU)|jDBbM@*`^6O!VKqA%+xc}{ij5(;#!Juq?pl* z>_MUJwo0?EpidK1HXXLO#Au_t)y?BkfQ5)8ZSyFRlCOV1Y=Z6Ug5d9wqYukbscUezK(OigptCs&Jz~pbNF5M9{TUPW-Ir`Dv z@eaymJWW93s{UX!*SO0>>(tc5AC6#3ZtMdk48VB`CF1$11+t^oz8%Vu38u|(uIY5N zvvh)NGq)DI>LAlqoSWEJ-F8lu-xMOrnViW(K<1JsTL|>lcWWKjZ{|k&g6gZJ{RE}2 zD?Im~ZS(3ZHLn6L%l=a_=5(_#qXQa;QJfGd6@vFQ!1?-<4mE9l7%7H5_gH&}EmH|m zIdgK+ZD9(n-wx{B3;4n?o6L^Dax^9ui3ZvxG)|-oelQQ(bIg4iza(hta>vw54PK*+ z+twCZk!f)T6jAR!sW5lBbHv%zI4>i+s_^)hDqpI}I1M1w6=4yhULLM!XRy9k)E7E& zVy^|mdMwSnANcQzt*HGP)Y7rH_1uqIwXF+sm(>a$FPnV2?4P@Jqr6~z7vdn(x=QaJ z{v%(WbDJZV`<0}MrZF!?&E45Aa8CH$+A+WQv%{W!MCWw}9_iY8qG zMrV1iWKmifLC#>?g-_kx?p{Ugf-N&v>&da_UOzYlYRuItHs9SRIUo1hxG@N$%tlvQ z-a^?mJm|=eIi4q+?OgH{m;4AfC0cpx4eT`X9m(UtTzzszY&Xu8#1XR|TE4Sqj1^w? z4OUhTY3x-%aABYY%{ICS14QHfO>O1r*BZB<=wYr-I{~=IZmE9nJu4vmNH08B>g-@u9f4u$-V7i$2X8tDM6N{eB|BZOJ?FMsv8}kVFY<4OOGvI*9Jnb)`~kHqH@iPTN~gvieCl{H6JZf~|n z^9f$q7h~JA?>TW`b>cO6T(H*-P>sAtyzc+2*GXTZHH>0(f;1PVI2i+x?t}K{wX}at zhR0n%KEN=$dXqz&DcN8`0nVKNq&R&6f_3Ep=K zgpB>#_4@Y2^W74c*Ew_v@(XVk7H=y)zdRS+PHSO?OYa~ z#cilLwJ4xSiT3JXkO$xGNpzSQrOb9}51*&dPxJR)pLhnwBLz=$A9(t zcmG?T7px<-c3$IOz*EDNZflXn6d$L_6dxvF6n?HPT+Dq(J)k@KEtt5W{aCu$|ObV z0rGUufi!MRWX;+10v*O~AUs>^;bSO@Oc!5qmuZsj&vzXT;}fkUKp*7j9C_z}If|uh z>SwpdhW>!5jjwxJ3_~e}HQxLqfKU3`;m;BvaLTusfpZ!JJ9aI2fy)Oe^p5mREX+No zDzm2Hn%4c7JI`ZKlE7p;abM`kM0D^)s99Kcg8C|5-MECx`c2ot)BKYNZ>ta#67WWl zQ1=g#%H|%+IiZ7@d()G*fpm>>W@~3lAA(;T4I(1p^C47zmy7?_n4&!bLm?3;~vb42Wduw^Ccl-_* zYor<{FPxt7v|`Vs#QGj{4Mspu_6e{nfGkO(I&JS!r}j{p zb(_dS$4py9S(+nN5;FF?8NG*y#X4V;bQ}8#@Wf2~SowQWpvm0nwzRo}!O%zQp-4Z+ z{r;bg50^hHc{sEG88Zz8#8-5U0<~6FLkdVo-kS5Zoa%2Cv?3nA@G)Jc;Y-N<2=VEZ zj{jRZof85Hj+ifoHc|-=IGd?_ zh1B+bW^~DrT-;5IOyX$C87paa0LR-Xi8SJDQN+$hBjA07^fL%&r_skj{7GT z1jmEog(EakZ6Es;5I^nk;PJR@+r5s8aBPpSf3Wl}ZG| z#22OxFFfS?&K`Ur&Hq;}b#!l)YJI0pZ&KnLT$j7eoyD9?(J`9k- zA1pYM4l-R;o@9he{-a0zMDbfM;zzW&xx{%BA9xioKK3Cm6eUD0)4EbtD*-19Y@}9?xe&09TTWk*FS^+aYM_dKU)((G)Iux@h z=s#zL#NSVIdrJ_%i(u-<*tQI3y16&!$S0~D&`^@nel^`VVhvSixF*}m2-D~=I zndMaYH_o-agny5_Pg?@uX&UgfqWl-2PK5&L<%ex>3y&<<^6j{ zVrqOu#+z`D(Jm!(t)bHU{o75}h;zb$BSxt2H>cB*os_B)X2IHszWBy4C?z1}O&mo+ zRFHH5IN?1`@CA@plhT09UmBhKxs3zAxkZN5Zm zHNQ=3svw0h^4f624w5*~PY&GDt^Plm*jymV`s!`%)LpGZ=(rpxa< z^L~)y8t~NFe-Wt#bc8;8x2var%d!eXsRg8?Jagt0oxJ@9Kxc7wh_uS6{82=<^bk!c zS1ldkayVzMG-O&l^0>p_=qUu3huctHBnTY3cE)*oq*??Qx3g(`6{9H&NT?;dnUBA< z+R~_a@i66ZB;k;`ki+U+CAMHfK3hr@woq%P?i`zg0d5^*IQ)on^_?lVG~KIcXrL&L zCgaa+$l5s|g*V!g{*nzmeZn!!(nMLf_|1ZzFpQhZOeJ}V3O?eLYX^#g3fAkiC4wz5 zBb;w#58m>2Q~)sFj`EGIuZ9mpz6;b7l+f82R#?y%-hidKmw()sPXDg16HOaEcnf6~UVq@?*r~*ndG|g~M7T?_2 zEUHVl!aIq=P5x;a1vcO{XH;pmK`9Of2NgjNyvQet6^$U*qVGRzzY~$TTZl39U}GVE zX#9obL+RS@xu*|W?}EdQ%#LYHFm4cGYQKk+oIDKqL!Tm4L(W4R)8-wj$V-hK9aQJ9 z+A-$4?Ne^J&NLT2<}DRW9QY!L>4D+M#%7qc1U7TB$WHHj2+MW+++Gii zc#U?CHLwwd*^7CAj}i5~TJ~XNsJkL4WA0eW`*<{L#XEv7tui}!F{Zd=1Qr#Q`i~Z( z1^DUnBQfDZxZKfSX&Z;{*uuMmLbg5bB&yLYmg@u@n_u3LCK0IBJ#dx!`N2?vK zTE#=H^p8YV_uBe8u6NtQxmi#gU*J$-`kZ+-v}A4Z0{-8)POzeEG^iz7VJ9)F`d*|By*$}-cB(NX#m{1dogGI4R&*( zW>Uhc7>+@jE_g42#NkWM;~;SZtzpdWK$wK9Xz4{`Ys_rTRZ^;b|Co4We#-kWsY0`u z_r$P&LwTtQ0rlJ3aP<+8<<-F^AQ5aw@a`$IsX%o-nb_${3s`qO-AZ0$fnvly$H>3bMtSFDM``Olpf{B zrmQO3lEjj-x8mS;lrA`W7`CO}a-Z90O7}8Go9Z@{*hLw+r*hJ)L_d#&Tl|OjUYA;lA{0TR#~AUW%t9Z}nrmKQdX9 zV{+J6FFUhqB7APMvyAd?F%t$h-mi&_5{xjF(+A+!R{>s zjP{=;MXQu~PxNNaYT|kM*V1FM>9oa9>alajXRkY6MXYru6uFSJm}SiiweOZD%0__R z5RrSII_Y>tCyd{Ib@D2Gf0bGf^6CuOs=i%nUa~ddNnDZys`U*bKKg;%X!}NpP(S&Q zYt=6B;GFBV)?WW`{jJ3Yh48pVO&?R4dH4FKq(oXM&(c``?oPkPbK;EVX4_at#`fb% zN>$Ez`+f~8pP>5gps5Mg@n1d{x^=JFd0lO1_pH&KzsK_8k|>m@ z{)*`0Yhmz5WU!dBgVD&hto@YeD*V8<5L@FGB1Y5T!W1z*3y_x@KknwoB$Ja0e<0+&dbf|B1g(BYwf2KlA}_`t@3q%XCfNlUjjtQqw)< zlOn_}Oq}v}orb|~l_|M*rGO}~sJYVT4h*46vrAV+pijs|GN|MB3*{dqHDGmi{o@74 zbGZXQ9G7oYbts|w{WfemuLtc+k!IvXIcnp=yvC|(glCUd=-0~~kCb@xxy7rypy=DH z5yt|*g*LBTh%}}8g=1rW!ZV-`2W|RVQ`)AU1N&YXYZahTS!DTZ`C;^UuPKcc{@lvk zy`AL8;k2HJolFX+5sQbu}BH~b=-op=}&68V+81<%a0sLIVt&}6UmLk z<14W$jQ;hafL{cvG16XM;9l#L0=WPN$kD6cF^i>hrShJ(pgX0F=~>Z>8kenNcx)L{ z5}u#Uwe&A?MDkp3e%!(B!gA0OS(nM#PnUee-m!T8{IWaU&ulfx{TvH1vhhw2x%BbC zF1{SOv+sR7mN!fau5j8ZDa={3p4VOXPi8Dk++KQNoAi0FK#>5f?1J@W3M6^N+{^Fl=$mdDi5Ici8%7d+rLTd5z9SXi@ap&Vu!i!K_J3 zoXsriu}=^hR=<;c)U0e5n@hPp73pG?OE}gpC%NGsTQpob(HwuX*kOXRB zmin)C+Fv4Ec%S7Qe0a|VYOeAN;+QT_Kl%cH^Mq89__67mjm!9`7|6C1vc|k6q__RQ zl0?S;hOTgTT|^JNStA?X6M;yR&kC;*!sRVFBb`+K!TQZFT#H3v%Tk2|+4gw z?a_#IIAS8?*ZMbT{`UfzCdG zGqdG?Oe-wbi4e{pcFv2`+C4gcP^!E{x2OeOL<^ui^4T1)Z~w?6)E?w8=!&Wb;ssKv zlhnF;pfK*V?2-63O(^g9%?CZ6{_3>m#^zO9*w(LxX=TTlI%iST#pulXj3v*HJeo6d zIHsDb7{Hl+z0^YZ`Jmn_|lCI ziF0cK9ekx`xdMQgyVk9f5psoVI@4}YnQ`2@$o9j1pF`op3)z#gg@18ebQMuXSyUuQK{I9)k z=3jOm>jT*dlYE$;!#-hK5h{dmj(=m!siEb}K@0U9`ih5LM|u8_9xZ$of*S0yVo0EW zBrzi$;b)HVW9W(aVoTqYpNvfIsuuD-kHF^fN93^xah`$0d-w4)tJjbmZ~g8u5_40N zaP}zhr3DVLu`o~U^!utYtD9<{#@^07TGFb%G7Rk}&t)NH@Pa(+y<5bZt2^IFbioL zX-Tca$Y3#L*rg66^N&K%Y4SX4zkTx?;yZ|MhDYd(aF!<3nuF*BYP$BE=czQeGVe~a zTsE~a#*r)6L4uhR8^^;{`fo5YQZozhbyzTER68eDP1QN2dLH^gJ3@+Xj#=g~vxP}s2@x&WgsH&aXFxe}>!Riu zvi8$9SLTG`l#(j-!&zYF4Wr7R*FbWa7P&bDuH{g1XHQUP1F|;N>;N<)$TSzn(fD#J z)}ge!DGR4Bs(bp4Ej;dVx%P>gz4&Bxq{PFcB#5@OZHRwe+2Rtj5L#iFe~oo%#_6}+ z_C>2jP+A3{MSbe8 zJzOM=J_N`O8Ru+(*!zG2xvMYf|Ivb?POPgA6lX@U7QX&B%n>Q_E#7Qh#+fUAER9Sp z$@=&3=9w;b;NVEV{3>RDczd6#@XwUbk_#1yc>dGy{=?5GSRr(w6a&e%oOU@kbso<2~kuACJ zvsG=-PLv}p5)8G2r9McqNA_E8ttFQxE)cn` zs&cB{5D+MNrt&?b@gmt(fqf+G*l0=>=O0Axwaf#G$&$>9b^o8q$=>WJ%|IwYNyKUAaQTM%g{U;1Azf!R{SZOw`Mwq|5dS@ z6XRorX>Xn`c&ikk_pe!;X;PHG!#bb<1QeGjlh1C-igp`V+Fo^Dp@T_*iWYJ$RE7v;@V}u4zIWPx82mdjg%gtG(h zBAvceZAr#@f&9~e-~bWU7Z(W3i}*Vl#dnthCP9baF#Q}83tHEw~h zr-IEW4G?#*w0lovIUgV^2K5}0bU%l;`8T9h5P3)WX`e!!XuDu`AQUC7mF-7#)HKRk zwV%SkXlZ@_fVaY0lfHB9+`;2n`#17VZQx3(o7e+1F7^QJs$~Syfc1|puCR8G{+|vB zsWs-1eux_Zy0>J$Cddk^Buvy6cPs=ojAs=3KTy1xrW}7sUBt^qY@Sg|7&9t%@-4Ie zY?HM?uXsN5SgB+D2Ml*#IijCEn>=7=_=foS3D{R}a8FFm2OA-J zVrRm`aa~Kra3obGTcj2yW;1i(kokJl13;+V-g@Gx_!=LSud04F>K;2RvADg3m8~}6 zS(!?BBH*&>+1|F-MP@y2NKZ+8mTZs0pDHpu{v8x0Z3nh%ft-XG3=mk0d%*zhs)yq> z9f@FSxBP!r`JvibBJn##Z&83o;5a7N}YsdIgpg1h3iJ?1)6<=6H~o9QYVd z3jhiS(YAJS7cluiYc}Me6^O66=9J_B1{_Ya;V;`D*B?bv%k5j+hS*!5+@jYJE%&=< z?W6R8#EDSX0AHC4o}c%j>NKNi>YqY9T0~vDuA6nxcmuc1?3K?ZFR5s^%Jo&WAKFBO ztNn|)TI7wnfNwQa*v-AZPI@Lr>G`u!X1q>a3kg^WSHSrJ;=)By6xM!nzQvgr(ETO* zqHk?OY-xG;m;-9cf;2uN|3vUd0o_%(qVY!)1Xp=wFjvAo^7%Mdr(&t$EMxZ4?18)U@gGWG zAqps3Vz6Ofq;z>*v%e@|WXUDGj2QtKoO>9-tXfs*`^3xPa)KYKGQ(As6fJEeY0&qQ z;TYh#M4RaJ);xPWSrIP zue#yn*XKE9D{W8=Vh7848+q2c|004EsO+ z-pj3e;jX&mmGj*NGryOnBMy5&UM6N%Ld`VAr~5K)?^iLEm~+9|jV^a&o7+s{t{l{U z8wo56twimokmA8mL^vyNSX)8DdsV%pHH6hI0URyeP5=*S$qS`^qeldzqBZ;0aw4&j zP4LSj8rfU-!@>?=zjplL;(G}Usd>RSAFie%brCS}7y_FK;&woDJJ`qnACXfAEXjT# z!}8b_YD_2d9P?-U`7xvPHmq>7#Bd0Hn|vwt{zmi3c;ar8e&RRWm!X|Q5!8G z|7gq>t)+zPQN_%H8{%i#6fbTOE18zJ2}LKl{vT849nI$dzkj2uEv3_5o!Syxt)Q){ zw$!Lr5v#Ro?-DVqN^7;Xl^Cs2yNDTk1VL0t%osrs1VKcQU*4bZKfgb7a!$@kPVU!z zKd1`v99iH-gy~TTIw(T z_Fs|-Mr?CgBx*@MbGsihaW(#{-w)F|?CPtiz+!Hq22Kjd2-6y(WYhP{!TS9^Y17E( zE#@||RMTq1p`P@)2J&4iYS1CMO~sqTDLWM-Pxx3yFW5J;uC=}r69{75fXO$B2hnB^ zjSpjwyTLoncknt8E(V?TIreG|Muey?N;tl5%oG@6P{H|~)8Y+%A_Q#x^erT<)hATq zdHwmVY07ckbohzMrC}lFwu{%MZ|of3VC@hFQhdU(#HHlIWK=kK={42d=zi!j_%^;Z zX~J-{u`qSWj$pjO7UY)ZiBhr(`|z>5)CsLx$J-(ZQ`%l;0u+f{v}_JF1%9fH|tb zQ}c)z+E*oRuQJ1p#E-BT%g~l{z=UW<_=0VBe|H-w$=$DQnLKKh{+= zo~?Hulnyr#IOPdd7%J1az~n%6oj#j1LN>FvFhps2JEY>@qy3(77yUZ;N!8B8$v2pv#L7%yihRzAfOEJk$R5*AuG7V>B*St5TPC&>q*A~g>aO@;SJ6cz(HUm&v>e^%aqjD-!d7Dqi<97J>^sj%O9=em*IpM!AFL=5C zXS)7lzi;*W;BLFeWlD{o6>e*kkC=^p#_k>5wF5uNkQl30du)HRz%6I6erUI17NtM-Hyv{{S8pecIu zI-Frd+t{1@k25Xuf82YwT^$2WYnB!4Jt1v=W&XccRI@O^X7H?&QKO>dbNL5OG2{D% zhVNSP<3UW(fZWn8=7h&A_fFYlef@#2)I&|qk=O>F_dB}eO%1jsf=X%+Uwyj48mLG54|b%>7n|Q}7s}4syUg9Z3nEYCCSzcm&6`Jd#P2q+wdMMNsq`F6 zuHN%+VPoY_@uXwR$2Y^o?~)BG{iN-bo*RMyOjA?lH`q;@tuO9P&K66PogLNl6g^Kc zgdQRivpMOr;Db_~xi^t4YNn!LkRcviD63cdq$H4QW`RGU{>+GsssIYf(a#BX_6t;X}bv;PD5)1?& zZVKKA?{y)FgJa%6d(WC$!bcJtE#9tM&EG58z4St?;j-moPGHH#*91j;DPlI*(9%{G zSCo^G7Vaw^88#F)0+V-BC(r_rZXN(Jzw?G(9$oId7iTWumAk;>-R_~n9g-;WHc&52 zr6>Z{-piVlYlm04-ec)&DT)U-w8uJXm+&F|^EdVxBDVYYgcq)n$t`TJ=zLqp=AK(T z{Rd8w&MhgVQDwflJ5x@~%>d8)c2XS{bs_@LW3){a@ZRAti;*PKdX$qkm=M& zSt;|>sM7)X$UNcbC9f~b53Fz)YVA^`smf_in3ob&ynfs}sWjh8^~ktzNuMp>eOgr7k_{cCCoi6=S2uKqz0mqr z;Hwy^3x64kUzgXiP~+Ql+zkcz^*BQG-!r$i5re1yyT0!H-}QBVbfYm8iMGOFzXH$Q z?bN+e@$N=|*%J(S_eNi|Pc<8CAIc{Odi-d6A|VcK+nqo%`Yk<#Mm$ zxhfP5D-?Dv|Ao7#|Eddk0V~~DEHedbS(TELLXKp3bf=^F4e!o}d3vhDe*%9~4ECCF z#prftcK1vJ;hyKp3tGoNCkw|G1LD1NOb$=}#2lktUxOZ9v!3K_)$i9Kz7!eaeQ=V? z*kH|IxPE`(jmsJl4tjm&aNe)wXEdgxSf}HTmejV=a&loE=su%haHkhQ1-xYD9y}Zx zw!TOBm_UBcxa-dsCl|;rgo9R339A$=M3HYnldy#7BgY&d;wf-dNi>w@6V88U)0Tvv ze(oP08B`^lFKbN=DZ(Z)qSR=akK_U`jQkT3?BVK0#b7n-aLbcS@wy{S^Sc3}TPjtt z#M9dLI__F|&{|W#Fs|Ft=y;3Ps@&Sb{a&=-J2xra=cGX?RlVdd!b>D+xxb-`l=@)l{{AWdvSy-Cgq_BU%&^L#79hLMKrU_!TWYY|PyhQPf^cK`j+zd41zLDz z!UHw?g6>bFo^;})oap*D{tlzPMrR0x^<%8+O`_>J@mC=DB^~y%E6y!bak4^%1Sf1Z z-hq49()y%;6r~G6UBs(2mM5&m>$q;Q+OFty1!%l7Yn(atP2y8iVU_^{ntKE#GboVZ z7U>uHnD1MO;(a;J;G7BOIU0GV<-2V;<`!pu0!aR~t)a!t7VLy0C23;tPE+le2C1nW zzQ^fl&EZ!Jwrwp?drGLSL0#hWBe@kwC>#nDZ9e!LQGArhe4e@mnV_!!v4oXDYUJCJ zj;A+>G(r?s=)GfBi~Cqe-OtVe=MdAvp75LpA7&c@-W3J#Uu7V)H4RW?;pNRgL$XF` zLA4bpe+^>oI`>LzIGNsLEkw?bt7KcL zu~+uGz?6kcD2OlFV`b=i0lC{<6LL*Ql37~(c>e&hr=btNtBYFmGo$ZX5Xh=`D;l}l zr;2-Q;g6p_1lQuN#!693FTN86UP%+bao!$I2LEw?m}Q@`8l6Zd$O5-TB1O9D5lWsi~##XDrTU<<)pd%qiOv&tdw4jEug z?Grqo&f{3e71tLA`Kt9IH!wHc4onjdtad4?OZG3p75=pGJ&&4!{~99~eg6m27F;EI zv>a=-(tz(wu0N5yn);GwKOvE2cj>s)BA+F-{~zG`%8aHS<;Gf52;|`1A!^ptYPLG) zxHEI8rr0{AfW&W*ogtU=Q0(bx!#i>Q60#MWtnVi9QGZz$%}l^-rA@;OGkRB0EM8xyI)d%sEM_R1f*hMLc@9?%^pFkYDZOl;#-I?1|H%TJyTYTu{B$ zYli9c1)Q^DN%|d2H?6a2_;>|RHDzX)@fa`oPzXLjj2=th4F?<0tac&c?;^u^e3i*c zyE;IGH!Qi$FT|heL}2o(-M&fxgMU2lmuxmL0v7|ucf3vbF}h;DWx<%#rMMzy%DUPY zqLmAl*#(92BLVG${sv1MNXvc1;#%4)xF;yKB{lXH6X!Kl5pvxNN*X zN>BC411?&Et4@eYL)AOZlGvUh+HX}@PqoUW&~=xdHzj4RgZ5ppMR@rJzd&MHbMQuk z8Awo67rPEleE1Z!+1G2Y@*SxIZP8}bng{LE8aAK$z+ZdZX4mJsYAd8sLG@M{q7j0> z7TMdfOH>Df8rheTlS6h6C*>ik+#35o&Vw31>*0RE*YWckkl>`KEQ6CCy2xz}m)WU> zpgSH!AfYR00$$Haw4GaZap|IU?UWn56$aQ|IeyX^1tUnI@haBE#;W($01YD5Cv|HD zR-JpQ<=nQQbgtVV+qw&=o6vIqy!~y^kk5a@_3gEu?b@gvMg~jv66w)o9wP(dW`~Mrcu~vALFT_0gvMJ8cT9Y=cD*lDlnQcbDbK&uk%faWqU5T_ z?z=8i{fB>OGYoBzvIksrgTpFX%YMu9SuOARGsHAtZ+vUx?`!W++hA&Jw7D2Z`1D$- zK}Fjp_z9DuxYhbN) z`Q?0{_3FK(r9_0HIz{|}$Ns>+>`q9)jJxE53jhR(Rc-5Ky$K#nKBLgYFKLs3`rFe^ zxt%Q?xZ70MO8GLY;=lG2l2*bwwJ*E)WFzH0dVq`$Q0M6F;r=pNpreudf)7I zf=*JhIz=4w>Vs`EG=F zHDuehGzciC6P8k{E`(U&MxN9xm*-czu9nMXT|?{wW0N%`(SPdo^YSI$LVO-a+k=*P+*ePhWrmMgStE;I+lz;}p2g7^AwlJ3 z^Y`SxXo0s)>09%_vhY2#42*skP(O1Pz_F3yiN_=S@aIl{{$s59y6zJ!R-9X@psJ;X z7Nx3S<`VlE`**^hQNWHPCHb^BpXq#drrMoXJBPs{Z*C{?RD^|GE~Z*S<~rnPhNvYl zpDu0Pqrhg&dN20QE20O17mFiaFl6|=+ae!!B%@Yp|QX!eq)o;!s3>yTS=O;!RZH>el_G2ZpM|}4$ z7YTV~IW{cQO)6aOkpxN|4XS(KvA6nNVtb&z?zM zp&heRJo&^jvh*lCPr;p8+5&RwA0>gHoV_pFjaAn7XRy+kQK<0?Y*5BtQ|+y1&5Oqm z0;&hsrZpsHQ>hNzA1)@RpPF9w;^%d(Z6jM3QVdUXl9dQwY*xxPl$D?EY>o1R`CQq* z%je~(u&sO`5`p;FT|S?qkhk9t9-YzxJz-7`dXInDnaoobxxc>$XZxU9u`Xe6D?khA zC6{XKN40`yXT+}Kv#6uBf--hT2SHoaf@i>4r;u6Vg_uT)iq(`0wW)$O@cvVfsx?3N zkT})+S1h4UfTh`wd%*6ZQDdkzxW$#ZT#Bw++q5^3u|)CN3)=hlBlTX_{h>ceOeMgF|K8;Z|82s;!p}yJP#90wZu4UiTSSnTE!Ph7d?u#?)kwG z2#qRo4nd7Sw}Y7f{&lxhYWG9_r6{aHc;qJDo^I>YoO+uzau$YZPVgv5c$o%)mF=a$ z3?}!$y}o^8qgTK4eCDoC&BAxySH69$m8!uVQrJkT{v!cg_POSq?-5P_7S=PHPR8el zGImVa4BRne48Q$ z!$Y<7N&@=|&(_~tr|cff#4%mNX6?jvO0J)gTn=wo%EILh*s4`~w)RA1u3qV#9svqo z-hW$G#*;RhS4t{(-D=UT6tqHg%ai6bn+X$jDHn{}?3*-WpPy5Dw^g+WyLG{SY3AuC zun?0tRUp@}82o`*L4LV+ZC8Q&g^ppCn~o&*%N0>8!j`#&T+sRrZ!vS)C-OaRHY202 zHXa0c4U`r+?0T9B%NGQO*4-JYg?pZ@aeM$v&8AFm+?T6JG*?k3fH(l8RRxSKNF-R? zm@jY&J5rWQEH1VEBoH2F0YFycB1UrnkqMS|`HH{f3(CKw zkaB}lSdU!|(s!PVuX{gW@bl}(Kq{u?FPn4k=2Se;uTy*BHLTXFYX6iZhmg=d4K}6d%2sSIPU?=J#=qWk8tk&E%=B z!8WS{mShw_y8_}<$E0b*VcJqKRJQFD4m*ky zb3n>x0aeZrzixAmzYfOkYDzR|11d)!uIqtOisid0vb^N8N$%jvx`W+2EN1+(F)I&o za!<$2@v6qkXJ%Qt>o{+kJGtZp-9ODwf?ssy6Z2=)9Ff0CNO`S8g}{YtqFQS+Ko$|gGcdZ@HO(GUIPfeIx8Pg!CHh^g zp|2>-bmeSS?MeV1x-r60hA8j9V9FBGB2b&fMv9luJPPr+Fx6B!SwUxxozQ{n#0-}*QUaqdBCl>tSu-!@7C zy4;FJn%?E~4`wXof;1h7w^sTIWX8kct82P!r9}OgBK6jc(iNeZ(EG=PnZjbo=}u>9 zg{9=GimQ))0AVYWYPyy-cY>@oGj2V2^74+5h{kmXu_^Sf5|oItv}PScAHRf&-QLon zMq#N?ktMWceLp^`>)81G`ZwOaD6vMaTwu;wg)7PuVo~gN!3^xam{ho9{^};QziMBm z?qTOghQ6`$vdD-rq^e$hp5!zX1)(vzoW7GSn3tjsFJubbv{j`(z8~mYJUtT#0D`EqxnLV ze{!d{#2B?4;D7ZEOvORhH?Y%Fdm%POA2z0166E7(sUYIdvkFG_o}-*!laK zSaGVYYePQ!mR3tF6$a8i84m)oBK#_-+gj(L62ThW2Cb`V)VD3~nBLi_k)AP{-TJxK z3Dj4b#z52)J^vg>)X~Y^1!@yN(@2nysQ6WFbBa*Y%-uW)^kl)83K0YcxaO;*B}J?` z)2__8$AUWQ7>rU8QN*=F#xxtef>*vmBF9IqrnP;@Uk&wpb677C%7UR7q*A(_EHVjq zMHz(2n5wE6ccpNGDr$jNIJvAN}mSyWxFVh3$e zyG&tl3L_sP5f*%YuG)lf@~31??98eh%^W0h9uarmye%D>(n;i#?OAA+w6buV%Lzi- z{B*PT1{V++ScQWz&2pk~)`0FYJGnu>drxuz2`umQ7LH~xMjld=Q{`^icRf#4{2&V- z2vqE!8ufUlQ*iP;-g0GJAh=NflXvOlh~G(L3qz^f2AhTps!b`lNFRd#n1tlv z{LIV!S>e1`Hb4LLR88<$zz=ao)sr_4jH15d)Z_j`A9a%S{T3A{bSJS1XB2o=sS>qo zH)>rUuRm+Xo$aroX14ofH&)7WE?0Qa29UvbzPg~=(PGk|q;cKea{bWYeL9$7GKpRZ zVL!~;yyCSdyb`+oX7+@mm13ZIvNS)lDJmCi;$Dj!AzSoM=&j!M_>Bo(In|~+!^^hI z$Wi9>)Wll6{hyNKS8kM&AZ?ppf}6bp+bo*tN6`Y#+7QJCX&%S!p24WiUbmTRjGiAJ z)n2U&W+riZjHrp38`x@R(Wx|H<7?H1xkl6Pn>yto7pLLXX zihm3SGe2nxJM2@tK1a0tc%$Xm@J*uHI zUH;9j1T2m|kUbNw-v(@o$yz$*Ow4jg>-q3(LY=VKP7IP*wYXiGVTA`d0g>t<6Zzm9 z&XJ`Owvfpsy_aTu-}6GS^3dwV%im4{+XL7xXzPhJUZ&VASqD0X@ZzZ@D<7V*^`_ok zA8*-NZ7tOOUbu@!O6?~Qo;4_GbW?$To(#!)cjt-HLqi6u@5cRLaE8P&5dI`IO~|c> zEbA+(+P*6_F^(Y19!5p!wmNW=`^a$6Z*9H)6~@7SWsIym=yZL_$1`RrG;xs$=OGUR zR#gXGgpGiaow`J7#eHK|r1loUQ zTj!o~R7n}!mtdba6Q?f1Wi@H2BdZF+4U~&h3*oEzYFS|Q2f4-qoMKBFim-vuuj@_G ze5_Uu@mBu_1G=x;njcyGYOVjw_|NHvxF6qcG57vsXSkC*CeEL-Q$TL$K>-3aU+QKf zLK;G3$kA44!8MBOCcMSOTHeyGKr?6PwOh^ZTNhibInsYK zRufGrJZ@RiX^co|O!o1hbvKH>NTK&w)0f`RmtLQrX3$5N8~^iY8(VPagdV5Po+O0q z>u}EkgU9F%^xNHe5~6?BfAjuJ^8e%M_Ai4aeRWsBC%-nNkcCl$+2lQQm6-nWC@ROL zJ;r4Rd?=7JKYQ$%8NOsC-ilt3S36Up&mN!D%BHHKjCt;;_8V}`2Ec$R=~f1C*rcBo z3~3wS8Z7$&Ec3hLwoT`08>bCl!aU|5pSo03*M?Di*nzN*^ANqf6Zk?6bS~WGlj1Vy z@`A^z@ssR#o7IHP3`eiHS-?Y07o~Sj1Nh*trXTOQ(#&)B1#;`{cRP>gGeR6}lj1JZ zvX?Gc)SbxQ;rnzc* zifhAteSXtvZ;ieOOYZ*LS7xPYo5!u)xxd*KevqP{5~tT7UH8LKe=oT4Ux33!k%zZu zT^cW86>EBKCZ<-m9GZI#s|m(n#$|(DW*h>)DjL$?&;#I)<@)>*utO+-??#JuKTg7m zKvj5BM-%@W`t<-5N+5{meb`W1_K5n*aPgm zE1;Ed@eh!6PU5@JRe_jX|1!(`60YSpS&dq$b6+-l-?ezx{fK;!@u+?*2c_sVcKp1k zdMuvd|IoeD&%;*;iT{i}#5qKMTMj0iQppleLG6&k`dfDDN&)--(7oc^CGZ>5v<)CS^2;UfUYE^Aj zNU`)qq+chTKRfe=0rIfVH@@VKAORDy3{(ldUVe7p%Pq@pNl`y&=pe{`6-RgHl@%fe z2|>=GS~R`%8S?8pX^Q8!vf%n%q9KWTCK| ziZp&hEu&aI0rj|@a4|T_KEZ1OspyKeAk{ZAr|L8#fQ~{MO_^DS1dQ23xT-;!dd8}# z;E4J=;iI`M!bKnR{mmt+2iCv4Gt)n^E*e}ISV*6+WL(mTMKdTQ=~m`jK~ofb5Oln* zN3CXj@8XTp*~L}=$S(SJDmhKw{B^?`)7M_Fv<|FrJ%(o;p^>3-JLf6(jMD_^vgwN2WN%Fgf>-RRqE-Yvya}&;5L@GB?_E=n z`}3R ze(`J)h*Hk8%Ba+CEdc>7ZcNo4e(U?Zcr7nQB2659*UsDac17u`llk#Nnw|G^U5v-7 znH;~WZYs1m-y=HuIlETKp8nwOy&-x=OJpEVl8K&#|2F!mp#ub>bV7!JtdqV)x( zYxMg$-V8Np(s1$*+qTwZojR5A45zP4pR>(~s~)jH&20>u&hNrG`3^rkUa=khIGs5z|KIkjo47kapa1%XI?87rhq`7@%8STFt93WiSIS&S(*^ek)n|}ys zvQ2M$-39#M(qTuhSVY|o}ZWOUn*iKvPJe>U7jLW0!g_zV??sha#}`Syx0M{98Ex$kCz7U&j}V!zOG z@|7I(uhOh2Z4Iegv;VFHMKzXQQSKy8?{_FKFs#4Oe&w4)-+=C5!YjV}INs!!fziIA z_G(s9oBR9zH_lhq?k{UYj(4&$zq8JrA_y_@ZlCx;U!N)}am8Y-@T!h7Sx2f=Y6Kw( zMvmUpML`juKLKa0hMZ2J45Y~|Rm3KK!@|@#851!|IVo=n^?ZEZUXQXDeZ=`}O_c2C zB-3eWsIqNlpLoRJ#r}hw?;1%W6=S4uB6oR1T6r; zC2#2FG?yLAWRjdgvX=JCeZb-AWgp83yWv*|2dDHCdmzfsPM@t>!yA4$fMY>fVm$V& zkCX#i#zG3Xa~V5}u@lR{d#l-1A@*)CUqGqS_5Q4hO{U?6YbECB)%l5f#RHQ6Ni*ZHnJ_=z`h{w*h%EXru7n?K?zP+ncrvnhFD zMDd^gv+ScSMfSsOB=eZ=b97Tp?&+y%2J`b^pltB93+nC@VZ`KxUaZ{&k_&cicr6P* zjvPV+hMIr_Q+T^8$NE;TbFdxAhK8OQMIDahxjdXM7+F6Z=1DyM+1y#T^B1?y*j1O)m;i8*=|Eivu z4v~~sQnIeq0J*%dtx;a=Ou`*jv1LMzC(&;{ zX$nHv$bN1rLk$i%OHHep=X~V!)+>A{6#(6xfQ4;lxCFQfE^g12Z96j$&9bn) zfdR>*f%dhSI3Cjhw~{@-7z1|@H;0!d-z&o%CN>Y@Qs%2-Y$QLRAMP$au&sd26=E_! zDOzDLAiCo!{OMl=GX!{l#bc@2d2B=Il3|E4sf^eTsJSJv@tsnVa#-=r!x^_-?~d^w zoh(`9uB>45L%^)MSzYngM9iUI1k)#M?X<+)l;y#UTLM6qTo_NDopO5IzN%?Lk@GB~qdKCs^{(25xy z0^v8nNCX^{eN(JN_f)(ZH6ZGbJAymXir=)Se7}Ik`Cp_0gH7FnOZu)JHvcighDNf? zMTqS3uQ2Cmt~^w`tG}PxsdBP(FF38tdGyC;fbXc~EkfkTNU4aeJnKDjXcto?OkhNR zHkq2Ev=G#b+`HYPPvyoQXvRqzCQ)8#=JyZQ8T#sDVU?vkU(OA+Cto6H9i`VWZx9ru zxRs*Mg`tAQ8C#A4;<4j9nKMDxq(RXg>X(X$5yDU{mTE2(S#g@p3p}lhN&9t`g}#Tk z5P77)F~S)uXBw{=D?IrKhj02;KGuAJ6}-NHRFg$^Tq8$(s0WNj_|_O_ekj;M_~#ZS zDqRxdeopI}6YnR7ZeC6(Ouyxs&Fv@S*+os8?bx83?)={H(Xj9V&y)sQopbJJ+>hdR z*)24T73{gZ5h0$%JuSYdJux|LE8&2v89l)62dpbgr(zuk?NwS+9P`8C6E%37F}{Gp zJ!gSd`6CTTaF<$#54&xi`{1tSBMptxyuxPiU~$$or6(F&I?7WPW3{ePY8%)uO3X>m zf1!$l{N7&9LI*T29U=U$1+$N@36ZZ*zAAod0rcX9g=8fj9uN^}Ek2PhO}1wHm^6at zD(9P3k+@W{50$egiEv>6_U+Hd)IXXqsWz%CYef`-InrWDP<(5_G6l zy05%g13Hw)n&I%XMb*{|IXBKPiP817YGriHg$Ckhm%WJD%QVT$H$+c{c@77$ITd4* z7H4hO%$D$$87n`Ti9Y*VOafLZj$1E##sOUHeUk$ZAS>Ca5m3$65@~=;SLvxDrf+l7 zz79Ou#+s7)JcaKqHO;WI+)(-U^AK#dq;K;JeD@>&8a|z$J-XYxjUlJU@ax6uzKDrq zT9qkp`CMU1P$T|KsLce?7+QYbW(F0wpjZveG zz7=shR>F7itD@g}Af1>NC?z+uCs1-GqN@C{-_ugo;ozI82&?ai$i3^0QJSio#XOeYi+`!~xU74%8Pv zDCYo#^l>O3RJ1Icf16ihDwO{ao5}>CQwOU!D0!+`+Jh0E5 zR`_|<)_|n-yo7oAd1=6XWWTdXPFBm$t34S7t!CHa8=H5I@3L-8-zWceDxKah^7Dw{ z6Z(_S92C~^4ZnUp`{U44^p42;U)X8P9$xaOjZtvwG8M!(cPPt4Md*SDssF^?1UFbe zg%9@$-uj&@w0TXG!v}uRh?&dH%c|u`mN}1KRh#LJrL(9rZg=S-+5Pg-Q-m~a*opjV zK?<$wD9rh|!p#PJxyTLEFJDwjg%9$3JTQl2&nz{6@C7!wu}!zTxIsq)u(Gxb8eSO` z4e!}zLa7f*P&`32K0F`wXKx)&K>j=ws8H2E1S)3_d6kn6q)MT!yl7oQ5mqCWKuIK= zsf$$PAl^72Lw}~QaUTu^`ZO9|5W?CwH&P)+rkmDSV!-+7p2l@c34<3gG{KoVm#l*V zNY^Z+mpQYi%LJd9u=Ew}Z)U>$U}(t<+Q4X&j{$32EzRn(TfaxiKX^@D<$0IRB`5S? zs}sH6BJ9mbAgKTcoeW4*F6#lcuUocV-Bt7*{nseN^LOd$-z#o~5x;qH8{C>Z*$rul zs+wb^?rD;vYEJ$vS}!?C$wSG0FE&riSB~C_wC3_92Gc&Gn|2PjGMVcL*#uuJ1F)OJ z@SS*RoFsO5%A%#j?8`YCaaqF9&Br=lnB1$i z4+DIs22_e)H&@d*Xt?k>-AN>X1u^_&uyo(mWknV@w8Is4!7M_>(3cm1U z#LTRpsQ}AEMqgLA@!_5~YzG;Z89e7)mz9~hE|v{L8?O{VMyE0^l8TpaZ&F% zRYg&3A^z-%3uDN6MP00=X3$W-u|P!gUxG^aZ0w}PZjbqwsh1-y5aKtA{`5H$B5n=v zH2WXU&sG|?Kh=mrs~75&oz(fNT4{{(HtvN~bT@61!Q2}g57WgxJS@=GIq+0&nms1m zNz_!jGQV(QBw0ptAhFQ@u{s=USD8#Xv@k&!fnT;X;sZ5`^uPIKkFyg)CLkZIrixt_ zw;kGWKY!tr$r`46k4v=-v!d4w8iJv=MG<>Ns{2nJ)ft76FV)YJ=U2sHt}jH3@SVWB zFpMrK%ud%KaD%yzU44Z+i)A_uxbiS`;L0P=%E_Kb2(5(P5xPXJI5a+>C}&yfauHzf zyevvRO{oZ}X%2sMasvOt4~M$3>Jh#|bjCLJET_^>WSfA?fh-|Hk%NE_D6EYCr{E4E zJD-5g1Z9}9{8pSnf+V6K4il5#W_HRYeG95yB*`N`mK69*IAt2#_XcL#-F@yB@j3O< z`04pizjw;qOCPKiXQ3OUkMB0+eXKm~KbFbWo`l!Rm3%s5d+h~zrw=`Ut6V?my0rfC zqX)awE)n9JiG)j;wtnCTIWMcW*0uh9j*nt@f3)2z{*puD<)1{_@A4tI>gbQDn2Byb zXDi`Eb0K+o38)&m80Z8lGM=LB$bgScaLMA*Wf;1-8tAxmyTcZB{4Zo7_#XJYLkdAt zlcw&6383IqLL7%v;uBMOU6?A^rsE6zgH0v%`p?VlY-g}@cn-0u0;3icy9P=%9b9~q z_AvE!|3+xU8?3WMI^g0Z{C%6fPkRFR0_q5#t}042iEZ}C;wAqx>`uk4W0Mrx!16h)%vN0qM6M*?c&`T zvxhso8sh=Ai<=hcg>Q81yDvWQ9dk|K#N{eUi*iCpvX8woib>{OPRT7rI~%{wc#Zb+ zz|^;tt@X96CBv4M{8sC8x!my32ddMDH-5Lfg8AKUQVs2Wt1oe~7IhL6LoO#OE-4Ry z3*Mgoi?4=R)R(9^_{pxDJzHy57MAqwe0Mcs4_KgzK>kxc0mmX~-ch##vDp?%n@^=n z`|!%3Vl0!_n(s>d*;ff(H5YEntMT|nN|_4j5Df}Ds-`6)ma91^M{(iFRxAA^i_GO3 zWxy=;TH)Z{AbD|1=&MIUh!#i+_7+x5RUd&rEor>@Vbay8WW(T@YDIFu;36F6Th_D( zgzuT6#~b+;8BTF9IUKz=0io8r105H)?Q-_iH0dM*6H`wQSZB(z>%_)hM4!tP=og<& z`RdzU{ar~)P5Xb21W-ynM~2R@msb+RWx87Y_Z#dNnKp+f6KHByU%M* zQbNi0?(-%XSk_&)njny|{?(f4LmT;xX3B;-XUw(Nwb5QBeqK!Y_QEFl3 z+j-3&_SfzKkG~YshZQzs%s{+7hvMo_P0+KI8Zndtt26Qm>;{g*BbV=LLgUNs53Rd5 zYkq!|T?DaTvi9>XBjl1<8ld9E3Z~809f9f^k`OsD^;x8%eX&9 zR#8-a7p;Ov%YH-Se?*!8m`PjqKv6yf+^0p+cc&PI;;o0&)*v-^k=>k%pCUXf+=0Vf z#od}wI~@I$9p{&OTakSCT){1jRC@U{vQEkshe%plWTEyv4`O6NO%+^srB@N@Gc2OL zq;6sbxiY2L{?T&1rgV>Q_>Kj)f&B#RCympW{5df^wVazR3{_s(AbA3md1i3ye78JTqGz6xRvw zJJ)~ZoSh{0dICb7v;g|&qE*snuNoEGu9Uo#@MmY}<9J4J2(NeWbjpyiJC^L;Dfhi# z<~ejP(=26%DcV2y11j@f4$?o~Hiy;FaVN~dJ%W_~SG6J=A@b7Z$yvD#5i?Lj9#e=jtP)D!$8z=8+{`cG|3-S0%E9oGlGeLto||?e`{C_VYGIH1VCabRKB3(AjzCbrr#^eB9-Nkv%Z$e9}ojSCq=B@nk3W$ z4W}UPk@^pNqG_bP#84k=zE9Y|e<8#Fw$_RzWE4V*3 zg`lppGJv}TY)$Ra#Y_dz)bats+=*+7_3_Hfe{DU#J$#UYzsgjOJZQl^L$2kL)Q{v1 z%W18{ph+@VOmpOwL67aMKq$uXVXCs#b1}=Qmpi_(0}=a{PO#8a^`^DXL)$+wqbFfK zE)7w$O-f5L$s%v{Og%n(^QjqxM$8Jm5ox?EoLc79L7pQl4zdNiTdA$KwUT3#QLi=) zvB!U<$RZ;if}$pP(wvKZCgaAMkS@Y>7$H&<@vbIR!3v)}Yc7TG8W0Vr)njpM&<%gh zhu~GTy(TU3?QLJO=9){}w6Ua5;}7$rfbuE+(Koj?t?~;vmcPl=v%LpXjKn!?FPzS$ zu#9JY;zW1{C%0S+x?(e4^=0={z$lU_$Ov`4>+{gL)OMx_^A1brYy&$HBs$*;`cY}( zOaRqI5PI{DM9%G>SAX9c_UwEi8!-l%RGRt#>FH3hunza&IZ*F-7}+J*F!Zi6#ff7S zqmU4)Vb@O5FR2KC!XFk5{>%_V&3VR2=TFLa%*UCFkPO-Ds$mo5M#M1YM2f|gb%&7p zX-qqNfw`tx?l)hGpbHd{=x-WEkWadqh6EB^Ox6c%H)J?Ho+F5d!?8R4QSk~MFPS6- zUt1b0WDglt=$8&EpXnt3tv#z_#eGLd6g>DQ;YN4(k3X50gL<_ryKWoUnhkT!x6q44G^wR)PQ{$vP+8P=z?~xX*z$wORY^yl_zF=OeeJwB?*hRY<@&4koKm zrSX0t+2O(E6KvS>Hr#suN@7Cj?F8sJ@ycu1$vY>`rLj0g6D@ns0d^cV=C(iIkCM1(a&q)IN?d39DTK z|Jr)6n860ySr93|W|P(0$C)7?W{HLsz1GweXX_p#fBd*ZwUnY(2*0v{Qe~LPJ*bF> z;3UVkOoSC+{Clfk{g*G?cSno-wtm5IuEM}E1@+%;8$OK)m%)3@+I)prmKW~U9!$OF z-f#cKvnmIwo?0h4AF^<_xiv6MlbJ0rO&pp6U}~_x7%KhN192!8R$^Wu&@$@#Ch!3( z)BQt3;^hZ#LPVh5zHZjs>ggh9qHvx|-+L!I<)erEYIoz$#bTl8;$Tuvur@X?2n&Db z{#~GRy$_YLZ1qzy{pa4rG=tKgxHSUk62{@gN@j4?y6ssW-alshsL1XNH`QBj&g{>3<6Qm5A}$NoL(<@l*Q#QDUB4!0Yx-R!g@YVCcNt)Jp^d_(%T zM|e*a_ zpJ855QfW+@)Et9^%a8kxJ_Qk_U_z^cI5!L}Zub*pO7$$p4T|~MHRiFBj<EkV6r`#1 zL`lJn?9dbieeFsi(ycB@2PwQ-^Jc*+F*@Rs_Ahdo4nBf=!N7&x-l&l9Ut$;VC0d0C zpTMn^@W+AY>-Uw!a~cdmasWtI<2w~_g2mS;&upLP>WLEbc6*Wv(aJ9oAiiQggB9lT z81mCKMlkjy3C!)^xq@oCD`2zEH(%9s!u4YU3-)yKX-+4fV~CXO3Ai*-uQX?+k8KZN zO%B*TWSJw%gYtJGT~RSNULON8q8D{ICFeXpZ^(<@4|5u zxNdwYI1hGYvyr8`H@wJp#1wi+z2Fzt+MTA~xtVkk&GnA+F8SaY2bz`1BKoQjp4P-2 z!Ck;#jG_EOzmkyA2{yjX@td&2C>X^1WKCw*-(RGk*tV-^cG~ zZkb{&j;$i4EWCtC%p3pO9vJ{4EFJ>bm=9!J^ zi}ZJ{IYu|22foLwEXpvNj+HJ!7u$>7GtyN^YiZtC>qII~gzBoX1D)A8zbW@{mF8ry zadQ33Hs-yba>Qn>QONt$KZ1S!Bbz{1!#_QUoC|9YjKt4oj_X$B*m8Iph~e`{{Rlqi zdE>DP!bp5^DuD5ZbT^l`KM*1%#M7H0vzo+h57*Ngi%K&vhntzA5m;eZociwLw&@nS zXaLI2s+VM^d))`l>H)g;)z`PzEvd8HTab{AC&I6EC52YfiIuDX`;G94b;`G>paR_O zDR6WQ#Xb%cEe!-|nyOC%{XPu_O^RPli!mdl04p`J^+^p`X@|=`$LD3S3?XC$=IB6q zHrU7SX8M0iZJ<_tzQ-lzHi@iPHm~DYZg14}8(!=fq^$JAu82LB#xMlLQq(OV5dstj zu5%h0A)D3<{tmd5>A9CXF^*eFL^$+8vUz<@5T%Nf0Q2GpeST(~`l-R+V;&Hjtvd6G zYf#x(k8vGE%y4MnMo`n!^5-8#AfL!<(60Lq!KNNBvbKl-(Fcr!*Lv5L1nALgmYgRH zDr|W-Ow%;(JxhVY+kZGX3lcWx-26>^G<*HjVoDZI(c3tHEWIOPW|%A(8b0)DKsEG^ zfa9m#Y1NdhZ=;bhQP!n&G^B_Stkw@C2B)zk=yAzsQfzBQ8qASF5}IS%Jt_ETFlLNb z40L5>*fUp#=y;&LtSS|$02l7(xAV-!wvSXqNq#iPuyK{6XfPyQ_6c6j- zy_8LI?GbZsq?W9KQ2a2JzYAW4Sl&%u&UXIL+r_}vH>%sqlzJvF`4y+|lOcZd_w>ldd7EerEn9Iqy)OBq&}Uo-ST&EEj$~mL0E*UFYrB$`DwGyip?+6veYK@1#sb$K z)4^*MKlVK2+H9D4clqYk6uQ!U7%r=3t3OX>9#&!U`nafEW;TLsDLwfMHC4IGx>-^H z{*o}B!&MQzS=P*{=s&|`fQSI=_?_BJ!^V(fD2FGb6h{WxU+lBvM4NDKg|dBCDDmv&$s-83CYMQO?r`f`F#ca)%%&bC^rJVO_;=+xo_2u0*y%C{Vpnv{x?2w~nesVl|k9h;3nA$`u*qgy&c5jL}m;G&tDN$8lRw zC!9H{3h!21qAaU`I>v-<+oRMGEjiXHiMU67ofdfv(0*N*0U>;?^EE_!VZb7mhSfxq5r8+-wM(0FalKck*S;(TwtoC=ZD17f=`%w)pmt*bUcb~ZL+v5vW$ZDGGjJ8_aOmz+EipIx(B-vhewY&tZ3I#I*>aAB~mg&EG z2nt+~F%#On)m5H|P1Nbc{T$X!7|LX7rMM0GfB$+tO{O9z1LGXiJ&g&`$Xc^gq6Hm) zq=iDww7c?XvgF6|MuFmDCXVoK;cvH9h7*NWZ78=ZA^XLjCDA6$!)S$TlU;1-u36gjidyEIt-dKlc{ak<7fb*9?CJYnF5O+F7v@aNksKZW3? zUy6eb^K(`kcm|T3)w20bvSk?-9mxkpkW=gcdYI_YtGwXOUD?Ybzd~( zc|FEf;XOo`a=RY!BcvL!2ct&S!7c#9=)mg^G5-Y#M%!W{Ica?u4&lj-nYhCr7_ICnp0BE z6J{uLKI#*B=Q9JcbOL-qHe42&Urj zuWIxX^wxtAYowEv?&x%fm^rbyqeY>>rp|2o=UVi0x-R0F)aAf9xp;Vd-WxfHjJDc& z{M!#3ET$%Tl?ErgS0;F1Fvc{h&Wh0Tnr(AF_i(_XTnAqPMoa`XP@!&&VoXc~P2oBt z->+=-Pgq8iN2p<3j8At!U9EjhGkQlA_~RM;(G=!nh13QaPdN7f>k@Zd#JgGKnM?*V zI&d?|^rk?IjL3e=0mj{66J{pgn@L-CgKnd{IJ#G?>xxE%Q2x42fVa2F`-8 z@WRubgVbN-%WZviQ-9jSS1I$)T8-^#u;F!y8v2F(;0<4d@U|edXkoVaVhB5&f~G?i z)(fV^pLqL+2=sM+Clyd%Yb*~89^|@i2-kB~`J^(WI_6KdY;L|nFzcP*-S&K)xyI?1 zEtn|ktPq->J&8-lS`52s6aNHrch9V-QftnHd^Q4Yr(WFPTMt4hbb%9nJ_k#75HE2E z-ixT%A3eoY{hdb+mU$F}B#Q#c2NH6UDrJNG>cdQipkG(!MIe0OvIouuGDaCT_$!pv zr-o%;idKfEEJ9Mg*fcb5xZUZNkqRFxr2)X8%aK1iEIDQvlrj3PvxK@huyuFIn=P;6 zq+#}SEunW=(Mkgv<=tO!+;b8NTYro9 z1hw4d)ktmDxJSq)(n9LpL-)<5%|3pCwEs9d9zg@McZ}4t9(?PiQf~n z{eK-l-Kq0t*jJ=m(Wb&x?W^uD?sZb1jiH{JRogCmy zBDslbN_bZbYrOc0qddER7aU^*kc`93-lj}DltO%_g0I={BLk@K=IV8{&3$L>qOKr^}^|8k9)G&83*JrIm z^*DoSOb(A+xS^JG;DX8q_>IGi8hJ0@=YNk z{ClS#sg=p4-^_b96J7WHWwB{p9W`;57?OlUD)e@)E`?az3s}r?N{_5_)QI{lX|zC$ z9}U$gamigP4!JpD7w`%V=6UrW{ZicB5xFx?BXZb3|LB{*z*65|XY1pxb6nD32(9I= zJ~?yCU0;As@thOWQ!6TXNJjL$D8&v%Amz*zbdj7~TICODdrzJ=Ah~yMLh_2H5A8Su z=>N9)@^}#-N|(wA-}6Rv=m=PqF`tItXwY@ZG^;tB1Orx<+PX@Npj*Td_u1Ffjz?SY z0b8z{+e6{+2byS0Z(Nvh+A6xsOL6P=TWI=ZSV|1ffvBvx%s71I{+#!*ly@ARznK(E=f6Di-V*&i z(%r7xQgpwgBMM;YSN$yfQKGbewPCQ0KPK$Tc9Ni>`3)wHJgOIyj{mBjRU=Fe_e@ zTD8qtx*2X>NnZL8g?~BT6;9P96S_KPQbcKEjQE0)VM!Q9n5exFk*|;ii8*2 zJO*lkDtqHvz;8v!dRMh1Fwc6s6!!|kTi`tL7-BVpi>xFUMEtwhf>@YFx`O?7YVK); zc`bIw8$^T`-LoTBu)P6+p}4|tUSoMHV=^7l78fvWP)WRt@xOOy zK`0>g7yB!sfzI7Yfyj#b%|6@i^66=q)H$CxUa0P^v%jJ$&FL=46C&qn;Qb-aw1SA1 zXVe2JW0M1p6`_#ny?HJDZ;-u@{W=lN!fUPduk?OE;5*e6mh8m-e^|qvzu4~mO()>V zmlK)%x7jJ~O<(*k;Juy*16X>+#1(%5T8!+YLR{h%-Sg;29!oYW#TZ|+;=B2SGtX~O z8v;KKSE*&K8cF<&8mhMhUFE5=D@B~gY$!&bd2FrU)AW@fl)|^wd*QtOR*u`{d&7AO z;&vadidWs@gLMEZ-9VKbk06Fty(e{ncGNsmM#_Iy+p1Qqf zlV&|3riLT;gqHpFR!o%0Q@t6V=H2u+ubMMnXwpe-Pl19XGK?EK)?yx8t>^rp~~k_V1qACSEyp z7$M-=ARy*QH#||@qCVX35E#~Oo|`Hl<0plpzZotMi=S4$9_<$_(O6z=R%hrcr|qf>?2=H<3jSTr z*wH0Zg+G_)=7p4)Yfzp6RM_$M=ZVWF0!cN#r8+33;oTP~$wYZ`nBK?VJzlV>Jt0IAny zA4~ml_BL}{;ukcv#P?3Z`i7m9)lylAUrr`_{k_Y2@-BDZdKaV~201LBvne!alC3YH zh43hFt|%4GZJ(@_Rn?}D3sZezpuLNm{-zg#qp3~j=5ScThUuP zf^v%o+Ya$55`a9C{>-tZF7H?gCLTRSkXGzrKPNYys`a7oFkvkHKLF3vr~0ks#>|E@ zfyZwnh5ycuZU0AdKYI}}XwshQ@>n_g(X0$C=$%}>z8)+gwNr#9?g^}aU^MqvXwV3+ zhW3ymzlQBm|Jw0>P=+z{!%B%Vg*-kb4_tPLV2+T=4;1+KfBFsbjB7l-JQc zYv3K2b-@seLi%~6hvO!tqV1RCVvK;i@!`CcR*`9h*hbiM>$sg#Cn3rBL2<@jT;&0QL>F^rPm&96oO)RD&yXsIN#<2^v>pf#J_A0(OC7XY_vJYo0e*!HkUxU{RXM~80dfn`iD&46CQRQ|nY9);o= zv^@ObLk)t{g*F56MJL-kO7qhbm?33D*pA}hK5Ge$LO(w4O0CcjHXE`RFA3?-60gP+ z+#}fjH@lVG*@@=)Ir=CmH>As%2q?SvPlYthFmNq3ilu9h*lv{^fk~H)}V2 z-_luRlQei5k^yM$>t}M9&kFwvcO7&?>dF-YSNF&R*~AWwLhRer0*=T_k}~xZoDRdD`PJqtRXOi`Y(IZPm+BQj~$P#DNb2bAH($BB7#Abf^4n;mPuV$A*mMgVoI74H5+ zYrHdt>+C1X)3(@e43*#}qF7`OYkETtZTB#RQ!y1z(;2egi%Nfamdr zf)5uT?z>pn?=SfY!}0lp;t-#tZZ%mt=w%V(=<>i_I*qQKyc1ujll5z zSD_KsT_%scP}L-uaiT{Ph00udvUrUNnf#ji+_{GndeMQ)rYt0sw}fh=fCT5OJd)md<7&5(U;oGVDDB@dQn%R$X(j<4OAr0Sy@M!*wvHq zvHgfQjEw8FJCr4(l0eaL=Cs=SWXHvPwP7+Uo~3PQK}Hv;I0No_>t1)B_w7LGTN=PD zh^VZ!KkJhCgD^{z`D~!2Cq9;>)eBf(4z5d|<8@w2k!)QXRq{;(fc$kgE7Y$$;HTr* zd};Z!J-2I$E93&pH&)q9RgUC;SE zo?0Q~g#bL2v^BNsOa(y*<*x9M>4WvP35)4SSS@&wSjxN` zy}A&&`l_|8VrT1iAy5RV{G6Gx&a}iVt);5MD=@$CM`Kl6o0-fAA4%G@x9+L`t#19r zpdFnS>1NHN$vxNTW@JlRl>CE;JRyYyji=v91CFb^6baRoH!tdhAoNLDJ-<^;tS@F%@N`WL zo?fP#Od$8Mv;VID4nzUXK#;L#!xf%(?nTVF`I&-%o2KPMxoG>8$qO1zq_6^V zRc+DNGqm!+(}EiUdYLqDWVU4YkM2*5J=0Y*7;oab|0Df0(Cde9uF{)RvD$r?D=@AZ z3ghr@Crr*rSTmvZGJAvnX6nfUPDuS+C+@?=^=oi&E9qSrEd1iS=e%(3geFLf_5&F& zvz3Of(Z#}NI3y1fJpUbcRuvb4bN$GhRI{&t+@OD9W?r82f_KO}qI8vfz6k^=__SM)BOuhqLJK2{LId^z#^8aSw5=j1b6#|(e6IialK z6j=~+2c#$F(3x0oF8M5ryb#aR2oAHU2}%xW3pLOD>mtesx3R6n(8q+A2c!sR<;|3B z`INI$fB*Hqmr9Kq4QX(@flVaeur~mMTHdY%L$@5FeXrsP9l^Np`T{jaT4l)d(SeXr zj^Ub#5_@XPg9WhMnoaBc5f}x#r-4oKcsgu7)=B>z37Jys?C>CZY|!5j-`m3Ew7P?# z2DY0*_HP&!`Nl+9;NgmUWuMyi?1$m&5)oA9rH`aI!aqY)b`eMuWTq zw$|GB+Sl!RLa4M!k8;<|l=teHh_IYF_|%V5VXB|o%-EsAw5T#%s_+qRJ_IGDx*O|G zhqhUpgE6)f(i=bjX#ir*NkBKl z!(1BOp+BYIrPId43WJIE%6qH^WyiX>zn9r~v%4;h)P02y0crwvXX==GS@;^`=L?0p z!*$f6X$eLp9R|Va21`zn4ZZAN#vefsaDo{3lkLLjLys7mwcbhA^FfwGt)~)U^FL#R z_<6&_ce8IESFqocwd>dA%59Zv`Oul#^krR-#CVmDa-%wwF}#*< z8FBsjgjIZ;&>4>lg!{eJdrp}za-Ck_e($VQegC$(G{xcq8IM3C;^r3(kwMo(&LoY> z%$fy+io4Di8ggtiM(&w^bd7y`nlKg+X_Ngt_d+k&U`CD@$G5R-`^M@cwtkh6y#tcm z09EO|c@aGoJ7s78fHprvDi2Ny#wo+|WzLhCv(M*XrXfCNh`kZtJZ$0(Evgks9~E~k=v3RzTd0fV z0zra&@1#{RaMfV%&kuY4MS}@@!PtWX=ayOwnm#)(ZA3|J*Jph07Rcv`{-g_9Du0n0 z7x;YF)cWbi)8qBaaow$B;Iv7B2nE3qxjULeDsV*0mAK7XiRHfd^a<-SJAS%?l$|9f zre^xHYw*jvISeAz(NO%)t&s9YAdU0ZBHe{6AMv{4^zF8=y z;rArJ{>M3J7fi&H8)KxNup~x{8Vgd;hw%Jxl^9)eIX2Q1B~rfP_}yE#L^X^%R)<4) z*aN8`cY)eZ|2f85T;mA`QuX~6EBf*JA;em~7d~@&NopS>Nu5zO7xwJ`=^X8#G0Zb5?H3zz4 zu4&Qw*)&?w-2Y1uG7!ypw{=*1sP0JpwJN4B=~ zEV8(AC;T4kSn)6q)VrC_|89_3C{)5mV|By4YwydH@FJC+Cg=tEjk=*>ZkNDbF_&&6)j~x;)4pF&fABmA`FsrC>NR zz5%U=6R&IHc`=PUP3EfO@!#U0PF1r!$EUL$-biIbuz@$!po%*b>{X((P!l088p@k4-haC+6sAA$+(pjqDz2r ztVqExMH|~WLr6?B-=CgP=YcoYiMqs{(aQW&SWU4C?md|#s^>`0-JjE+0V;9fB`0Dp z*b1xmq~=|q(MnYt<8-hsCzrFtz6Q$5<4mjvIION|ka(9YF|;5CSdf>y>ZOA7SHxeo zX$I%!)Gg&2mG9J!xjsF&+I%G%+K1@0E4=C>HccfC-E$s@C^(Ib1!m@E-HK}Fn+nRn7u1-k>u5xo2G=s1q$c!MQ$k20t~@~T^~Jvp zz(QJdLbM zpONq`gV0+9iML`$ic~oXQqEP=1Kyrnw(r3ZosnYUZ3h{~Lv(uGNwysU#96L$_V-n` z9saS_9o~25A@lDtj$o5Jz>DIgC1b&7PjZP5Oe*>##8z+DMgFp$XY4#y@IT6Ac1ZD5*FidB zYNV4peFRu_=5hA_nf81RRyy^xk2GZ}snsoODSfqEZe`bECN+=UQi^`poz74zYqPAv=E(}AuT%bRu2M<2t|YeA^G_Qe#T&WIYHUHeHb)usWtcMCqn zW;!pwZK4LM@IbSlBhx_+=#nYDv80p|-<@DwM56jf+}BgG5XPK34gHXPZ+0yJutg-w!Fa?Hpd7;m)Di<}ABLwVX?b2t$!@Y{W&OA{F}@kwn0E zl_>b*RXV#T+mP))W0Y}l{glf+@;@)~Be#eM!OaQmqbEHdmT;0m<_jC~hSt`1M1(Vw z=5}XN4xratBlY`#QG@=-=~~mWbKY$4XM`8zAH~@-G*Wm(wtDT0mR`Og(Z_w_ml_^> z_(M}Ox}p-6+SnG1O?+`V-#*VepOy5T)p?%H#aUwbYz|B5K5^rI7f$x9*f83a7B%VnaNEn++26wzyjJVk5xiHH z5^TRdT`*UjVhcWA3lEfLuoQ>(}JQXTCVHgHC2%!etK?$&a?7_GMZ ze4%oBFj!?sxZci=;a*{6!&{Cva&GmxtVrh*a)dtT;&JR#xrp z*XHK2$ko``={hq;cO4Ty*gx1)EDiKenUuW2bMUm#axcA$KZlqqU&c@zjs@znR+7 zQvHS0;E8a4cb1*-V1eG0&wFjae@yXOr>@P3DiIy^dR`;ng!Gw~sA+Yu-xt*#b2E+= zXT3k+4UHLwcK(_;WEE&Of-8)9j3!hA<8v9KUq9pGgHvJy(!!3Ne|(XOVf(>ePh)2* zy)3zdU|aWohyi+tlxUiw-uJxe6ycOSc>;K8*+g%>!FdXApC9e3+%+$d9|T=AaP+<1 z_8!mlgz$bF{zl}-0hG$@t_(UCCxwQ06n5Kt{`XAR+dwcW*yc+bHchw##~S5Kgf~(S zejX4y+Xd}*jKZ2v13tv=j!P;8Ta(gw&n*08K}pw!)yiZVA_6F|-pW_PoinCK#h;s2 z!-=+ zoOmhi=O0bRJ-oeS%rcz~vfYPgiT`*lX~u>rr50)a7iN^vDs|T*;=opNdA3QZZnGDx zU$n)ZH2&;s_wLROPxHuK8l*q+jvvcy*Bc_8rrL}-;GHtR5TQP69H`gs#NQvN2QlY| zg1%;EM$Ve+ejn@57l4wmpzc9^$qtJ%`4@vC!&!uzpp~U;d~DpwX#y=)C>7-3cH3cX}x3j&gy=44B%Gj3FlcsNH#?Q*7B_lpe@T! zr2@L|%ggG!z`t>($MdiyK7sYJvGG01hjAGOW|jI(4RKho7yBHi0f$6dM>nrHX`vtp zODWIFtoPhNZoI`?g~@iwEl$q6-{DbTe7Vz`CAVMqaVY2u>rYY~g_EDZa+AtX+Il7s zPS9No-`2QgJ};Qghn=mcODS3<5N$bSb7IEqYYx>cg@(XTH5#!Gr)5t@J{8!mS(&5B zBcl+Z;jo3T5YJE3KYSvC0?0HvE^ihZEzP3%U-Wbh@ZuV0FY}a=f~Yt*ztqcsgEw?1 ztiUK7!}9$_jLOX9gcH22qUD0~>7D(qJxn6`8^zHE+TCM4nsK$FwM+eyq#nErdrrE( z^QfWgjvTvJrrt*phB@Aclj~-TKjh<((s#lSRsJI*-&w*?0pPCTRzhUxcgW3?%Su#& zbJZDnEb1uIWrA9s4^W3Z3L2 zzO-Ea?Mw6P4_Y~v)x{D?gRqH24y<-2(_!7B+1iHaV|b$@7`k7WJ^S9$^rPg1ypl2=#*~!FhXvy838cNQDMV z2=B)c7rDJKn7U}`0AhMzKU=9j{qQ#ObK>i8Ad>U+d^xoi;)OAoTRNIok3Dp!#c&^l zNZ#)rm-$=;aU566r%5i;;yNtU^<4duksbt{XK)`g&XZa5)wR0!`z+`Y@)lw;+o_}& z>>C!(>>G}dp7O%a^KCtG1n^3>B zFo&h-ejJ_(c8c6N*X9mom;SapXiRRz{hTnSfC?Bj)gp`0>ur$8kZlU##IMe2TdAr$(+;i0PQ4pVzHch)T{T;8PZvs`Fy>RyqNrmg!twQoRSqI z&Zno|XJq7DQzr$CWIn&KgR@!HiB6||)5ppP9JhZVtv+L4!>Asie zajBMOLlHIM4wA{kO%FS0&ldkSlVfnNOa7n!==pC;glMwyaPZ0xUO)B%K zqCK~sVf}4riCMK4x9nroHFUL*nMGzzAyS_Qbee4s1wAjG8!J&}BK=%_x=?R{m*&!M zBmHl0)H~7|j-Cd^Rj7P2c2F8BHcR~h60e9{+iq^tk)R@M_fva6Fb@uYJx#bF@iqT+ ztZ4mMCyo#M7sj7MS{M%FfofN^#;9~2AGc`DtaNsS6Qex~&jT61x-1{z#Ks_)TQHgn zpTu-q^ayF>b8Qrs4!LCB)tbrca^WJuIUxJY>*G7vO|{mpO6d=pA*b_auY;FV6l_kJ z-!aYF4-*ln$5Et}f2N<=Grzm>MQ8Bm;^2Zw+K%CX#+dNmK9jFc)$`(ZQcaEPn!O8S z9^Vt2&8_=MD^Dbk(z9(ZD!fie$r^q!m5NLcffm-HTy#<|{tft0qnfrSWv@cfeaHUq zvP+Rex6g!rv0Ek{q}vi~9C-wtQY~#7_Jt+YY0g%slh?@YfYvxSFE>;xzkHR>Q^w@R z*C=ywSR`0dE(AX+b^Uz9l;*cJ?~oDN`@`y@QgqUofn(vGZFOXjRMu?nN}b>OKL(CT zB&741(3TM_atP3x;sNierS=o5$p6~6Csgd~j9R_NMRLl8w(Kwl?F%J^64XazYMC>U zvAd>+w%`i-20bVCWVUI0ur#xE*VMc2+9MEZguHRjrSYQgGO8?P*~P^bfcsT2Li^Lg z46H%f&CIeOLqtBjGjnSyvyZrptl>+YjxHd+`2JY0i z^Tg-ZARk1h+!jmDzD~PFwu28|*}Zeg9Wr9mCat7AYA+n$smp1cU(Wm~@O1PhLhsE@ zn=Q%^bSi;w-n|Bz`tao{=cfmLr`HfEQnVtr0+fUEa_PPwn#~ll9M82XB<6&> zE=ulhhc5}3E7aY`<Z1Jx`3Zj|vwzAhSJ+vFjWl-kDtZ z9Zqq@tmV43M0a};v}3Y{)E-TYJX*}1<4HTfH4j!@$co}_Qz9|L6)xO-xOU5+QS?Kf zX+Z93!n!u1U$Iuz>-NxmzS0}f-k`y2Yj)**iUW?V58-G?I zjcL50I`}15z*KFS-J00C48l}#VhYhYBk%Dxp-%p%4)vhrf;jUMaH@y)XMIXG%-BJj7!&M*iD86&|ypw}4M=bHt?V@PJxRU;!s_sUyVbVr;Qw)~gP;hiUFL*W)TRzHaCo*!2A-NRw2St`9&n^J zc+hr}5X`T`VXl7ma@x{wNA<7o+(UHi2fb$&ufHsB490H`Fsxv~enXV1cIXOT{7hrZ4t3b1a@=lPbws^$#p@yA$?(B^?fF3aXUxS{d*kI_+v|Mp$xHZGUJ9#^k}0kB$Mkd5aL|9(PTo;(($_s1)Go#xC20R0H(P0!J)Z9Ha-<-@|F?UAO=ef7wL#!D%wpGQY6SRI8N4)9s;6 zohKVQPO#3|Ff;HCU9ZHC*;p$*Fq4C#{ef-=$o7|N`M{`bDSo~Z=b^I|M>yDe;X_E! ze`NxYy-`>j{-;Cd#qob%qKyJ3pMFq2tLuoxeBn;!^ftfLU7J@JzZ;7|^u_UeqZ>av zw#*JCz8wPEC$j&1%R%?kx&QIRrdL(CC-4F2Lx=85EW+GH6S*dvF2N?{DfK&oW1zWUGdwM?(Qm zA16M49$=QZLuadzya% z?jq%|h@I5ALbMiH}SNE`b3vx0Kwi zYzpy4Q+{Ebm*!{1tpH*>b1Ntn9NFry=;i!kEDCWaI~Zd(q30s)NQ>tI?KP;8ueMA2 z0csrbU#Fdi%i;^cq80ORp z|ETW~DFp)~L)oXRpP|jvBR~ahR@JsL_=xNQ zPAFJknPvx$0Z9Kn6#k>>qU%HHZYATQROMKv$pFpLDYN~^pwiuZWLO-;lvJLq(|yK$ zCEN@3JxSHkB-n?#T2fB=?E+n7q~euWwGPA|n!Kw4ulK7>{>GB2wuB-Hi>7KrC8o=N zC=(tPL#A|z{|0j|)C^y)C8679+4{ahJ2Kaf1l;s>%-qDXc>l~TLlel?`fqt)i`|=Q z&t@h>f4qGuY*C7FI_6`{C1SX~rqHm=tG@J_Y?0xfl3Gt18u0>4On^u zw6-q(xElKoSPue%+d8cp@(ZsGN)V#M72`&ZKNs>+FQ*KvR5~`<+~@bLH$k26ui8lB zAoKtJvY{&fb?D;+!ig_5Z$-BVgGk^UF!xE_{f74mU=N07TWvak(B^0m0ddD8?;UbwP=`+19|I5`@ z2GeP`FE+J1)LILWGl`s$n~v3Q#vG2??=N)n)+6Bh*LT+++@6CI7n|z~0bdNqmYCHn z&DKW;p4gFP9bJTZ<|q>EebIHprQN5^!Z+gz#i8rX*TQsEMx8$bI++ zGW}E8f0Qz08&+``xG;BBn%u3qFyYitACHy@iHP8q(w36*t!OA0N#i-v{d-iurpJPv zx_^dwrwP{F?+{$l{sQKOqid+et@VZ8VoN8?XtV!4+K>P5(SBptkU@u>e9nk8CpW1) zS+EY&mHmG9Fn_{}t4!r{TWypsRQ+TyM)tKie%~`nfK6)cL7!TypViGzqA!i5Oe4?4 zQ~i>PmKjT3!WC?A5}xfFDwNGV&-Q~SX=Tc0<81W#aOYyd{d#Fv_S~xl+zxDn5kPAn z^JN1p?ot!-{a^Fq+%#@bol^Tlt@=3+9R2P!u7}4)w%j|wrGTeYGfywad8@iY*%IE1 zUYil6gbjN4y`y=A8C);2YM^`Upvy9ajUX(O zt)uq#7w9-;5f75o8f5F=Ure7a@#OzS%S{8Plv$fhbbJEf<>3XWQWfsM)C47&h9fpj z&NcV4+7fEw(7k+f$Wn)z5{=JUYO^7~?5M_}`5qh6_Bi3qzJKZ)V0d_L9ftmKg(Y8a zpIfsV^UgG)Bu0HSrNof7%g_CPES+aKo9*NGjpA-8I;a|^J(wor-^ zdq-?lZ517AM$nd6F-pwDs2UYSjl@i>2!bGD#Cr0(|Ia(ek>lWvGuL^2$LGucZd32c z0k^LXJ-uxsuDhG(f%k3BbzOv>EBEn3N~E7|%heud-D66X5$+H4LGm81cV(*_eSARQ zqmlP-VXl73IKzgDrW`I&TsI&`O>z9s_#W5CJ>$Bg$NpOV(6j$orSE-X)w4%N&gp}1 z=xzL_amM;?Q!gGXPU*^2iG^5wWU1G;lURt0Jr&SXW@sN#X|L{VwEuzYath5e*(^{{9=73N*A#Jr)4 z2-ilZ&LIdey#EAkJQIJ?T+XMjFY;+N4L^Glh}Oy@Q_puQEz6Dxqt$iG8>QGw53g%Rt_ zANxSl;}~ez4e>DL5t$90T9oC^_DmybJ5VAtZKx6;LsY6({IcKH*qa8rx3j$47oI0S zJ{??hY$Kx^mjy2_jC*m&p3<}|7^oA9b52S2!D%h@Jvh8w+uY*1CzuK-v>{ydQjhv( z4q*j@ElnfEHFe(f7A*x(~J2-5^D1`VQU~b5@fMLl#BJ_CDihFcRsau^4|| zb%^_z4BW-t{QZ{z4dr$r%6h$q*`{$$!(WbGid&c#I{1(%w6C&2*+5yt>-WBQUZ4c~ox4)72Jt)DPqaDG*w`pc~vJ9%WVbvxT)Z;m50lD7lk@4Tr z!$wQV(9Pw!O<)3wpQtpGrI1|RwEGiHX>9mvsWA8n$9aFJG1#JXUZL@iOW@qtR5k%y z_gVMVfyaEq%7W%@CO-73oNIKprVa=a8SHTq=>_#34uW5s?oC?)LExr9ffsFkY1_+p zC8Cv~j~sdZYg=ii)DXQc1A;3C;XJSHpjb+iSkuC0?AuT4B&7#o=A@x2(~WP^QPR>- zHpj$$Jbk+MqbVh|U&80;`YI%3rPc4tJHSlK~5uq97tsO5~+}pfk?PcFP0}FtxKl-qM&Qehq^k(IOXtG zox_m*$Yyc!&)VZ1rp?f$;lS7M2*{$!7Lc{*1mqu zd99<=DCo9HMS85Bg=S%`iH5+DeleeAQAyFl&&M!J`|Pm2>AQ5~*DT-sQ=6>;%7#*P zmPF(QF>^Kni~~>8rtEBisfPVjt8%Wmn_5GBdhHYMtfG~7hs-~Sr-YzW z9eV?%seX?iWXaU{X%%sj$BaKG3l(uU-q3sH$$s;s?=rz%f$$3zrriuAS_YW5A{D?d zy}A-Dlu!dMU@zyj7O>Q!2+H$=HDLCjNT+<^Q(}@|ups!)1rEp?53deyn z{!%ndLww+uEOu;|ZXKJW;O?;cqBrqftA`EP^8NR!6HRTpgDNYp3uTvHTp|7j+im@# z|KTVK00j|}Rg|%cc!`}u;?)eb>Fl0{zqodirq5}l#52wp5@AU24#w{=x+()-KP)7w$FGRT3>Saau+_ zKb&zuj%zq{IUUNt+_oE_T-6b5O=U*TsTnIsYCDaw(>+9a68$P24Cn&ER^ zwC_d^SBRSRv!VbS%zvEn;1iofEhR}pzVl3<&w8za0*Kc!Y_9cFZPQN9M7E{N`kJF_ z)e)ddbrTZaMN&!>dEtYHYcf7jvGZDwLH)kRmK5rK9J)t_RafoJ+5}F!iJn8SLe<(Inwyo zrn4!JLgaN1M8Dr3Dq%d5P<`?1yQpss#~rzBw&&rb$JZwjLk%1UWxL<&>jCN|jDK_C z=ld+4Sl=1WFhJjY#U7(z*4+7J5D@c4jaTq#cAAZ|U7wa$3bv#*C5f%m9k=klE3-{+ zN^ni6^0~+k8$o#W$qF<N4|D_?DI4^W_DLQgPT(H>Ib|*1WGHReU+ULWN959$AN>iCRI2U$5(d{Mh5%c` zO?6EBqs!ifjvo$PH~i*%gGv^ZDQoc2J_wbfGDQD*?f29yLX;r9H1m<}`KQ;O7I*CM zMQi6}jE=fHR-DdXJ9EPm3^!@tZd{E4)mi1%Evv}s@#jcZe?A_2z9#MaS)p&v)4gAq zqH8c2P$<&HfhL~liH}A5eli&9 z<7S@j*9D>6XXloQ;knIC?KW#Roa-)-`rI9CIeVk%aX>TQFoj7u_Asu%H}JizSV!RXbs#X{lY^|{0uuGFD8Zr1x#t5)wUsvv=b z)oU0?Q0od^vFTK-GXv|?6-jI1cgH`^e81dPTt1EGT-gzSw!SQ;bTo6d8ggvjiz4!1 zcUFWj{tw$hPGE6ufr!!4pL)rkm*G|q@S9A;{-|g!eC;IEd7*g36u;qzA?kS~`BWtI zYxE6iyIcG4p$}^jEz`k)rViQPnLwaD4A5G1F?0BX+qOvgwbc=ORI^_A+gCK3vvcA$ zOaH5wW&KwgpC4+{#U2Xf&*f;>G_ zsK*8{D+ruOmjEq<#`wuQi&q)EEQvaE$FFf~SMhwSN*M_g{xIR=o1u?IEz|&c>3Kby zkY3>x(e?)lY8u{WnYM{le3g8$SCnaA$7m!LUM9ai?wbFov^7!>fZGL^E9-GC~x*xKAv~Xksv-hzh%q5SSqG6)Z zb;Hft9i2+PM2QweNCbW3_f8Oyi8W2O#gKnt-gY!}zuwgs_cRgf4`A7FFm3E~V^j|# z`c1$U+JiKw_xb>1p6j`{M37Y-b^kbq5O9v_%df%PGcfYYK==8rq?WDcn`nM!2-v+e#gXAKXf9fwV3kU1eBr+HiXa(Pc@+9^^%Bi9 zC(^#PV$5l3wqe(GUVXkz#g*wf14=esyvuGPpj2(RE$#zJjv`9@EIZQ(OPlDq+4o5% z@RBu(3e=C}J1O5oVfx!d-p7u9c2SZa5bAbLpXyDwkuU9#4<$oITkIh_(HaZ(U#C1y zPH@a^OT6#i+y4D3**w!nX*5~Kk7RQY&~lN@&1?vI^V+p(w!h!YQyN267hZiGL)L!yiy zjMF2*Hb~Rww6vu5D|O-TYAxb`w*$4|QJXL$_cStF^eL!N@k zUzQFvP1bC4`}qv9ZLQmBF=hj&lJ(g~#jZQ{<~KZbaQEpw2G6xY%}tySIjQxb$5{8W z+}}qQ`(unt+9C5UIkDRbSn5$0mL4#4cpUo9;NcbgqjhyUeVFrNS)6$UVBy`egH59% z{G60&dP4#_WQ;!l1e>6GinQf~S(y>~bL1+i_P-ZY0c|$c_4XA{F$Ydwjz^DGW1SBT zJ+-|Rc@!rWVi9`Rz0rgE^t!8c!$j@^_+u=|4)ELWuZA&}#Y;uBHmNO80JB3$EVEd4 zuWm3y-QqS|+)@@jU%vbaVledGN%cDsHcE9JQXj|UMI=aM-9Ey<+>;Ha@@D=Z?zf*L z50puKIu5#>u`&ncF|(j>~t82w6nr0SMrB)n^hM z&SF)l4liwl@w$)M*uoqj)9qJsv(Z&7LN0pYNC8(!c8?)({YXiFg$S9zB`qnyztp7- z7cr9kqcD)(Y`mzX6kDSWPfIo`jKL;2n7UooUgG#S-=NN=Ax@KMQRE=Eap#dhXTpG{lpy%$NSrh0(U`PyX6L z$eX%D(sF_?&zh1OTzwY#42o8!OELYbUKc5+-|t16Sir{ z5m=5B{=blu@`P7>e`_Yk#rpg3nF4-}TX!}Os@vqzz0rG4tNx*)o}yaWZ}xoDDW@7a z+2(N-&1`SAlhQfn0Tq&#?sl%|NFzd}reuZWkmMi>!nVPzVw==E+{n4Kra?*^3gYhU zD(}vguh574+5|6D7zT;MIoX@ozMn*^zx0*ZTcGag#{IigIp7~H;=Y@-<>}>ZU|s%& z%4Vg4?tLGHdz{k-Bqz8lDkWrt@C?7^G=?zKAvWhID@7BGuY;n$qE%79^d_@>1daiV zhy)RpB!R`y)>{N@UUc~rVCT4`&jAV;`uC@e8Uc}~LocUF{|fMxR9B*R9C~lOCfOkf z$!dz@&HeTt-t7QUI$WP@>5nL!J6u8E1el8SnKu?W(C&TWk{YhGdiyl%uiYFBxi`_x zb9rq@Hgt9P;ZC?FE=a&)XetA_qXy^a4h*Lx=no#0LFY7UkZH-MTQ#YfRw2J3;KPkT zQ#%&gN$f`8j6PQhu5@X%wTWQ5pvO4d%hE;c#nTDe%A3`ZXWYxMbDB5tnuU!#gl6gt zv{0K_l?Av!M)9vfOF^bBML^lyoiKE3Rtd=vl)$hpCY@KV76egpmRSyyKC9G9u}ozZ z;2cEb%_4tC9%hq{=sU-YTb8D@{bT+?K~9M^B}_&NE0`$u*oweM$v9zMZ9QWhFwbaIn>^pJ-Fg zbE;o`Bl$?m%LSA0C7$5ffP`o}@^EN|zB$W^O>u3M(41?_fj}OyioNsy@_t;7ua55R+0YP~MufA5PFkPON075P5#S>35WF6{RR|1DH?}$G#M}*fta5-Cu z9x)?~Y~zi!m3fTu2bzpWRhSZG7cFeZK|k%lzuz{;Z`bQgTu*^eF%-l1tD2kM^m;zs z@~LA|I|a-vjF_e(-9nU5%M9X85KrwZ++=B=tvxBwC_^S9q_UXRwviEoH4yQ+&<$3X{63LI&+9Dl zwg|t|)O$X_uc@Y6))g2(mR9#UDboBk0varlR)W$dYg_P^_PTTF7F zWXg6k4M@{HsepA`^q#07qEk*M%CCh=jhZV_UrsLP9BNVn(K@ItC1Uei#-psx{lPR) z+(hxJJ4UBUhhKPZy?ZJC*-OlYo)Km@@KtWTJcS1fR%%9wC(2@Xf?cdCePtdvdn54{0s?*4Wu7uhv=^9mttBJ9!o-_mOOM zT~*%=FX^Kt0R%1k^^Yk;82WNTZoU^mKZ^M3hFhh-GYhVGE@yi!NV-#S(5i?L9a((< ze3E-=TQFnfd5fCBGr^s=lsH1V&6E@%WC2`?*^E$ZKkwVb;y8!duy-ryfQQF>*N_1q z)9@X4R||A{o{jDf(78agqG<}ex=2-6Yg{WxV;On{5J=sE0DQ9U>`KE4f#m_| zw)mdODJ=v>@W!dySP@`?ZBRuLa(5|gx1t$TL6%V}JH1J~%hojFM71z@CGIL{(MJD$ zq2aMl$Ay-7e$!0a%fG(;ORjqw?!ELE>`faVM&q^Eg3S7U9e{rVd1lsQlRwF{3z5Yy zN}h)puLy|h96v_wxZj1`sS@vQdP$l$ADI%s{SjczHHsZ@;J)m}9 zs-HrYa>wxsH9QAs*5eOUw@m`=iEivd2t?(L!8^ABvJ11FbpbcZn2>IrH#4JyaM7TB zo4N~w1D*i4MfHrGG@WwY_`B(Um?{;za|IEOVvzddGP!BZ=eb?`0W}rSSE$AZV}ac; z{@35UqDblN?rTj8Pa>Qasr$?mAOZY}3_UTjcFVy?^TKxF$VWm^r&6J{Ly%Vkf9-DnCXFB&$yy1e-;qbZQX_>A4+n1;sjb0kI zTIZ+9E^Lj#%hf><0@F)LbXF#xt*nlHl0!!5#t7$0pGOs3(+I=z9!c~!Kr_;qIx-KT5Ln@YKDOV#%>=VMX48VmY4?yXV9jDpCn_p_s} zop6`vKt)D%QkhbzAvX-~&R>1}9vzv}>2*26aN}z$v)R*ubU8^oA-tj>i@H6$_IR&S z;maM1tU+ix%`aC_&3>*T;OO5-l$Dt8IPy2(oyX%BwNFhU=`;mfN97ccw$tkudH$ts z2*0$rK4ZAYaEvuKgOKw_5P{jBU`g`eMG=?NR&_0l}gVrhV)gWXSLo*m%n4iJ!RoSUo#MyuQR%|2rzUxFnee+5XlKYhdYU0vEy z+-3B6*lDxtdJI_Slr^pGE^D%W`nUPo&#&l(Vr$Q|w3Ie3PjG5&WuqCPU!4AA458=2%~@m<`1roX^{{ zXsoiPqY}NE(y(0Z*xZ`3EeFZaD4XCu?q#*wiEX^AN^zq_JkGC=ZFuM>nrpX!aNZEb zxujxz2yf+iro1iG8Br6aCYsx#pmZ8qtm)I5!)|t(tQetOH?i4ik9?nyE|ib>X+GVL11A@7vWx8r z;4Z>8VYo-KdUtQ(K6igVOW^Mhz8{S#Z<-t8)gt~hU&_fiHxT-=&s^7C^ftx-)T~X`Znnv`7Z5B%Me(9` zE6&hCDB)%sf4`>2x{Vd@OAF7PUrgCFcOV|1+?6cB$&x!RZCG)7qSD{gXb!kkCTa-3;e; zex;j8!Za^QIytT%aQmqP;^M%9dI&RT*yr+QzUR|77PAPt-j$%GNLt&)?n@ultRi1r zJh2(yBiEg-EirGkP-(+cRVR@QNv^>PXq@({whi%)+s7nWalfQ)lq)&s2~ax1%!%LO zWv$Q4#c^r!a8~njT6u7~GXm%)B@whXr(K85|G-^RQCUKX^ESO`Ma%Vv1&RX=Amw#b z!_uImLsh|D-Kc9je4pUD^Q;``H~~*kEY!8im4v@JQFwelPm^t_TvupXZLLFH z)G2>X)SWdy=fCgmTAjTuO%u-s+U8#_Z1lK2)*}(kT)7^Z?8UMax$fvF=0SWeZ3Wmd z5R^cP2f}X!gnvQUN8J*)%4u#=;6FH(CTjt%kE(I~8UT$bOaBk_!Hy>DW*#-#TlZxD zvFB*ya=dM*U3)AG$Yvp>VLO%{AN4|*sZ}+bGPjCD9Q0R@ zL`oc##Ka7Kb6sT?Y_<~=w^&V~t&XsY zyvD`~9*FRYubxAIMoOf=?r;yN>rHNT|4sRZ{O<$TzTjkbcbvXZMN-_Vsa>~B_jJ;i zj6Qa$=GKPrLK0LM+O9jtQj7K5Wn!mdNnw?`CS#gooGzG%hGn?N{xlwtf&B^pXI~B< za7l@#r>z4aCA18<5F3y`48{B87phzZt#|Oie)kqax^u$eb!zW`&R`HsLzhOgVajv8 z$&b?8&$_^TG-a!wMn2SJ;)tBXu{ulstla7x7WbNg1op#{8y1&dqIH(kp-f(72gDEB zE!-!}kImkhhSa|p6$MGn>Z2PYC~$xb}~$xhw*xyR|bM+bWs5_G#557TY| zW{&psWq}*2sozX#)c2BX_{#9uvlra!by%I#;W9SYf?I=m^DZtG>9kG#lZBTRofFT? zTSgzNo_Jw4^<9z_|4USS@1t8|n!ATaawysCfF&;7&3I86J#kNmZI189EwdSGnJ|_d zeDm9gG1wDG<{pRxIJ1f-k9B1 zZ7GC`v5_r{xj3%>a~fW6`ml84_u=>~S>aKaPhx5p&KRh>y-t*@L*g>cC}ig{4jPnt zV}b_=4LA}uJ3!&)RoQ@qs&pHwexhU~4a{%{Rc}TNGm=S9yrXc;UqMvZyegsWS>BDH zE`Q_JonKTO!@1#Tj_pi(7xTRj`=)Yz(yg#*UdDQz353xaBz=g#Rn)(yU3q9Rs2_UW zbUN=6*1%492|)|byg#I*TSk}F?d8F~tdQm&Vx9abS8I!5{q(nxWZmw}EEd_{ihYhE zFy>@Gl}}m*EG$f>SDEgv)PMDJ56>vI@TW``HtWKZnU3|sM8b4!QQlXH{S04z)*ezklkex-|W}be{*XK4)q}O zE=O7Q`G~6LGTeK9Lb6 zbYHtQjSk6E=Plmkupm-yFRTFV_fpXgaGm9Pm4iLEEo zG#pV=#<6~_B4Rf1=qe$4dpsmesp_E3{}0jsV+hdkEThWqN5a{Q;a#d&Gq!b9P94XH z-{|L<%^C48z>~Q9QYLPD^n*)<19!91k$*phR0uI=WF@b1-QW`x-(gErW|yY~+Est( z+xghPgGM`?OQJAd@L1)>De@LB_sQbU8k60>eqnL3=E%^*xkTf+#Gu2|GwvIwU>~p8m+*&o#IV+Ja zl+A{m_5eZO(9`gCrae2PCP~v(DtDsaMI_a2z$7NvWJqU*MUxEJgK@(>@}6@aJYEM; zhXV`GIvVuuO~{+mW8Un`+t~gHT4U$11rE#mWu{{yimZP@rR3wt_1w|D(LXo;BygPf zRi(2(BPYbTvrV%-IDaq_XLPDo`Jb|&tx;(iF6bHW38B!5Vx_01;fhRu=r$o;pk^ zhI&m^5CT6Co8kN2?y8uFUMuzCUTYF9eXGy}`FdS=|F*(I0R;$8NT?TBV)j-xdDACy zV=jAroAn}^|K#n)kQ|bAyp(e8c1!j|Z4+7!D~?xMcDF3MLZ({cYTWJY6o0L1_;62` zxLy{|VKW&Qm7-D|4(LXT}0%~bA7Pg?w(FiZC8Uo+T)7v`h!T^oZapNe>q1zhml3Af>NXPKrN`@)BydhfH8;rUs*GEX%gR zL8QNmt(*N@yW#tOw`$ehR>jH8(971fOR0IlJ4t`JJMRmniuBvUdcig++^6kz?a^N_n33j*ldBmRO;iQP&K@^|>#wN@FN4uZBoy!n+9 z`Q|?;?HFhyeUBkT>Zl(mSc4x9roC;vM2LJ5KA@xP0C%>fWjF8iw(Nk`AZ{2&zQN84 z*~V+dZ>Ai2LovW`Wi#u@#mAvGP+K+PJoOd&P=YE8UM(VGJ&{f3m`gh&VloS248Q#{ zH;<9AK?Bs5dr8Q=%9JxS?3Ss(*z$!GM7m|r2YBSU77Qi1aYNqMDgsP|%&jZ|JkW$? z3<7B0r2RXdgaY^~m~;YBrZ@QirmAAJh5b z4)9Gt%Sm8vrw0=Ool46=%k*p~s;`3L#YC3bb@_rJ(Y5vk6ni{bViz3bT+mlDz&AAgU znkCd-jWn_IQQrmRJSOIBFRizy8`(P~tG?3tV5?(Vrj#9YmMt*RU;-euEbPI~7LG}V zhIdzqTu7v=_eCp3Z)zxvsstO@gk6uIgI63aOWQPQ>cxz@5ad^UlT2V7>4*c~>)h}=#<0M?rs1cx7{Wp{X;&&ruO-OnK;r-RPmfwAkSuF6%5IBoKypi} z;1zA|r7qoj^~q?JOG>6tnt`p%gD%6P(2}3R!sb1O*jwUxOt^q9)#>V)Ko;^+o2}VE zRZs$0Xxz>cQXe0Vcj=md^M$4%i}<@|nI}Jf(=A7GX9CxMpBo&NMua$>dj@+0bj{Df z#-_~2E{fXAG0It9L?mPw+aEmJcWGGX>oR`U#yk8c@e2`_y#_z0 z{g+=CXzq?dedGSnLBD^HmS^n3?oWr$ILaBWsrN=zZryJLJYIijUsN7?xir{2ATRh% z0%CA5oLad|IKMA0ycljK^=DOIgCJFR3v%lSFgpo}u&d zHa^0QT(1hvt<=INonZFDr&Wru18lP|C1MD%5VX0&%dEynp&D^$3! zS}U|aQO8{p`_nUiJZoqAbP(H$TXeZA7d6&>&?3=P=@{&;^iOkLU)s-O3n$zKz(^=b z>%PauGTbt;YKJX6=WHTIcFMM?Ja!FH0V%nSmWI z0ACPJ`Xsmg!CSzeo+BLoSy?ycZf*Z|A|Bj56tbt*B$@ND3cGRtOX)*|_HZe1%IOLI z{il*DXAM%I0@rbkh7>P)0OxYoq0@uBwf69?@a=-nozV~dtD#pa(;_9|`ey=i^jzwf z3`DzjmYBDQq|kS=tRUX=h%nK!tG9fWK~878XPVPZJ;Tx#x)W6DZ{5|TJP->zwZ*)N zsPgTFjFb=!_4k2Si#X>JcJ)+W3|8MIo%O}+KD}PQSxtY-MY7RRItnjU>M>V{@~ZaT zy*fIR?fa!5E97S=*m+y@ZW%#T)^Ry$C{217F+H&oskQ;IDt#YwR73ks$81?R&q`c- zB7L%@eY`e3otF94kGOSsKdVkBzpT#nMc;7XaDGC_R%X5lNNze-VkulQ;kB6s!7e$V z%j>cPBj^y#?a$XR3wi5*=1?4zM#F9%8dDcj>C<9=NCqZ6_PU*^JS4~Dwq)9h?dKlJ zkDuj0S5!*LZ%kzYd-Gg>nrylulC?@#7s$jZVMOr7JMwxYK!uz^Um9 zP83dlQ7Rli^}=d!;dOhpLiw-nm-scKH;&X586m-;qJ!G?zQDxKQQhdmve>MgZ(lf>{DoI}xh*zFPaJCxmt8nbBXUF{FD|bn} zKip2<@GjbidbPN!;yI??n+0r%1>N$JSho}$`aa{bdM59FQ|fLKP;=X8{6er-a+s~~ zd_GnY&4BMra0UmhF!Ffn+JP}j$+_ihnhP9jmq4}F5^NNWUN#1>>+w;azmfm2Dri%E znf)wMfIRYEyy_Qb=fvygS+UqE`Ipx< zeme^&HA#r%cb@AO=LzUAa64WPrtp|Y%^T>5Oq=aKFH4<6pi9ao9s+IYW(gK?8a z;lsFPmhqQxNXuSks-wB^PeIujS`e(a(Yw+eCU3H#J3-j|AM(uLKgZ|k`)xyG&8Up8 z;q492_+ptd)${}|vj|oOQ0K?7YeDRJcLk?{vP=Op=eeN0{1dIJ@bgZg{@Mr{-n|>U zdYMM~mz$9Pac2$UF7K=SPt>8vxf=r0F>}8-jP8gozntM?h?C+^%wCo5L(PBPqlEL> zWc0O_Rxi*uv-!1jtl4o=AO^lkzq#9T3t}e-3(5mYl-LDBblsS1H?96%&4RxT; zyefc*NlSEDOxO;4V8w8zkKBzyVy&SjUM-y-JU$#urxh$+g&CjSzg$kDvoHd_I{qb4#Dxv}ui2 zA&l9O+Rly70;dybewwHnL#ZJtH$7cmxV7_h^B&~ z!$kI`PCZJA5MDGiw7=Ah*4^7To&w_o-<8l`Mo3Z5u|{wXm>+;S(Fpy4BdEU$?u-v? zOAr&gLm*X5?46&Fps64kUYtn;87-K1pu#>&8al(0hUnMoSe0(2OqMh>dVCbMJ9k{8 z8y}TIYZr3<*$=?)jQ*7As0I9d8h~Au{>QJk@3CRgN{MSTAkxlO%@0)Ts3te$5ma(F zW3HqWMbP#$qFo9FoM^kHn7nu8#-O^-qT3~xpxICIbTgiw*ir5D#>a7YuxaFXmcMyv zc$xh|zpBpq@*%(2FS#Lr;6hxf|1 z=MP^ux4=@~wP0bEU3Lm{nQTOySNg4l&y4|Y8U|z;*5CM8e=vrE*>ER7W>Ig)85Eg3vr9zu6mgJIFcgOEm_3ka(B}V(_?c3AJ zwjCw$-(&gd;TrOLZia!pIUQ9WqKJ$y9kS=$*#^f@TJnGOFSJ;dZV84Z`qh-{UhL9v zOQ*$a1y_4sY&Hs=H1!*4BHj%#nr?dV=TOV*{@oDR#0XfK_l3>2dDpMQ@Wt2;Kcl65 zUhG{8uRwm2Fx$STMr7vDuR-rcVKBBdC;@gsc-hn1$`Birj$a+KiKtcVV!&hy!!t?f z6c}b z8STm_r+%zcBB(?HCL{B~QZ)7=QgwYlm^j{OJyFImruzdT*AghGueWjMK5z{-pwHqS zY#Ay{OMiPEl+ZCDVD0l=eEf}2Q-6@eW$%Ps&epIRr1$Wc6AXKehNS#SBQG}TXlaMf zkT(Vyhj_R7Kf^#k-P6^JP@2%&9d{H2fu`l-;YvwO%dTmrr)hG5ElsHO;Q@P=p37+q z?ZzMVgDr#X#+$p&QHRhG7zE{(vL&uFeEo%oanl1yL>d7ZQ9(G)N=~5;MlK&s^b#Po zf&SuAprCRP6OW!41W$h7X{tlZT&QV|K=~||$<$jdI;=Px`)D6Gv34q2b_IHS0iiQ- zfYhb`TT_+#eN!di{2PqWhBT#SY=k#83-x9BamkADYRXu_<;~)|X~<5EB(>+FmQ$X{ zA8(*W&ov2?uFdz0i_1N1QcoDYue0aG=^e_Jz2^3|ojWLk%Hh1sqHN?x3`VKR*Z`Tj zIyrD2*kot+WK6}ZsF+qgPmPJp;qaQ}@Fdly2YzL7zjhjJTjGf&Nw)BI z43AuGD1#_rU*R(*;)IDP4Jp%gA%HcxM~64>H{CWtwM!V;9&WMijJbqf{K=UeB2c7O z%>krPW7Rafg&HrK(Nf4Z#HU#^`yG20ie?=_Qj|6|BLRyWQfvKU7PS@&M2t5{qs%CA zb8^BVVZp0Iml7-jBpIq+{EGs7cRQg`Ev%ID$o{>4a6EXc0q(Uf9v;JQ`oj!B0oUH= zDI)43$^Vb2_Y7yV|NsAuqD7^XR%>)!rKl=uk8-I_v|1~~su_F7R#k1)Xzi8IR?XP4 z6V!+uH4-yHBq>1^ zJa=M%fN9kDxvxuZJY!;$n>xko>^&uT=?y37;uw9c>XjAlUD_)V2Q8&>tTdSiQZm}; zU6e=0PjOZtG!w^=bv!0xAEQA3a1*>?Rs}z#IeTVMXffcAntrbohdI6dPIsL2mV|m_!ryn!Oy?qT21sZ|~lH^Z>E~I$%yE$G~xjN9@W2FF_gG^Ny z^_VX`<%8S(GL--B3d6Cq&e=0a)}>`L3)-tO@H~<#NK@Gw3pX$1Zn$16NMBl&&6M>N zD{_AbC?*zHOHe0Vo6sBQN<*~Q7nj5u43ZK=qAA0A-xDn>-YpN@NEAz_)E?D}1k=(e z5WwybIFm8EE}+R;{s5Zd|JQB1c>%q9ly-1xOcT6!FmKOT4LK=h{icbFy%P8Ct${us zZkFSwL3%mJ`^zEh2)iNqChv|kWl!2hsF1tR-~6KMLhY9~O1NH~!DR)!zu-CM*bk1? zQGa$s#j~SQ&w`Vn0qL&Zm$qe8-TCE@56>I^T~v_u_?CI=$XwjsNR;FU9XsJX`@T~S z1L20Z#D5O_Hrh`uKxjKBXwgnJSWrZV4PxkmkqtbRtuZ4{)=k}Zc1AQ>Xx=d>hbMzu zlKT)Abbj>oS{LmWS0y9i5Ug}uL{zM0AdB6Pn8*!s?yuF!f0sY)T8OTyp}j^&DJ>7E zOMzwPPoZdl2SLpn@VosE4fHu?Fpb^VyzWt@gzR$1Lj?@4UP@)CS^WODlw^F{8XhfMY-szd@iJrV zk@}ej`P8_siwvTIU|w)j{o<-%%?mh&voHO_XI-|UE4Z3zKVa16vTK+Du!KL?d?g?% zj^Ch^OEsG0pe8rVa}q@SG#%v-Y#`r{UG|TRd$_}2=^%PZocQ3vNBa`?H@w&H|6PhN z&A z#7ft?uQm@gPstY#s*rQreLO>5X&jOMtfHP?ZJQ5m{e9qWq|A6kKFnH5_8 z260mnKi1EOTcv@U{Xv^veUDS+BRJ6nkj4jioo{Ezt)`akARl2OizVapa3ZGN`r zGjbz`op>ZEB^OJVF5{;-8`3&FqRwq7P4<1dSTmYID^|Ri(vUBE>}$C-OaYrc$v<6J zV%Mdx5aT0U-&|dO8Rw#C_b~tBd2UEvB&C78yW1fHzq9mGfXQC|`?G-H3h~yjL0+^8 zEg@}Td*jrTI(~iW+!J#Zsevn+9m~eJg+BN+aKn6 zB%JP?Qw>_(^AGhsx!@c-O*3o^4fsR#bQ5pDE(ng7Ez5a$5BQ$)cTt-YaR~aNUQce= zS+Muc5+V)|-z*^_$?)4LVD*_k9__ge3!WmNf4Bf&P!b0gq#iH~w)802xe3C_{It)+ z#=?{X)SPL*G6*89D~B5Cq*v~O4zx{0hrqtBk%;P-3_)O(it-oE);OLra7&$cYoj{$ z@%GK{zVXxD8b=Sldu*{2?tyBUY?DD>%_=UiJQ(K)TgvIa*p`1)fo22~3wztQWH`br>8eM}xCft4NK&VLhq<>D`FPuQyYMPux;Zb4Uo(uR5klcQhZpHjDSY+^K6?>NBGctW?mSU0Dvh z8&SKqZkYnh%q^o9UU1S#u(#FlbYyL_WCN~k#icU5y%iIWTc1G$3fuQMrN>~>eyul# zSD$(})EIHDo68K@zJ$v3QwX6VO;?RI{PKIE>sYZXJzT(jHqF9o*hUTvf8~a{mU`@# z)gar!=Bn0Pk|HMrs&j?09`;Ch*+lAX?T@*)YfimNK~8MvT@*K^OAF^m(W` z#g8Si;p)^w!Jz)Ra*IdQ8e<$uQOdP$MHJLmZ9xk%r+;eU4L}$BX$@g#EKShgW=o}v zhVBl^Ma*xX2?6z(^!NrrX+J=rS9H=xFS~UIt+!vS?XYimmzN_fJBna}gCq%n_1;*E zOCJ{)w&WLYS9F=0zQT!On?#i#9*f&k9fulei@_4H+h>A@e}_cutQiAIFVWx@llLAX zQddd9 zcs=pT6jpP5OGqa7v3mkRNAzBTVrnaUu+8Uw46R+g*FN+=V`-9p;-&xI%+GQjS|4Dv zj;vu3_+zDA&6JNN2U4^_-v0Y*w&AUFj=m=R<%H&bfcaN&9rquV0F{x9Gug>B7W>{M z#6B%#+tb`0`9XQjMJjPJ0A+!PD|BX(`~<6aepzXejeiy4+|JG{3OktpT^vo9K3UV& zwd$2ypHx3-gld3+_UmhniPkjtKj6N#dBl!1LPQqX#Y$LN5<{9d;4G@+y z-3D_Fnc>K^o%O|yRs?AFTc9TsuB!OrA@fAtX#JDcTaI;mAR8o>b~Ak&Wose27$yr` zl`srx#qrmL#CGqTc`H(LZq6jLryrOMHVfB*^f*7(zoMM+x7THcTgvHL$rNsDXq9So9pRz?MRIZ) zS&~)S!RMoC-GS}@`j4NA@dkD&!^ViKlUJQf{uREV z!Pi=P!PY%NnG##r{;TR4Zq~Ni^gV9#(&(d|HPrbDhBd3*TVuD zQ6T3@VU6aevZDc##aeZhfnN+uRTBx&2km1jYmMePtgNCy=>bbI>VzX456JM9 z2G;OT`ONs%Da87#j_g`YcOfALXs(a4^zZK6&6zwYB=8Uwc_XXaUA{tbimI74ZKv5N z<8h2_st+>0M>kGZLWR(so9gkw??Zv^xaCnlBsuy@=;K~#3K7xpfSjdy`W7w7g9SKq z22~hvyEFp$&&fIkl@Mab89GzA#$NZoK}(F1G!`aG6rstgW?3O%acp;e6Isog-WV>CKqqrR2d z6=CQ2zl;9N|8+ykPUq=PqD{t|RI<7!r{2p1{E`Fa<19;qI=$r!<)o~~52en}Jgl~B zI1j!vw$ymuL8&Oqlqh%KP*G>Ld^+e=MhJ6csnsPnaa3`zYyeQ|OB+)Mk`R`1Rc-J0 z+O;g}vd!l?GEOm5bewwOcVXnW>9k5Cw7O2%nQjGG=0%8kQ0(;elR;(b3&y$2nwK2p zpz37NlNjG;ki|_X__n|MmpbOu4gcx)b&Q|hOhHMSC8{f#F%(Q}s6Pa@`TEO;m2TUE zk&UV9HsKW^vZPZEh_#UY;_cQquzD=j(8c{&@(G$L${2%v+iAIxg9hHPfFO;oN+c?T zqY#KMIDHQS5Qp@P%e+X^sP_W_4`hnNvd&Yilgcn3b1sS&9fJtw8t+W8Rn;hcoiBwJPExK5URGQoZW z`KnFr?u@)vTG=SzndO#pO3Suk!OZNoNvGiPEBFZeP9h~ULjA{OBd54D^RF>91%c<| z>dL2O!P>S@9kBPUs>9=={bwr|n+M}V2E*j&ZGuge3R`V}8ClCm3Az4ZPQ4c)?=3~8 z{r;SxU7b^I_M~i8M151+BC)gIbOL+US-{{;PJCPCTIM;A&`-lym}0afX_a+b34Jdl))Xw{uu1f`wEJl-vlUi7mb34LP<~@z z9Mh}wSFm){-_rLdItZa${!*|ZP#=})zL})sB5ro2y4l~)bhZnFZRuCCT&N~ymtnh9 zapS26xMIf-I6_aO+iPD{=<6|@;0aG;97B%; zAiEa*a!W_9!ab!g^>9D8v76n!19objU@>#f(fXYdI1<5f`WEDCbh4XjXAm<&LX0bp z1cQe5ZSb6>cZZ3m9F#@WgVmQBaF(;aS}GOG#2~<0fiDsS@=T<>d~v&XyS6U`oE%8# z5Zw)Xt74})p=xo}dd2YQ;ep}t=CulD*Ths-C>(F`(=jx1-VK8)pA1P=}uFIcG||PrstFgrg9NCyOVC`)P1Cfu$Ak8essvA(Wy!oVBot0j%9`Z?&FM;%^cdB-0=O!Wj=xU7TE^0~u!55T`}U5=VF|dDl^XV{f8z=C_M&to z1%!MKa?S=?P2d)vuu-p`N4hmj^C+#deOEa+v(|d?h3=XX(4GjXB&lfoozb}|7v^sA zS1~w_X_H2nmNDNnnG22EiL_+9_3d3t#Dh*LfJhtN@@%sYPgQfk0lKSmWPi<5pMM?)C>lZn z-Rds9hD9keK>@y+EO*Me1L(1nmqs+jx6x*0Dwn>As8h1ecCqw-VZF>2 zd#{ahM{5mUR7ftFZv27BE2Mc3tB5Fo>}D>xh+*@*4OiL!atrNwGnS@$_VrtVd*hU}$E z4@zO9jjjeSMq%df^*0vPQ{^kyy0jRO>ds_z;-tF3@=z}G)i4zDMuiUk_z5rEjBNsC z16F*h3T9-bZP!H&Si=yV<2%98q>f9ySnCD7fpFJZPh`P=Hp>>Y5Bj zK01|DAKfK+=5M%6%wrPB5N!TbNv6R#JBA6-+ z7?9#zpD}P(ZyXY2A()FOD8gn!QL2`h=CCfC>JZ2(R5=pxdqu_O`{9_v8X9CH;@8if zUa!h;Jh~(?E+CEjqVBqx{%%UK4OsxbUrLizMEd`Q#Hk-4JH|@(UqxqKSabRkga5-x z1-tu#R*0-5V&6_-c(w5JgG###Pm)awHcq_uRE z;6pLFoAoE2a&=w%qAljL>&V)YL(|i0QnJC!tK5(CL(Q|3iClU+pp_u~* zFW|iG5|}jdnIZLu6J>sfe33Br3uFCZcI{`pomF!CZ|6BkQ%B>uJe6w=r$jkZ_t^|kXK$_XPHd!9yVc>MI#cMCjl*`|qy zO|)Xtf33mxGBqBMt^}rs_g|`iPzn3oLOHb%IP^n<$Iv4m-qLMPdEDB7nJDp=QCW_nUBM{ax@VW02YHqYMx& z?eLZ8TL{TSJuH(b*zvaQ>r{8sLPg#mhRV@IST4!Z0B8HyY^gwqL@v; z_K)hO_ZL48F@OAicuj%w;`5&yif>;UXhnRCL8wUo*)L=Q?vC6bDQ1saMBa;D7)@$l zWdW@m8^E~xuBif=Lt@oe{0<;h*w%l42W2@-!q7E2f&KDXn@AO8*=U>wIE|zvuOFqJ z5wm_@YAu;-kBXS)b-TBow*jH-aH}D+S2p+C_s)|&S$J+oMyq{#83tf@D}whkr#eq$ zc#yD(i?uNO#M)kRjEB29{*TM41{;7?072jtj^@=aO3c_~zhoF0l*5{>o-d8A+sP$7 zU}an)LQT~lck0O|l_?ig3pTI(LaJH#%%iUIKCT);|7i-ZJ_<4`Yo%RF@;`U(tUP44g&FYR@UFPfXVO09WL$sjt%5({eHs4kQf zvp;Um=BK2Rm5I#o`1K)vS*A8ytNnn}+Wwx^iI08Q`p4+NwwmulzIi9^_#-n38x5DK zpnf+P9_?OSk8-Qc#i8-RZwsbF%$PT%XkBns`{Q?7duT>uZBTrhp;fVld$-##Ec zq3U0L=kS2NFXOqY(TFKfMBluQj%j!tStSeN1Z`8pD3X)W#aa%cvFXeTtyCViVc9S8 zEVTC=p(vWF*E)Q3Fhr(ZEaIy3RmC{eYJoO0g6L7yw^E^q6w{Gtmi!Y8?>He!6JK90 z2*LdBS1TkbR%~m!P6FdOYOOFO8KnHIs`r6|AvMZbRuN)O5VNg+%?K(LYl*t1zjC!w zxTOb#jt%zoIBebs_3Zt--qEBjo2%jXU2{Cd)>@?{MOD=Uw%>V3K}s(>BJ+2mWPY0i zf(|oAlhPUehmvLyH!=4P55gSRt=I#}u@%foNmz;42`#8V=at)MplZv(@tU60%3O2F z^MBbT%6ftGmluL6mx3!dgpaitzW*J(+m7DgW|@cHrrG5k|0lzavpys#9arHAuV&g` z9kMt}-na9M7AI2m8XfF^WB+L}x8=GkjrJD%Y&jIWOL+>73mA(%zN!@#*V0m-;#2_p zC6|ZqGnL}I_LRz!q_TKZ87Gv+;)2h3w!8sR?@7hrYm1f3Av&Td<8?bf$CquODLh=T zObqaW!e1vi4TOg`xpunG{Dw{LF=s3of}Zu8TPFTt22G&~YRGAW>Fbe$&^JxpPd!Pq zqeB{`@Z~0rCa1OIF+WW3=9H?Z$Zby%WIGwHChZA?#MSa#|J(3-=&)75{u0z?Y-b;`>4#*w;-luM#8wYxW(Z z{alHYeD>sUj+3%jnc8#gws9ZEduYBdOqjgcQ^7>}v6dj`v@L&dNEddcK7_m=RXK9nxFWfXpmZS@mOmm8*n;TO+6xelU$&u(%?lKtT4nFDO! zV;5LMPNcwyf=2{djdKNhtMFZT4`5xC5yZa>)gNfCV_kXvRKzAatTD!@;vL%ah4OPh zzS+L>oc(Zx3d`_c`;Z0BS8T zF1V*;7o=?85k}dt0eKJlU-yKIkiQc2Dm>uHbTDL1pBkp4F>{*)`!roKzVru5+l8vL zX7n|o{n3>_Z(BO=w06WzDn(eVRkdi~fUBk8{Ze>cC8c=jbmLI{-1s!jeF-_xhg_8L z$L{5d?)t^sV>;G% zfP>ZF(?)9(h)Q+UysY-jSRA-PQzzU5Hrk+$TP=WehD|-={~%PTc>9^j#GDw`W#v)7 zG({@t>-nxC0Ezil@iFy<`Zu6h&8yy*4Wc(pX)?HuJG(A3-&gSRWkF*H;sAx0fomW& z%e&^MUWp~O-ZJ}6gZAGJxLt6!Fp1pw7`v%j&pIqX)!E$%b1m6kdUh?c;}St;YD#+r zUTA_{c|difF|mC#uHW_Di_q;=QP=Hc7vaI*2H`vEu%ioZyK*R(V@<}j6E%CyXzItn zc$Fa%a!{!P-X!2{Za@TE`T8SC#+yx!^sG+`W?$(R11`%)xsr|V(mjj9Wg!DeX_j|J z>MdGxCE|SGo`>L~e_AWicCzvCVesa83fHx}s`VmWn=Jv4UyauF)cDvlx7J^WQ-Sj_ zY|bpYQ`^(kD};!i!Ar^TO=munjX4UmF5-@k7DlX(A}1#J@d+L(V{(7}qJE9b9n!|@ z+vH9(;F`itKz2RNQ{`3u>do`0fEmW2o!dm*hQ_VfI zpPy7g`zz3}s(%5tRRf0Q1ePgY(mazGEZmgB^5W&kS(oWGotw$Sn9S6SLwu4&(Z4m+ zM!w2+nZh1X1u&;Np&!yGr^2#i#*BqEo8lZA`T9CK10ch^ZN9-j0S{U3kwW|G6o8dN zTx@~L5N=w*60Vi&)g=@!Y)VVwbWP%7fMc9Lxn97s`l13`&>BrJ15K+WzcHP8D%0kknEe;W z5uk`0dn%JYJEIj)4;LI-hGx?jT6z90>i4KqHl?vy!j#q!J_G0L|G=<$r+^nq{Si*Z zWrBJsUaJ;`ryVV>~v4mBh&97G?p{U9=($w)@`=&xz zmMQFs`*Q_%YNnSKQw6bXylhCHZyA;acN=KfvXEy8evo94$o+oskIYFw4InFW!gQLC zU>+Y?A4ea*bS3@|74-=P{W105q9k9-bJkDk2@;fCoz+IqDwXr6$fplJH8m*A`dRfYMSO3BC?1F4dJC zNx{8F8nkpOs}v7^5u?BSZPsl+rI2hII4(0a4YR;wp5XUJt|v&MVuNy8$8_1nNi-8S z2G(gtcwZ)PqrSGnk8k3q|9$I~-z#al{ML867P3tv&|t7&@`p1U&fL#_G;4Z`8oB3G zX=alUrctYJbMY1S$PFbfx$$JGbCVLt?$t`cPC30EK&ag~7uVrf(m9aqO-jl7bv+hvaf@VRw^)mqSdxBp)PZe+rsC$seGf8s9vLXpWp~5U_fVC0`2_*}y!^uj*mHKry3OCRjBG z9=dS%qzg%Q-I0~<+P@{{?voaqO2?3zj})R8-zf`vU<;WFDeq{$79ca-zcO97<~04< z?e0XlB*d7j5bSf@gwa;?%i;~)x17Yox%hHi)rT4TsBSyLW(`yQZOs}g!SDwhbN4>AxDyp_(|J6i3X&!uc z`uZ5Pk>CW)FnfemFr-YnngX!dqzxyiU!s4Ur~rLmF!ytL=Fd6)sbETM@3~a_`%|>&-9Ad3t zH1x{#>m!$?jHb^@D8IP4s{GY-F;IKMWSVUbe8MJ+?(RN(dALoHb2@ZkWPo>$<27fy zhMkf&RD2NPx-EIBqg5l1a6@on-`FeWFV@jMahSIxYLyWgpmeHQDRLS1{SfvJ{~gBv zdyT8J#k-NT{!oSnWb^TKkvyEDv<5zJ8eI)DjE&UnxauCi1dlb?S@a}rT;P2URpL(w zB#Rhq3QXAKzJ2#fhaUX84977?cZ4z*HGe%wY;=Dib)n}Qrl$JIl|c5shg}&bKSHJD zobUeqbSS)<`-3G|QR=;mgug9G=!OCms{N}({Z{r~{X@;!WQ@#9-qdR<^y`Q+;LhW_ z{BId%-ce-JeInmzR#%vwBl&q#|KUMJs)-;eLu@F207$-BbZ7KKyEG~zX8y%&4OSp) z&u6o}N!Kv4+bAWsdx$kbow@%JTK1KW{pCTU}2pEa}6dXqEDGYLkYMe3Y zea5+7RWNPzECex!-P15??MlWSW3RrfG-Y4J)^J7+(m`+{LIgz-vn&QC;?!j&jzzWj zkJ71e1VOqr7<~iqmoZZBj8Use*Np9F@e8Cy6#=NAZUDX|{SbeXrym%bU(xE>tj1H! zwIy0|`IFmae~CGG=Le;(`~kD&li;vcJs4W`k>@cL(VjLtBSvcrf(yvE9*45oQjNHa ze#tiIMUXX;Lt0IN)JOSJLR4Q*B>(K&L%L8|5v#QtZufsnN8{Rv&h(EC$~lJs;MMy< z;Yat->2FKL5~9}3`PlC{_5UL;G3_fVZ+!~g>5zZ*Ln&i8{g`!dKZua2OAB`YVn9o| zZhfOWf!rAWrT25Z%pdeK=?h1v29(LcOigQFB-?DWecdK8v`EOtt53g82N%0I6c{AQ zHL#}4_rzZ?S>6vyj)i=D{xIF@~ z@NbyRd=|tQY9vHqrvZ6n{45^|8w=s)E)!$@05&Cvm&D#5hU||LaEF2eA#Hl6MZ8?z zliU#5*s9ZQnM{2k!))1?RhH{6GC7tZvMdG72j)MHp59j`(NvdTU2cm*#)22Y zkP5l}s-DaX>yI>hG^B4o{9p$;Nn-m3ek_tkSU=vgPwUNySbSrCW&;PLjn7N6N_c~g zm(N!XeI44AD3A56D}V2x$~lqb(j0zt`b_i18ya0RKg|AC>d^MisZ;iOOPn%;Rs6h$ z(kK<5{v4^CT$_gBogfjc{X!ByzPTSQT`zT7wqM?VrU0bn(b@eaR`1D!2?hKbYId3) zlosNKDD<|`Rhm%X|HRmsn%qW5zpz(A-xb2GR^Fi{{t#h7n^FvQoxE^ESjy z>vMV4fGjuG#kk%*t_UY8kw%$ zifj0V=S%TEVAgxZtZo?9TzZg=vju#7{mglhYdlWv9yYcEBM)G~nh){!(mU=qj!*-xJU7=N}5ze%-OuPZa-gsfvipdA~gs=a? z9ZE*%Ugp<_e9@O$WbeMbeaDc$JNmX~&ZKWlLSmpq)V{S;BAC`Za3b85{+xmlAh%aVzQ*n{xY5C2%eD01i2r79G| zM3+h7CD0d)Dra5lTTOF)G-xEL{=u&q0h)cImF7SNF)B=&77bas@Rky+0S&TFbV94= z!FtfDuMCAIM`G?*iHeK8s<=Wx;JHB7+elsEic*Om)Q4p)E($?MNW2a`G z|7cFK{~ttL1WMK_IFdxWh6anR9JD7wKygt5U6Rz7UK${u7GFRcRzbp&DO#BCF%+$} zNKYA*h;8wF2>oryZfNifJBuq*SoC{yU8guf!DQrymK3c~rqiAjaLHK@$nOINodos7 zswUD{U0-EDeFeko`UQ?3WRe0`j1dU306xPKHzlLp`o~j1tfC04@bazjG zGtUHe2O+CinMKu`&IypsLv2gD5>e@X&v!KUL&!aM!|zhh2r8-~`T7}kmY(&?T~i4P z?uNLNAWtOX*~JS@n%-6x36O=BU4g&B6$JCU7{a}^+o(4KJh%=PyPo1HF7RvoW2;n7 z`ZNR8kD$UYEhV|vEvBGJjivM7@!cE19H6WH$m8d$aagB zK}?4)w-5*=OGC8LFJH*u^E<5BE`-sjY%iZZgln@~i$N*Jj&ap@HCglv0Y2H}T>PNm zMr@&Za;!3i1v2&;VpEIsogoq=wCM8iva!aYikNQdLDkCJ`)ntil4hi%*ZI4BTYMsE zmfVmtvbi*to9@)s+MaO}da3e`zVOJ)+Z5f1^;WIiGA$CSYsuBS>6gkqDX;V$Kzlb8 zeWC=tyxZ8>dEgKTyRe;KQbT9RzlDt~X#y+$XS{-gZD zkX&pPr9>d8BqaI(c&E2UESac-vG|`h8+A21{ew3M5r))v+BC+ z=d64QFFyd%mO{spZi6&aoZ52fRJGs4o+V2tq+;;AM}%yCD?k3mELfjieyv#)wZ1oY zoi;ZJPg?+PjCz0kNS*zWT)ev40CQC^0*f&{;HCkogh(a1jZ|3HVtfkXG@y zsUW*nb0T1D3QW~xIS@w=z4x0ijv_4053!wzteQ%$OMmTDTw93Opk)jhgVIOYoh*)V zBqwu+md@i);f090-Z56WPygxvPEM{b3(ON1z$WicCvcqotoLTE%C5RVSso~5YyPMI z>68Ia^|!N|QjVyX1z(?@uM9 zaa9g3iSB;2q=MwV+VdKCrhJ%L!=*O7iDG<6#ks9*gY}kx@Xl z&}Z|b*D(cqGxaQv{VYCThr8MP^eYuU7yerLC0qSe`h^tS&dwQN9{rded(JNwp~~i4 zqc}%pp8)2mwt1#yYnbmH*dATMFg5GDR_{q17Mzo&Fe@X?HHVEt5)?fR`LC)Ux3m;) za*obVo^#fWmt`fx2$Rv%kJ~T3ne*qVS=)UTInmK5mAa>48R_H|dRHxafj82ygTEX= z(Y<)p>0X#Jp=k10N22Ry;K&7MbOd+rL$FNQH|uvteil*dc`hG!wr&${8HLq(z^s~Bw`5$ZV%v-Z^8B!3bl0tW38DOD z0NIz?D@;}@yQ=6sguK^Z_fm+>YpA)r*-g}7M2vUtw}(N#{VTG)O(s2>k8!Oz_9^;$_)=O z)GI}J(8C{iEU6FKxv-ZlWeHW=mue8|#;4~T@d$OXVDR{OmfFCLliPP->H#b{R;;u| zWR||Cw{r|B)xruYwMC^7?^rp&rbMG)y=kDrx_bJS0v@!SrdS-{Jk?KGeReTtcB*1+ z{zt%>=}|+U@L65zyw_^!TCxWIP5si6QmWxN&3%0O`k?8w67A2MnNq_U)%S1q1%tpJ z%5l#_&1fwBj!`ZLy8gep(M<9^vx7l6V6+}<9WQA?j_SV(=uI$n4{xqzSibB&kz+_) z(HyLKM7SQX|NE{8SgybMGgZIlRsIzr#!nEx{|i`mHAoh&7eX)C5h_)RkNCW`^z?4I z#DlXlFK?xTUh~ZK`Ix6rf(zxEMSs(V2jBf0!K*hpe+$?v_b`&!WTdssg~>^z`-=30 zgbMNAI$y7c83tGuX&$k4TbK8XoVP>Lf6(=3U` z8x4@dMbsTn8Kq}aLoyDj=^aX|gZ-ky6`o*-$AiS#b^BVE`_v|%0So)^xPA}v6-@G| zio2o6Q;YDHp)gxbWG#HhmH0BQk%jC&!f&oL-1T&GCHg3MsrQ{~b0r3m`;haa$O?J`XuOT%g71LraxBI&Op>@2d4I z?agw}H<$bWZKl9qRNPASwWvN96bam6J^x?~l#fbn%-#Sw1Q95**nRhA%y!!T%hXd| zrzcbG^9moN*Lqbh8XO9O*Wa$bfjp{I#a*IK2}1kRpMMkr{C*haGVrva9}p+iC)EhG z!~-nt4T7*=^g?hg0)K_&f#I!YUph9+XUjLryH-dUO*7sUd*|eAk-2ozls22`a2J!DfH- zu}e$Y+7fM8qy`xDGj`H_kA>S8IS`YLV<>>iSbm+W>>2j#(zpBhLs{XncDF3)sTHV3 zU#xgzA|ToPs?6v9o#D(bW%C?6ImaBHjXp(`(*{zd?VXz78eDNmbs-5;KK&!R;>#P+ zk>D@E>;^>OX`ywussymil_usPlvrKS+Fqc>u;B&W2dq35wh?RgA%*x_KQ%HUD*iA) zncye8YBl48i?7gyD~pM9U6IJH-{GFQp@c7#*D9ij`z?;HEpB7 |`GzQ;a3B&U4t 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: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

-MebqVzcQHm&$KSZ+607V~c!I6TLp7WIcLNj1>leInpxw8M#3s_fv#Lh-NUcQqUHLe{`bXA#nRMa+v#ZVY z=)@BH`a`T+*V&gu-aQE2vs*ceZJymfK}(g$bE-;KRZ}vOKi4I*hK_7Z9}=YJ`P?~k z=Wg{qD4klCDZSQa|FfRP6_nFGdJB{<8S7P%@3U=TX2yFzy^RytVQtxFV(R{W79&3` ztSoOK>+Mz&2dxSFvx3v(yHRBq4A|g5X`-O*1b|0dz<}m$M18*L?h9Or7>pzeYdehgt{99HhejhEQxm^Mud~^^(DIIK`4;1(0 zA7ps5C+~TFm6jG}&?KVmgT#Ff^>$|%d6nMHv)r;qNhBfVl+%HQ% zIFN*VZ^~Gt7FLIK`ZicjNl~;B>3)ou`Qv;3ALW^^KE`&F2R!jQ76*d}a?eSTw>Ugi zRpQ1%RXuF~w|@x;^p7zpjozTvy<}8x$w6GM-Iehk;g+wSysR6oj`74jaH59+O z&v{(XJ>}6|@Jcj{dz5&?+o$|mQ%(*DdOP7(-@uhR9+zNryHE7;GDSyGJ)(BTilz!a zUZzNzT7-D;6e$k@*H9MMzh?Bfc|LD;>Uaf8-;~LA=sNrGz=4lpm1ZL~v(@?Vg+gCv z`H1%5XXvl2+8{W3Y`t#S^|F;A=fP@acOxVpH1lRPYg}%OgtgIXPrmBVT!(Z$x&nyyP z;$c+4-S&v8P5yKGT?33FulZ-w}F3Av#&}*OK2WL*Es- z-Tmc%hrb)9WOZ1@Hi@XOI~f!42jni%#o?!L@Pw&r!7>Cw(4dZ zJUA$lAj@=!f0e)JHo#_8D z#rMCd4t=m-d^Y|+T7X(OM0@+^B=nDSt=yowc&NL2ZfMw9r0*0G*i^*E)p+E3Nd6W1 z2ppKfAWEx4dNAX*xLv;1AZPW~QMmBlAUL7;95AzaZ7*6$SqqZM6u?+}uG=`nSUlY& zjYbmvxZfB0D&wOn{9t8FO}sjod*w}PNGpW$t)J{nqZVI+c!~AVzF<9ywt`75A&zpf zCZ2HEQPZq*e(m=6mPU(`u&j1JxzU!LPWsBGX1DL5(K!m$&CtdXDI49q=u$jrF3XY{ zI07kW%OI_BPu*ib3hJqhIVsuJKDFH85u3cb+LTSS8ATE;4BU@(Mhujby2sWsQfFF~ zMo(YRcZtLLh=jnqlh%l7C`w83$7rQx+>7R3Y!txN%!hVo{`b*;f_5qdPz()%nJ^?s zAKd=BoZagZIUXk)G?{g$1-;UkGzj%ciHd~NDorE;txo=qAsf8eMV=4R9{P{6yE^8D zufMvvF>Y{fP8Bo#wuvy6`h9e!Q`R_3&>Ye9Slbrd97E9bUiNsWNTyTIg32Ea`-Y`& z$_j?uKMesbo!?l##6@EYs`_Mx1uh1+6@6J-#;yLq!Vp1{QvRFUS}>Dvml%c(8aVTU zn}!+m8}r8KH}^X{H&cb5tFig#@M~Vz(4kQ_<>gLKkqhK@Wxd;cxUUjn)n<+hCX)~_ z@ba{Y?WUg3B0JW4ex12uj7UBTbtyssQgGJXEOSzS(^~TCnsImbEbS)!_O8Ju6S1Z8 zJG+*ic)_4qNaA4L_mREf!;Zh?3e4TeGoMX56O{W)J~?;Yg+pj8!-t|&ZV5OnUu7&LvlmD*Z%G-l1* z+CsnLF8BWrEVQznL!RCF5CC)k)fk+>;AeXKR(# zpW}J*iQ7ugL5xG0j5UZ~a}q};3`>*2v~S8cw5lW98;Yw4TOgCBupOVKTpUmu0chAs zCeh73T;8@iO`8@9@vr&f$TUF#xXxT|Q_!y9OK>&6tL&hG9Fz63A;65D?@*s}5hC0= z1EyB40Jx3fEDA{wNJ5BHLOMg)K(Cb)2g8hZ``MLDi%P>$lc}qjHA>u2#F7V1k{fmM z3*^4hjQ(+SXvCOlPUoGbIP;zbEO(D#MXSL>^@a_+H<9!z^PIPHq~p*K$vD4yZ;|ONyNEH5`uLXgxgjlbtnlLARb%&A-1_9PfDU-y-#w zfD_1W-|W%ul+Ng}Uc>r;<;0BZ>F%o7GvQjHH8y*q{E6Fo_C@=8H@Vz1^%(eYPNaktk%YO2oBFyq1Mgclu1LaIRjoaYs7Q=5y0Z01@Sov{x=3^IK-y@hOqa1*f#$ zm9C9h>DhTSglr?#`{t}9q`=tz8GnB(YGMmu$IBpInAK@$=`+ks(02Oc5^`JIfM}UB z@K&_1>%#Z7pWlJW0YQoW7^o~|=LT0JwGDc2&(D6q{@Gu=YkzdDed@i+(U}8YmOPK3 z2Wg`B$d{=eC1LxYAz|{>|8!PfoeVoPNo#avqvglO-MB8&3^r4Zw5mjYq=@xtS5TsJ z+$|-?TC$67;g88Xm;xt{e)6Di+;WNnXz9!)q<+vE9UD`@!-zgHwMBN3HVloZ^%+xo7|7 z)^U-_J!svC)<-dai_(AnQ9{&%j-=qrj}8>A%Vrh9;qRn@nuH`3+D}c^?eCd6htT4IBMpJe5W)N0Q(d zGaRxguJ&a!ab`Qyuc*gorutj6V}S6Rf5tS!&Ze~rsl*8;Xu$^5x2O<(Q?{JVH86>Gt^i;Lu7G}Frcas65Q~46 za=CpES{5`#a_cfVXBlV;R(!ajgwCj0VS-{tE6BOu3v3Z19y*`Z>}i%Rw z$S#0mzt5m|EyOU&ONc48lA=?V`*iQ8(oHFDmn;qmi#WU2&(qrj4hm1Rd;{2zZ)}+p z^9N%~tsUplxlbebQ2ZCS0;|%UQy4bH=twLXYLK@x!?pNxs4zvkn=bKeC+*70zRSm7 z+V;=;i&bpsF$J<|R7%)d?Y}}J&r+@<^3mF4Fb5epM@`MKwm|zoX2);)oIga-dyx&tler&;PPfcK312 zuP?-hYie+z5OvYY7DocaK$T}V6LV#5M=41g~ql|ns zV+1eFJF)0kRMWg|l{w|AkQ?a6DXRXyQg>yAO@1rX(WBD4B!MLBDh)uOdR{ukMVcs) z-?{x7&Ua?YYd*@p`h}HGL+v}#3Heg6%sT0*90z>;rwO_y3kudy0+=DiVUOo+cyI3| zp{HWTKAdU`HYL5CQL}6XC06a@Tim~ zg{%U^JX>l2`CsrEr?E{AdE?kC1Bc3fM6d#pti$FNCZKttc<1 z7^O#5b#Dh;fx`s-lJo439i{-k1w)Wbi!P@ax~)07KN`{v*gWQzIM;!i9hocXQ&{KJ zh@X*i?^^r^Md?O$rk+@(z-4CmqS_8Uejs(@#+XAC<=~PHX1B)VN77ZjPj3CzIXCae zxSlGeo>1AMP8%rQbGowFH+0Vs*_dwa?_sJu*9J2wY9j-;B}6Z)U>}#I)7_7D)?jP^ z{vl*iufF09rT!y_+saU#7LJk%+n?L^>Q?Q z5^bL2QxWBX=T*e%PM}7O)J?h-uXmFBvO@7C1+~N9VTdV+^67H@=HU%;;(tMT+Dgf= z?%#`Y%Fh$_l}1nyHL0}4wdoo+nots$}8!kw-{Zthdw2 zj=Yi(eAA|YwSIhKnK}!#@GOxZ+)JNq88>m@%^(Uv#+=h#xcrJuimMy{Dn=(XDJ;>p zK#1;un!Vt}rK+7tuN8ZR(`qgpboS7^7+)XlNuw^Xxwl3xXFS?qu={FD7@fheXj`W(935) zyCPqygz`7exYXR`d(nM8R>qcb?bdg7O!a=cho)E_Sha2deNSziDZ&2wdQ_5gaS<46 zW}I$%!@?yQYnuR^G&u2I68{!aWwE-)uJP9E#EXrYpfC@Gc_uO>ILCOwJVLfj8F)R- zlhQ(;l#FfmbhPAgw4fdsrsrHG4E^QBt|cQ*m6;0IP(qFG_;%dx+ubxM9D6Q4Nh#6m zxsG1Y`H{2Yq=y>(T_$4W(uAd&r4asT611So+GIbba;39ogvEO8Jv6B(hun0uHKDhu z7)Gv!!0ifmk5=vWcQ)A)S4k8KzLp9)-LyO^KvyQT82sO~9;ISQV;T4&xQ?_>zMa9C zFr|?EQaRtoZMMi9K<`lpb1cK12vO`MJ9_1}+KsectrLTt?|lQkbF@Vz=5I3H8>UIR z_#)P7DIPERN*?emKHGGe){BBOP)VPn*Nosf{i9y%@}Rlju$hk}@b1ro*2ysH&$#Id zKfoo&*Q?23ve5@6HYw#oz8U+M>I3RL>4X3(Os8YmHRK=`M#(oeHx6-!eUxPY!J-0;|yr z?HIWVsmX`@b5+3J%KI}R*~p*O3#Y$4t|)6)uT`^6`jh}p=DaMg9XJ@6EK8R2x~Cbr zuX16Yq=`@RlV9y#&h$Gg3<~mUW&vvu9btWFA?3enPk|viLSu4-du{qqz-yJSFhm=; zPXwi0uZ)9s*`7IH@a~Wed;yu#K-ZyS^dYsz@Gb2cTH2xkW<#XxxpTePnqIIzeU-Al z?bYW>J=wjk_EjR{r@4b48NT8x-rw)~aC75-f)!4m9CWvKJDFHXEi4gxjJV0}zkTIb zWX|-<8>%u{VPc=|K5W1EJ7rbnh6btfaJk_8T$P4qm|J2PR&Dk=o#)D9vk=mBqVgmw z!}15yh%_9~KVuaVHa{nzbF}IvMYmQ>q8)uhe5=M}`B3K-!cQgW%Hz&HlIVzzQ@)KX zU2U_C{0KMunk(9e@$g%hmEth~)lSZx(LK;E_#?~G^-=kr5@aA@ z1prrpp9h0B75fI(9$kWI{|bV(Zj~xe zWhfGw&yo*@5dlQp)fVHZpl;>=bDag=H({vYVm zqEMy&FX%(lu%e!{9^bG$K{djTZs3T^!GDM;`vl()w?=sl0zA2NvmY~|4H>g2WxdWR ze%&7T9jaxXE(Ga~IVrZlf!uDJPanLCzZU=cvhG!p^!&a-Q=%{8V~anE)rW7YsAoQC_$aog zXqY&rr{V0YlRkK&!nJFF?stui=A}HGQPjw-g$+7@!mTgxsBOM+scF_d*(o`%QC+Ef z@bRp9d%flm&d0&lzf54pRirt9Y}#t}0xDRMkQJ{_=%+j%Ni((1+J;34jQ&`Z*EH1d zt_uQ*e_$!NAtQrag|AO8IJDe040wt4u52QVju6h)bMvBqZr{rD+0M4L6ck-H$R)py zap)rpp!`$Twx~vHG?5mUwZ02R)~MyG&v&m(18E?d@E*)0=M(DwRQi+HyhW=7f@Bue zOsjjXAx(0BI~{y|$@_68TeC@U()F%#ec&Eu`?#G66m(;2KT&X~`5Zjs-X&yNjnV|I zl5#YP>E|2I8~dPCX}ddlrN8&a<5P1;UvFc4tD@~_j0&xgQ>QWM`W|H1XJ05=(ip#D zcBfb1R+DfatU}>0L3*=1D8RAvDiOwM*oYo&2s65F)u2)Br6aXQszEXiRfj8%l)B)2 zHh}=L!O8xjHvRWz56vJS6C$Y`jm*t*Y9Jr5+!TLz8dwt9wCHssbie%c&_8;q&c43J zT@GtvB;R7B*-?TvLEi~b!nxt%JuO;TbQ%W?s%b3vriA#v%(T5TvabD-? z_s~UwnfI6DHyBW}{^A6r_>9+d*I%PV2YFu1U++_1v4t#b{1kk@lJdUv(y20WG`X#0 zpQr6rxn6Y?=ahrx=_$qjpqeen?Fba~@9`{I>&LF_=>NwQ{xU%Ng4zM%#N#09?;C3I zPy{GU8OV5NB3I?pcz)Enpn*$m71K8vPm&=)wn(5QeeGR(ZeP1s4l{pkfljW?mg-V& z`ddOF2LX^+JLTQqLiUKFp|f*GuOg{Uj#!-~aN!ttu;$F`oQP~!LP{a@lFzR7V5gAG z#8}PvKjUNGgDVqnv(0-{S!|ChksJ5r9$5JuG zsPeZb)d&{NQSS(8u9X{XZm(ED%wqOU&0o--=7Uv!k(>oU6|K34i7ovpyQq>bS? zINhl5toYcV*&Q%b-r_&onX;_yT99!^TLyFUGLU&t_A7WR@L{zeKVJ&-2m@HdvN}kC zVQDM9OK43rgpi4A9U#kNld5yN_VF|WGcJn-(UMBFZ1DUWxDCfLBf^$G)vOsSVVx*%=tO(*0J^K za>I0wN}gAXUIokk-HQ`v>=U}fqksVcHol`z_0KA_Q-dGG$UnpV#EcxN(y0VeNvSGU z4#^=iTQIk2f^$pxro0Y=-|w}_RAA!!=HiNL%(55{`jr|UrJ^tEW)P2yxmAb0Z3 zxb#T)j^sPDMSm}S9clXIQtG>x64J%}>Z|2i+$rDdGKI5f-LB9Rdz0?SyDGkaOEgtieq>Y&k8wtq&*2Xs4j9Q;gdg%~1aDI>yrHe`n*>;eT}{LDmAtCx4}n zqfQ?lZwkR~4y76a$=}1vWWko?Lm( z3(1F_i*gd_|PxZx5`*H!4_!?I7(IqHh%~Z29G*ph7JB7uHHME?f#GZ zPi(4mSM63+71h?N6W>tF02HC_(Ji5;JyCZDS>|_pA{?#7biO zrPuZSo%`JPfBwih&WYsh^Lo9X&&R_pc<8og>O(~ZYdgO(J}4`7Z@+|9@sy z&ZXpLI!ShIs`*IQxu|r3 zV#tnCQR~~AvW{#tZ=2i#ZYrd&x;zOOpG^#5gf=fGIcZj1>%u^|{6Vy3`;~zDTnqQg zoRc+hzvdc}N+j|AMJVB{Cxxoj>MJZ!>2vaxFf*EH2NyqNA=M^%1cJ(CD8T~&nrWCq zx@uQap#FpXAW8MA!xhm|F!+fP1f)v`7pQb64I5xxaL3{*e%yNXH>uvSjrD&XFozyK zbNjX^Q8~xjvd%1VM&pT4`!#P7q+y!dwol@2ujz; zs>5&DUqDjHt$TBLe4Gmt;niH8DbId=kWH43wCyksfD^a_G4?`5Lte1NS(-7?W>_ zfYmW)=I<&rBT%;P6PwgR@~K)*Kq z`hkGK=&JRZO0}-#z)yP#GBB@{ywnxfv(G?06C&5(7IO|)3TDK*f=QK>90=!R!O64D zVNGcF-bJ^rS|) zGBsHL#-E#Cv>x$VOxGT5>5pG8{3WVlTI2NeG4KxCZ~e?ml7+IZkhO(&yEekpvICcdkjp4@XLv*DgTa9tl5$l9UaBs_8$$6#>F z?Jz|2r7guYUD#t`_y-!p9h&LHG-Hj$dvNi61ItZgYI+?x3x%)|8JD@vN%hz1*wtX=ahuKs&&nVwt}s z17;@Z`yQaL?sFtr;JQM3bt+XHmKPejf6=C4FVo|=i1YJOfhzpsvqMN_NN5hiZ)cwb zwtv*8{CTvt*2Q_q-}P105h?DO-Oj)-!}c$Mbk;8Y6C?T;(8TOdNu5nH=FDCCcf^$! zw}RLjfW>kTJd*(K;d5LW%z_rT7!6RsEA-ABm!8)D=e{m@{%KjRvsdKZTy}yHOMG+i1KDDW+V*89( zeyB{2Bxme9Sq4i$5nFEZ>;|$Qbl&k~FylsPYs|RLT!@Bj*ZD1m`;|i$xX{BX5}1*H zdQ=!tvQ;H6aQWO9;#LUHe4?!Nm~nfsX49~-us-3~-)RWUOG^mr3&k;3C4ZT?BI9}v zR{wYV{>a>yt@pT_8vX6qsb4|E2H^;$hNUQNJA?m{=~%j2=LQC)m9~RyDjBp}Q52dY z*y_1t#_xYk7U58&bJ4WcrTPb2@nOx{#*W}|i_nU)l8J;{3O(wT5ms75g+R385mg#K zLH3W4I`QY+L29fBS%g`h-j}1H1C>2rKjk#R11LdnUFoh&(lm^@)x5Rr>5R!h)hW4{UmE%b(KoE?Al8Chz!}9wT3K{S zx2l_$b1w{6kqS@a@7%zKM$viFPsI=Ke_$x8B86qazT6ZawCcp&d+GsXH_~GycB0L-ECQTU_Y) z?4Ii+7<0sR%f;OeVH;MXdOYNrARRe0;~LCpsstjg`Ft=^iFbs8*1IEACFA26 zfv}fbvarASC&MNO(zkp6-GAD*x&JNa@74GHZE}8ApdHR77l>>}tV3%2=8!ZxI;k&SY9iE;FtT1mMg_V8ur}Dhaqg8Ju_xY*q_^-IYbG}nS0@M zNNH&7?Z_YcA@nOomSHlc%q{gU%|l54IbGUv^`EzQ&^ace(m85miFO7M&>#R_KgXMe zzQw+!XuiBI!Y;2S3Sj2Dcdc z_LmE)glQ%O+_Xn5Q?M|j`APR^TuXF|O%Akf7HkQ4=rDd#EKn#_P%vP*;F}Tpm%_lP zMl~5d*X?3 zCTIO|xks2UZVJdP{zcrSMk6W)>#`=Vm$s0vQb4OtQr=fMB2*8x?Fz-U5WR1HUU_hO z(Qr}1H_(Ukp8K_}96>?wpWy_c_D&2vvF3xmlJKkjzTdZ+p9BSUTRvH-siX*d!`ugV zA2DR8<|pKfa6$SoOP^zR@J76lP;?%;F(x=zHe63sd22^_V^LWeIW4vev)qgzI$2XD z#zP7<6}o=#jGH5UZ5#O)xt_0F(_iDQaS`4Q6v(`t?}0qDNLRU*Qu?X_N1ddsO*QPt zoLBq1*`HF_`*`T_x5bQc`wMLklTUj$%@GkmFF|Y2fi! zbLMA>GXb38$gL7a)GN?HuO;~5u^>m6&nmQp@_x*HeD`+W(r&)KX25txbAXGGFuV`mrr0r{?R zRX}{^Ly@n>onP0(FkU?Upuo>`K3?A3HUAF3#y5sjmsnx4z*UODi3firCAThJ?FwUbT4CI8PCT!;=RP z+uMVs?94l9YvtpLUh|kw0$ywRM70bn%+oj}^TesdJi{|D6YjSwNSv6J*GUODiXj4p z$6ZcfSkCt;PoF89h@NQ}Sd51zwqEq?YQ(be3P=CArQ;?i$-xca&%B#m-z$8sbxkMx zNki+Yn3I6C2=8`=QgHItLt-iD#`_Y?4R3R0k1R@YL#~(66G`}pvFNK$pya3zSO+Gq z$mu87{GKj>mv}eKj26*MzmFUl_e@9Ip3XbSyg-TRwpYHNneTm*v&_hQbJ1~9jBRF` zwSL|zOS==1%qJ=YhlS&E)cz>n4;l`cdjK}};`@gsOE(kq0kqg#-tW8e5~2Bx<&S-Z z37|!d-m$`7V;pXsu)9dVO@A2CBRG;VCJD^xDM9oP9M7KnICIBKbMAp>s6$eA?QZBJ zjmMs`i&I^zx*vAz4FtH7a0Ti@;?GW1`DOrz`8OIH&%t<<2^N*|v|YN~#>V0LVuOmr z?0y9K)i#u5EqNWUS;sV|66!JSPN3%#hbOKv0GQOr4}l?GVkgYNTjE|zR7KW-wf#vb zcDi{_XCK)_FF`chCH*bqKG}2Y<68;QF%Vw*PUdasNK9V1ob7T|Af88AO^4 z`iv-gBD)*UKPx_ymXmHZWYEaL?I|NFq)K@laNDvJ+#@mqSH!z#&S)n^j2wxoElc5_8eEP7Rq|k*wUN)8 zn%lseXTgt#(_5YG+wR{`8o@$}NO(yquP-d14tcxpAa2|dv&^8z(|7Ow!vpsI6beC# zVqriyW%4^-9ek!mE+t|+P~+6yriPT)gZwG>`bZHJ%Hz?D$5sAIs8Eb&J@4ISmerdw zg}7>U^4ZK{YL+`-?dY-fgF2R5&Z^>v{G$v~Wc1yF!*(+(bQ{J88p~~w;o<^OkJ-_I z#$M2ct_PMs44SZ*N^1elo>iIU#h1%~2`6F%)p^w!wO|C2hWce@5~g%iJ;}ElyF~Yp z!#z%Qn4eyNBnbpxOj#i4oYKVxRbN7Qrb$&3?_6cft~k$-_J9U$jy6f1Y47d2zKyPJ z@ml%nTe9+%)AjF*i}Vy^3al`N(MQG77kn-ke7--y!*JxFzMP*0XIocQTQOA{2Ov1! zFodW>X`DrUmrvAXc^T%kGYX~n%dZ9`d2-9Dh-|I7#Ve0z3Y>Tj(4 z%A7+@Q+bv~8gT6_MpyxTf;dUc2tN$+0pklx2hUuEct?YfXa2PDc@`a(kt% z_s6TMqd-KBI`dRHk}15>AjU0oufaecKsz&1oEcZpmEiQOX--b|{!`|b$FI)LKr)uq z?un|a2WaQB7yUr^ACyD~FQk!JV80xg%FPV@c)zgE+A@7Xd^l#@iRyAe*zRC)%o7e7 zkWZj=T0~37{MoUUog7%$gUq|XSyGtRZwe|M#Dw0y-rjO!KNn(_VH1pyI5$9>!s%WA zT!3H?yt#;bn+)hRNDIz@4Je1lu(XYjLmqD9+<;b|XY3q7Pr{fzV#z!A;&Bq5W=;LI#M#!!) zm~j$VlZ0}r*%%{!3WFNwaQ5FBf6yOCuTipSHc!~nJjbTfov*3V0yzcnGlpkCIa+>@ zhTZSvq{jjAx37e(h*XBM^;~-H{78uUYoo5o^-fUIi=YFCKF;YTfAQDkc%D4Z;St~_ z>Z#Dfiwm-|5j-`VmL(mx0rnMHnbqhmhEl9(;2t|4o+!HVc}%N$fYHk_N_x>Un4s-& z`9%7Tu+PbWkr$vahw5XsYk{#}0$)1to9%Ggvt9K%G!)7J#euvmCE)kbDG?#m<)CD@ zvTtP5{dgf%Q+({h5?B$%OKk8r$4Aal?td|US24nb-n`A#vtvIldf5&d zPXPd+u^EUf5-kF(-s8M2p)Q^+enY@XUX6{Jt94x#V#o=9o2gSyvlFFXM$qwQ9!Uu?jDh38*kwV_j7A*^j-v&8?T#mbZMG*>iwKE zkGINhW-#q`n(&l;>qBZh?^MIMDi*@c220^V78r7Qz^M#W_QaV~si^sm^Tp)`Yg-6(`T79WNJ5G1~`84s{$7mBsOcYtfUq<8jQc zZrC5>J|mymY$lw=ctZPsBGi8WmP%~E;~}*{UUZZKcq`N}X@xuT?u%O@kz+SE;#9sC z4P}hqNOY5iGH`ruY5gc>mMDXX-LVDmoY5G#4+t8IYV}ys{thk`Kjia>5^V9iR(e7u zR_kVg??;=0JEhgBi8ar=FTEU0UC>8aaTYEfz2x^p=Y-rdgQ$+o94-5y zHmrCH$iKZWjFLy5AzyJnJMz|G&AZGD?Ka!*ChR!?_SIFnS|S4{#{IVw`zs;*K0D|3 zHln6yhdiQ1!nHjSW)qb>L#|00(WfSb`mfTJ3nN`P`|`IcIl#O%yIT)Ys?*Rt={awO zEpp%?kOYa_&&2!_drb5Ox?1~t^8P_{nY%-cjgY;0#9Ehe_hXf!s`pezB7F3w%<9X1 zthMFy%?qyQxVJB$M2Rx~uJS&vvr*%6NSFz7z}Ty|yMG0kwp>ti>Ni*&G)^D$nwHy7 z2`l}N+^0H~Y6o-lKe$3Y&2mZzpt2}eAS-#29;acG(&$S~;Z5Vgh@9m8%aOJD+rp1N z=mKmhi^^3R59jIFyCU<|>4-J4SSG3a<&Y}AD;ev8gYCYt%l$8JwQDPh$ddY3t^!sc zsK@dzz2_RfPR{aT&=haUn_yi3Nm>(9J5}HvRdOnoqeW~_@bj$pw9cX7+3y|<#2(#>c@m}Z zK!EVZTWebRt-5Y`+lAk6P^`L$Ehy_}>dTe92x3qQokts5H5UM1-kOSLEGO8L?zBp$ z!Bw7>p<1soI%yq)r$U$2?h@oUL?OJiu1?zFRjhKJX@xg!N`ya7lBwI z`b9l;LxnEv3O&i+=>x0MS$SlDD0Eoz+k&(s1B{uea_kUYtXu5QmZeYq4a|_b8w;tn zCW=22tnM?36wJK)p88va0%lr%scVBi-S?E2fC21>~O+60CK)sZ8pz>03g*=9CPcL?wj%w`bE2WtU-6f%y4| zF$j!WN<=Uce>%?pR zR@3a%Y5fD+K1yEiO?%&%*F@*JfPKG6q5(oGnu@Q}m?7<7gs@f~OturAz_;s*jPCaM zHl@=d!KLFIFJE!dm94olq!O3oeD)YoI+$nK_p$XBwyLMQ`hblZPBo><#+!Ay&Mxb= zK$q}wXHxy0z|t1g?UOJ>1PM^>(%sVBLJy+<;cvX#8swYbeVe{!-)7;&!!i;Nuxj^A}P9Cc0 zjNAdE87CN$p#tabjfr#E&a~dm1Ply`7+VDg+-8D5eB!~g6KTrLASha+K zfkp20xE`>Sfd<9n(03`t*>UBDiB7NY6--ILJpsYsfoPm#w-fB`Y5jz z(1o5pg4MUaRjSxg^D=vVM9_qh?WIeMgPUE)XpXW+>uVMz<&^!g|1S1U{_mo?y8mC< z?cZB!SP$A!>~sAkLwpPS}rnsO;uTIMV!+_Bhwm0%*-xnt&sx> zzN#X-+~2^HOL#JQZiBC?E_4EkWeh6OpQo}bboyM)YvXG;?5)jZWs;zdFmM79ag{fm zR>+ptuxV~#%h{OE*$c`ZbZXj^o3Yp1$QV?e=5`v7W1jU8@avsrz~{BmY(v^;mMW;I zG;^(CLpormZr%AH2VEqx`;(oaA6e)7oH58vfL&UMef*r8+Dl+}HdJNZD{6W@nRB3A zFff20K{fE!*{2;a8+1}^B0GZW&pq%DLzf~I~HQmMr&*SI|52|fc* zr-~2}=ntn!01~jc66w@Lod|1(H~_*S^R=ctUm?re&)Woe@qr0fJPLZZ^slo&F(U`C zy69_O4O}lsl6k0QTSdLYzO=u2nNnZywM(wH;mbDWrwiv#na?#vejg_Cj*2w6pFjba zKF_rq-uj(Mz(V-|D5K*xBEbeYfWfX z%K*Qfza{;DrG;i6{;dZDMEzF}2o^iXD8T@FC5UUB*^8fb<|HB$?YZX8Bm#E$6SHyp z8vgPMfk_pdq^T&$nPk&D*D}?=JqC-}|UrR1g{;`mPNnN4uJe7Yk)7?gN?11htHrD%8vD zv{pF^RZT|U*WQeI%=YEtd@ZepeN*lhUUF6}+)zbf45WXI>3VTaO)_F;+1-DVqfyp` z6egb$cvjVUip;mE?P| zvaB<*d3`#?$}oC4Rb?r@K0=gtoqC~uG5jf9O`X34&vL5vg1S9(gF2w$+#ud$#sdM9 zijmMQgQ^gJKRkSHQ+;2DwX2CEG*;2&N4dqgo!&0y!VT~%lOJ;5)d^V@K_5Kwi%E@y zY^tlqy;H5<9Bh~Z7)H*rg|}9+75ZXbdM5Tc@P{H@NmsrONZ12tEt`D@ex4>&@MYF9 z+!@W7fhA|LySUy(Nha0%(NS3)rX|?-^lQyteBYe`YIB^|V_pV;Db&_}tL$@^roJYx z!B)*!MM2EC%iGSlqOx+)JR4%wLJ)c5=IgP%U{afMb46#22{C9dpxx+ztXl@F(#@>B zmx?@Z5wRODXj;8et3XEcoyT0YR@1>Yw|!nP*4q1&!3;`%?(cM}zKYWoADjQyVv;-j zo5ozjWw;S>?~hxQ7R}b>V=Z>yfLw8sCR_8F*<;W1(f(fO`jk?c0&JS~;yGPa-tFz| zcUBTBj;V;|;CXO(!y7k>0qmIZ-sb~$3jO_ZTJjjy&6ztKHu3bGWmy+HQ-F=ox(@qvm579-MIpRD6Gms~}j$=q$fq9U}% zC;dcVE)b3!M=%r^dy#lkE^5>x&Qr4K4d#?t#SOlRsmXaCVE{ob=0cP`8$*fp@q)-Z zTb}TnZcs$tb&vMfgy0s{wFKJ(ykG*i8{vmenA)(23m~X{0Wh_Vl^2e(>AHdoP%?8= zAJUY-Fs&CRs1~(08HR=Mkl|2%NI5~0FzXe@7u0~Tz3A(75LAhqrF~D%kZnMiI78Hr z{8ULw>QVLJV6+zdezyXnA5Xf(fpk1U_WlGJu?=^s+&=i^REt>tHS#LmmnKxvfbi{Z zQCOMZn8&eyPk{XcrHpp_^r((DzWOShBfCm80_Y6pfYjO2Y00`hH$R}C+{jang0WTW zJ62xITf3hp9b=$1P(9|RL<&5{-kAqw!pDTe($>g_=&V+ZCh_p{ksn#ZLj)Ws0;LR-VKrs<*Nur?C-2axo6FP)$OP6p1zv7*MO zzP`QO&sml#)*p3r>P5=1h?j)V;RbDjxS|E3G7C0>R{yptIFsFNVj-y3K37v!!0g&?6ygudE^n`WWK^4KQCr7>OTF>{6J*G#(A=@>R^C|OsYD+!09Z%ii?x3Hm zLpD2XzT6^Ri^NeaBN-G5z=y-9ZV2M}IW>=9jTzWGjl^DD{N9@W@I58o9neJbxuxdk zcwVccDNP3ko%|tg_zXu{sW-@iktrJnkrd|IUty9{6>+4;!oh){UyzGzX{}h;o87pY zOUYWk7>Z*u97}n?AJ9GR9p>90FZ(MWhuIfQJPbUfVT zdeHQgQPqMTyYL*ZBf@;?6x*<^reg%-a9{}1P8M>`&YocYOK2*{50WdAvEV2D4Qw@I zpvQYC`@VO;FKt9pSR9r}J-tBAkl5WnGi2a<^0}mjKEbHb9|3~bh;fvH)sHq5?OB{2c~iuaF@YK zjRI8CUK$dqa&4mE%myD}cdLh{Qo6jar~LFO%ZZ2f@|#DAqts|@WzpWqHD*fn+m=-0 zv4Z&SzO4+84z?{~$oA?t`|ug@bncc&jbSB%Z1vXG@u5&1IKY{aBVZ)5kj?wt z2!<8l(iU&1Y|1V{Vy$4*HwXL501`imBW7u=re;l#znU2Bp_Gg_l^w0$=+uDLaXN$s z7av_80SQ=$!yWLb_^s@+MUHkv; zpD)M-9f((?#;51BHC2&|&zh`pmuWNf^DHO=HZCHx>alYBA2ksM{Z-l)j^-^Gv2XRe z_nldk-EvaIs}eHCrgkJUU(F!9Th_@Tt)kjrGS6yP5U)4$GnbB82npu;IEV%&?&V>T)1@oetl#iB`7N#4|0w(ag2vGdng#RWCLMJ6i@f#i zIM+2*Ba3*Al$mE#rgQ&Y=qDZGoVB_`Y~wHG_O0V&Q-e06BPrgHb|rAU90IK|6{~SU z!d0!N=%oJ>FE6~tmxgO=eQz;GU$1nSP(loP(*m6@^jC?M+?emP6c-+rXY>JHqKFx( zffH`TM^Oz|-IH2u!0eh9yUsaAvf}FP{ik!tKZSR!F1_aBg>{;So`rX@e+hBONTk-P(3{pLtG_FDqLfUR;WUZd9*~<7ZCcLS4(D>L! z+hM4POxc&t$O$<8iTLYO?3avhQl%C4Rn->J4Y^R#vrlM?^N;|lnm&e) z`Ouj-#=yRsUl^Yat(aDDxSVtP@b1*4JS{zJmP&wZOs-M7>%W~=gNte*!#8`(o^UWV z?$2#s!cCjme;r`e4OJ9#1J6@RNO3&%sQg!91Lc_yykov@UdhxHEWw+QZhVvUYw|4> zeEYL^#X#RZ2SavL$*%a!-$dS2nd#)s>gcOsfRB;RV(XLgmp7f{Rr0)ae+Ji(W!_xt zWNvYWIV(Qob@=uIw2|INfanD$^_o*BBx0Y4h?R+FA0NDRub&$M<$I}&ejNi1-r~)w z!Ff6rw7Guj1{JvLUaePvo;XyDHgFMeb|x>XL=SoXb!)2UWg43-CGamQvJR$*n3W)# z0anmlf3JGZGGSmy#>=;tNorxFT9M1!L-KY9-%Y;DO+TvNMO_XGUq7Q)^v(=QvFafG zz;dkSG8f_W53IpnH0Yk7VYu>@rYtkpyD`mm*nqa{?3su|7h%)%(CmHqUqYpbfkMgl&EEeNFy8L}rT9JR`ETsMd$4fo2W45g#AQNcHQRUkfy;!y zGRH4h1kNXp9o^DwtZwTi!_vsna#DF+2(S4}szrJp;Nj#WXqLX{t~Ce$lk=;7ag?co z8N;kb^kVKlIW`??AJtbZ_qFb;{FIZ>1))=ql|$! zsZ3h4r-5JX1;DG=>X%+L!*05%-+yaJkm@O+>CMT{n<{c&IlrHbsbSH1!pB8I8LVm~`B0RLz;*E$bL2R?0>*?lFr zl8uBju22Y{KdN(Mzs6@!gEZBJ3^aYhiQ=ZP`*qmwF4Xf`$^f$kz8RTndW#op)E7!b zaB2ngpowRu-W!?Y3@9eHp zY~1?8gDYlyKi*(p81Oys9$%Qb_FRvaJmEg&*T2#cD$^A9m@W=Z?o3?s$~*Jky061Y zP)SNf;FPafII)3UzD;5xYN{!dAsz4N``scA;islAG~z_6DLFMk03sEdeb`5F#5MQH z=_};~Dvn+lA8;=aI8#q=g6A&47Dhv+7ZS_^C-TUUOI0b1s|N z5kQt=drDXy|9b};u@5u+ly~QM`HD&#G+C?W&XMcQRQrdGb2<}KhpsrTosL{^`bl0; zJ#+q5m{8Soq0WXRuI=Hu6>f})5svca78#$_?Q1~a0SyKb z56l(HLL6oL=+~1jeHt>{=5Wgsub8ai7*}x!nwLQjF$B&ZG!ge$&rd<~-rDod^x%Y& z!t?Rkqo+xHwc2kGSdNY%`GEIhM5eBu2| z;z^dVq(j2N)kkXFhMz#PySXY@%#cH>;rI*5A*ZUn9^=45E#U>iS*chMul&RIZ0rf8 zmpvc!`0&*O7Y*W1C*G{!PQvmp{YhXyibQ4JUD>JEK_U#bCiQ{FQ>*5CC%^maDeffQ z$b05uVlc3EUB#R_iH5B_QLDSf*ZG0W|ktQhtyVA`?Q|77OC64^WS!j%Wesi&7$ zYUoGT?}tN5g4P7O0%tP!@SxTV_M1ND`>@4^W#;`_d8mHO;+Q>GRq~Y>#@GI&`uDlM z7^aLPYv|-bi~M2e;&A_#9b@lF3qcN+p4e{_-HzYStRh7zSq0~&L{&|X**BjER)4Gu z?l-R4FK^n>Zg8k(NLDaWe+PO!%7qfi2?kBc!*KQ}saH0P((f?Q6m|$t>J$NqxPL|D zu?`*G+VqWKukLN)|7CxYiZvofTQ4Z|1rs~x_7<$arI}U04>RB2D7dLIY)wQniUGkb z#MC9}0)?JII4T&tt^dINbL67iR|vE;21jmEAt~79ZKXa*2fJRC+gVPwkWKURF{J7* z=ebPZ-+Z`IfLN&RmO}>AO|K>=Kgl?xE<@a#9dpi2+HFRmbc@gdL#3w4j8Z%l6nMDd z#wmq*;uT`_;W&>|gYV81>s# zps1L-L)e2Ac;(a?lumMIvRkS{^ZNessG|^}d2+<~pnO<^aDPC#uSV|JH+hjciqNlY zG>fOOAL5sr{+wR9BjBDn4O7hK&~AoP@#AY_?~Z^)r<~tYo=!DpiL-X!BqnyA3-ps$ z7p|G3>65_53;0~WpLIvIDKBQ|XVlBlwN<}@k|IlH2Y%Pj+aE&Yx}JM?`{8n$SppfQ zh=oeEkaZ8)B8aDRf;j`28d4I*u+aVLlp4HGLAzeTQCoX4^Jj-uT|`A(#}w?KMfNIz z_J`ZbJpvU9dnyH1tHa)b?<6AU7Nfg#T4XL|JGONI-gd$oA1|~g8EtAs-U1y z5E7L(bbpwZ$9*+!u$<@*5%nyJ4RVDP3?oxf5dWl}#W9cLK`;W-{n;Utc z!Nv0#A+GqAOJCel(ip-4wIH87X%h&-rm6dJeQQ96T1=&F;uu6EGm5H}!3dV3c1bw) zQO_90xrm`omuu|*RU3>oZtGFF{%>krn81Hy;#3vx*bNGy>QC*Sv1|+P6D$*M{YvyJ zQ)7D95R%2CsRy0~RJIO~2e{qdB zobg}BlL+iu72CfA7jjJ9zf)5be)uO;l9488>y!d^>5tv<`hZuqzEVIK;opIg7W1%7 zznk5tJ;{K6$Tr_h!}23Q+QT3?=aE!m_=|Pp{exPz7WZ*)69r;954-@d6HgOI-ipm| zxI0bm4&8(+(GFbfr`70da+TkB`)&_wx(GA&X_`d3KFNw@hC$E2kP_5}OtE5^Ml;On zkTlNl3EP@W#&8imYfy_cdqXSnzNJ0i;M*SMDZ!xLeep+={eLT{#)g36^JS$G3tXBx z>BIRfN#9`Y|2RD44fkPd@cz`k!B5B$cT{Gc)DA22m$MvSTlH;+J?`OuLsL-ZO|!7) zd`Y-6z{$bhO8d$mDiA^9e@~7e-%w?L4GrHHlmQMk8<{gV$PSt?eJ8Hkj$y7@R1^U2 zYI?{a+9R+PTt@KFdB67A1mZXL>~f?0RHH#6uwPgdju{NGzz~yTZHhn*O!2|7(_T}@ z@cYG;i^GELl!#_Juw`({39~{}q!gjVkJUA;T7AF`=PaF(i}PR4P29v`2au-kWCpWf zeYiG*4A=n@BT{E1BsGW~c8#AcoF1n}_j?_$IUJKT7T|b2%Kv|_3fxY7QgL20%;w+E zn5?4V7UMUNkE-**Q^Q;B@07MBf88-X_Mw4L`DGa^ycf*aASzBq)gjX=m<(R)C`3>< zUJ6D_JtB|AAu4*ypcPjKdT3_5|B=|e_r?J z$~i=U)sF8rK|9cNX_-+In1U$mgY2*2zDpLCa1ft$GpEfIowMf z8?2W8z)tudxqOJmux^y}mfL{5Qal<;q2z@#MOw^16R{w+aU2#>#NFpC2F7O!?(HYkP0)5^^WMmoNfPN?}$NQ z>9+~XN;TAIiOHn2(wLs6Ki}&FH(TVzewrv%GVckml}(}y5Gvh9?VFXTiS$@@*c2fv z4Eoz^1aW1~ssE^$N{cxR4+-O=lKecCbTD}kdp9qNU7@D@_(FiFS;;h`^EP2YnY7)k ze16es9;PvHk+T2jn=TIq54<&`X1uZbN;Pp|D}<~^Q?5@XuUiHmy(;>r+x1oHIYS&w znwstxIGj+F^f+tsDso0Fa@(L5Z(kft8x+tUETHSV8oduHKra}h$h1*XCA}H4*SdDN zHVisSym-88zNJUG^WRBceB5dCHzXSzxy?A_!zA9Uue8l>+dSpaU~K(b&wfYQn!4Mp z@Vcu%jd|U~3lx=#zyq3d)UIt{Y<mMww9{jZ?vUw8qlCDgORHAHdhW zk7tK(aXiA{w0x>BMXZ5?Z&v%N@77mR>`(eu$(&{;+9TIJwiP3|H@lrg0#_d)ZK+8d zhguC-rZQk56fIkB(zk&=9r?Cfsuw2qQr<6%ooP7a*^fV8FZ#_!5V^Q3jm0&_aq=oU z`;Y8>Z|nRlM_=6#`x2kl84M%)<5r>*QV`WPcLna zpTR`!Fg`*QZYO}o-s1P2AXJ*;$x3P3a36CVO1p9jv>nC4Blq66IBTj(OcPGyZkcOj z&rl-!&qLq0{rvsp(%DlsD~XXr;AA)5EuEnOW6PMX`Mn`-9(*%t*-q|uPg{%M5x4ub zMqBpbRlIu~RH3H;uxr_7>mE3F%yLJ`6FS2F3PsFP0>1MDFpJ8!C;%o8c%H38OJh~= zk`KE5zx2Ro&;4<}9TH3I-`O0|t{JMq?<=udXibIayAN&!Zb~E!%U1uQ;;HIZm|;_q z#dheh(Upi_5<3;XQz!@%Yj?`cpbNKVO33HR9zP1fTO=(&bJ5;y(2Vd#Q1Y5=8UoQ@ zWXC$~2g={lPWvfCaJT?)hWu64&RUIEt%4P*WT*?5=mY2 zYEu8MIw;%)vtEIs!6)Aj7T&*RUo-o_sL~b`?H_FTIoj$?1>no!Wy^+YK6T+eHEaDB zxOiy_Z4KRZfq!4S-J{$XJe;Q0e62FlxRO-8abd&Edhkx%?zQ(oe2;PKH22K8Qxnlo z*q`>_TY>>n!9k*mE5Jm}nS23)w|U*`AAmN6RAH5Bb-FrJo6C%i*s|3VvE@tQ#P&dx zG2r*^e(C1}gG)22kE-OT39W8J-(1O;q%AZ>5WM_B&Z2h^3_(?Y<$a{`7?PhPM~DVk zWCmC4YF0o*e=w#?>Ybf1PDec9@c{{vC^nwF)cD2MKo21)>;xG=T=hC#&N80_7~?Or z{kY~>EHh)rq?sJD>2_)JICaV!?+N}q^gYeL9Gw**=01YWJ0#NV5!NapBYz%H7hk^} z#O6CYDMmepRPktR;rhJ6PIjc!+UQK;0NHTd=I#lv(sAy4f#1K78{cys>x`2Q#E0K% zy-UTJ+E7B%D;;dYLv0E#z)Eu+y~a;o;=}tG0E(2y(#UeWj&dvM(R!%Sfu$hUE(L4M zBzKSqFjOhM+HO-UPg~^BICGoC?MQTDeZ+?Z%qW{qFlUZ?2Cx-0>|k>nZyDrNC#nH# zcR63t#R$EgoFn8tvCqpnALh*QS+@lH+1@4!-&0;s(7lrkcoja)f8V~+1j@5`dWJtG zqh)zRSr9+-_(8MuccM@p8cn)J7e^oR$tUyM!`A0D#hdl07}@e1TCIJp%eN`!cH=whSiqeB> z(;(H+jjnyNW{=@{#sxDlO!ohy>OAAwexSDBt=gh!OUgsx4v%F&h;tRuDpX^1tur&HcuQw~^oPoO7M)T;GEBdRq0`JMXEE zu`YI%q@KOu61;AvijFzw{Jp>9n-+;dFWChuv*V~SZ%$N&#kZFVSU4{WxsB0@P$Z(5 zb}B~JMR0vW9pPF9GiwNoe~VxgxYBQH;t6RcGu;=ZAZ>99KY>(R9&A_82iLzT1Z*wtU8`7bIvR4tJ7)AsFK-DER4MQOg;WKf{NkrFw*@ zh|Vax$q;No?q}yCG?Vjd9&m-isQCjCsnig029@Laf%ZizH_Z3{^NxX6sJ8lw{p9b4 z%7Mpu)Qs_vmev!|ohIu`x);7))+YYiX1ac5F_@&drhalgjZnBp;x8|`)w9d+K!%9Y z3~AQ)zEIXEx_lw7mg@qR3VMjWLd}aKuTXdQcVnE*r?wb)E>ArFh68iG+S&z}&P=mS zRpc}F>wfeD*^KrD>K^hi>@X6{Li`dPPWUe7{q%h_5D;udUs!Xmt&Of>Q4Gc=c)b= z=W6pLe+vDv+`$|%3hT1mfYok{g=Nt zHHuwsFQPc!^n7rw2KdgOc0Anhh8Ps2^eUZ@y7^NXS@1omLWy{>Eid~p8^#l%A$GbZ zHFCJPZ4(>%z6W{n7Y_D3z~ketuW@MVt4A% z_&eLTnPrloxkSw-|8QLFQ4ZbGfG@Bp$`Dypy|SpMf7#}W&T`h9qK+<8RwwuAD(6+Y zi0>6*r-+iGEhTQ(_}R!1rX|!O;uHQc>|E&=bQN2!R3E+QC!^=~Q|xNh{R^g^3zwU` zsQbrje^@Sf7GCdFU`|^ax4;r=z|^AE)zm}We-Y={Oo+vDsn*g|mKhYfLz$^1YK+^X z!lhoKKkFiB=b}%o+n9Tvn_idl*V4n!p=7L05eF6FY?(KB|Yl7 z;{j^$JZ>jT6Dw@CK^c1WF73GBn8qjYgFN>}__eFQ-lpIUS9M*63KiWgA6Nfr!}z?o zMhM6$vM)Qc1;ij{1kr|rj7sa&hP>GL$7L|%wiWr; zXbdrqNtiku?D2Lr8{bI&+If{OBR^_EqLYddBF2a? z8ab<*lC`*yE1XL=i^^!cpaMsU$vU^qx0p#ZzMgVd6^%<$D>*SK&LL6X%a&D6Q1Xmk zl_k@DGC0^+xk(e%QoB&Qn}27=zwIYi?H^$!;*ohFS|s@&o@Ky`&2M|Ux9thMNBi}F z_)=NbeC^w+FYCk$loQQ7m3%^`K&-*UmrS;X{%DngN9O-N+SKBv-vWf}v^%t8w?uc} zXbCapEh}injOV7k87f<=9O+==FOPNy{E5c5&wR=zg%(zOoCevOa!&yZ&fKr`-`CT+ zLLSaM@UxG7;|95}oAKH1hF|SzBTkh5lSj&mvJ3qP)>GD^St(7EBgGhr;eD9;K|aI4 zH*U`YQDSJz3Rhb#D*RG)aR$(DY(UpfHoJ%GEiu=VWI^O+ok^yW` zG(*nKHA*h{L5@A~$iXpo^=#x0q1>=)Vs`c>(dP_x9jkb4I1dxnt`)REFG!x-P#lnr zRl?dSPi_ z@AHjDR_LOl>2y)E@*!TUM7nIzN%`Y&yJER5oQ}%1gcx;H~ojha}{VP3s5&9JIYpAk~EK>Z94Fq5;2g; zWD<>wkR)(7XpIkRs6M&H8u(N1`ZKp*_Z+7Apd$Uq3zx!e+@@aFKV-e9`Rmu^;(r3q zS84cAksr7->_2_rUU_N%_M_yVI@`^? z)iNR{Lv`BWUD;Y8 z@lC?PhianSiu`t!aDcmsV6W~P<|CUBzTni7t!v1L5AZp>(6sy*psUck!)vr-o(Iuo z6xZeZy!WWECW}0z-m1AdzM{tGa^c&#cW0}E=<$g^ecREv+?XD#zQ-h|8nstVxkI5^33RvT zpV^*bAYoppy+Yb){LB4QAquql{!{L8WO};kM$jrY{*g0x=kS!LTdlG==hh0@K`?&i z_%lZjPQo=fl2URlP^Tn^?Cle9J^rVAv$cVqOvRU_+m43Ie*4Fsr4>0L*T4KQtSOSV z`V}zlFXMu{8N5omFN6js_$2jhd*$S(1YD;aRfWr?^CPBhWJDT6$F~C5td)!48{WdN zXgKB5pA5Z}6q0;8$-*G${dggg>)cSDIf})~{F-aF;fAlEQe!ZZxmQr&BKz3P&e&O_ zA%G6d|NLP37dmAsRK9ISAxUep20)F#SgBN(h59zUjZkLLmG!Hgnr%XXet|twx_{f- z*_qKUHqI>i!^gLIZ1@0lyFqHYmFyVY{zt@YE4I{9{>SMN{UA>b4cgi?c{D zEEGZa1+l9JJH*p5x@qB~qP%mMQb z3Y!e#aL%ToGu+|Zl2P=3Bl4UY={Cdx&je$deb#97gz z7Cy~Rhg#X||IjjrE)_{mt}#+G7=ZncwDRaLSC#ke*n%{cR*L#~u_k7BDMmZ$$RI5yHWKb9%#^I)gWfa^Yqp#CE(Ix28&TX5z!da6j&6M4<8t zq|>L9fe}}*N|Z|)y(GDx{guV@xPj?*P^<7ocj1owD*VqtordZqP$;l7_I;88d=FPT)mlINPGWc<#KyHHjwMhYIgoGA$vLNQ| zuk*0dEYxRdE~=%c@FRiMQAIP~lDAKaJS)Pulv7bKg0Fh*N@9u%-U{c7yQ0ieuu#UK z4@%MY5>KcLH-6~NTcyM#{D$^K?)j55nq$C!IbS}yr zUI!ff(7Y#XuH+0mLB(qMrp#v#ue1uUNfm(Ctz~jV8FUPQNlIjlH1E1*7(b>Gv!bz| zT0@%@w1!;jF%0bvAyvTV&a&4=sNdZ3qdzK@C>>J9ntwOE(rU8hKP0P04V#0A~K%58}D1 z;F0rjTai@2HpiMsw!POA0cDJY)CFWhJa2)&A2x%UoU6;-PnRS*1anN$A)1h};F#_B z9a_@!O5sY9>8!Z#nS^*6v!+24zvbr5lRo=53jBNAl;a?=Igy>GOB1Rx3b3r~G8@39 zq8H=E?zKWo7193uc3ch$L60X`v`}qwCuw{lZC=6NhaW)!^3@l*2(yI{)p?uHg#8X> z%-bFbag<`vo=+*om>eisOGtFg)Y@W>R5U~k5xaVjKsWG+!$RW|J()FM?CA;ZyUSNS zkGFihz(F>0t?jo?!ldR3K=8Vb%`}ZnmByJXwT}4>>C=aOd&yq6)wy^+jF-xuH`Kex zhr~U@hgvipZ3ajj&1r%a1fwX@?x5wc?{LfgbEEVg+9fz?G9XG&4gCAnO0GaON>DMG;e1{svG0zz~d7^V8#Kwgq zl!NFyJII|Z=~-WRU=~&J1P&gGKS#rrGqf8)74SI#UnS#6{^DFh=>lnWg2&sHOKw5+`j zlkxgvqfo{&GloTp7ar|~d6ee}!tQGVC@W)UGWjC=gXSAunz8pf{*<}%kP7G@&XFkXO5ovAatQu=*w3Z2e zmlGf+^%x$!-0EJXw@<3)tBgL%aOr@q7at&atcEFhwyBJua@&dkt|>*ug@uH%n{G zj9L5RcQufg&E^Ki;w~gIhFn7^kjFnMN(?UT3(Ta|0VDEL6zZY!0eKffC#5IWj^FGN zGZ#SIt!HwcM3 za7N5vbvV^8Q?W77Ry;>VD5Uba%(JwA(RCN@0hNAdoh*8!;PjcAeso3mi#vYZ3BoR*A+w)FwfnV)>~?Dbot4}A!^QnYZk^Qmvh-yvs65i zZe+1 z|1l$KH^bmIF(`)C=NI3Et?9{Qq3tEBT*{AEy!A?#Lbe)^*=mr~+w3<_AIEEg|1=Escw&-Ku_t6sab9h3h|plwo1W?u&j~K^uxbe4V zb!lA$+>X<<`ok_%9XqdV5MO23uP#E6l&LH7TJSJc6&=z2OhZF;IgRfd-Ll*B^sAbe zug+VC@3ygt>|-FihY~IRA#T#Cpp+&`--H15j}{X5MS$kTpp~n79*im2R*}msW)>Ek zhxZVzS663peOzn<#O$^lJNUZf-a<<%OmsQrBa}76^E4X|d(OE^sz9gdFMS05>8b}b zzl`5Lt?!RHL-k&IkgQ9P+RN$qt(=1VSE{bSzLv#6z0-ik-*3<_Ty zvftbEZySoo44bnRk^3)PtN=NU9hb$ENf+mWcFfZFqCKKVueE~bZz?9u)A`f_2y>26 zbOPAq&ti^oL7k{ovmCVwN%M z{gZHIjUOKHDKk?);zQUQL#bv^IjZj<=p?u@5v#jM&YA6An|Vu*7z)sPuw0w8T67?p z|9w;*pawVoNu?C$*A+#|n;t_lw{s%g%5hoD8wiVqk~m3MmBN`-@GyCl^kwvT7|9=u zkKEr4l%L9{ugAo_Syglbjn(bsh}Pz(5*{SWX?cUK{U)XG%x>Sq$xHI_i1!S^r$*O} z?<;%h_*M>7<~LokUzYf;lGrNJ6D+}!Wh#^~#6iFMEsQ|pQfO71 z$$iM9vp5(%pj;)yCw@$ab_aK*uP_7tLCsn&8%}H?bBgHcMEvFC@`-*;6%snWXGH@vlo?6Wt*cumsuF*xE7`B z5_6U#n$ICRLFii8p;hh28mojjkALw{UYUpt*7I!Lwy=zPL@nJ}5YC>uxBynWK!`wd zra+80|95Fw?8xESaIAyUdI9i_JjTe>JE(j~`PuZjJc~X%u&mx1%4VptuBrnbmo^N6 z*av&|M&!7L!;PEk=Z1{+cU$NJmCW-$;oJ0H_3ZXmS92vIgt&gPvzXfHW`ue)9X zZl6jb{R`-j9Uj_?sq)^J$IN6W4!mYVC(ekJsRnvZIlYiYekoTf^f!1qdoTP+p_&%O zYqAWaxMdMKHLzVF=M}rK;iVUKs;T3eFCAf()2(D^3tPbK$|VKqxQwe!!eQ0aGX?e1 zyee{~OKBn{f1ymD!1#F{GowoxvJV%@0lDN9)>r`w_FEh{zc$8R;XiN1eH+1-I%7}b zyyie5l^c??nKXxvfl7uw%WLDl0!WyjNy_g0%kfYH65#7^O*n*kAuQ=aguW6wYi0pB zW_&p?wua-R12^omX2G6~X9(13r}zLS=!@z}^LJa>ww-oKKG?%a_d^xx#WIG%t#Y=r zz5qW2?E3cfvs9YJd)B}G^xwSU|7CcABc!NZIV5z7`}_h(|KpT|?(%g^8{KGk+PLiY zUlqWr63r&o^8qg`bn(vhtWB-K$!_x6YwS?jwaQh<7~NH_AKM3}SVe&pA<*PI?gtoTpC61$x|u6KFVWw=i6fW2 z?zAM7aXtuE*^_w6Se^+P4rl97JY+hyEG1MtRGO)~)>ve^Aq+#{JmM>CcV7%Ya)5 z#N4}Lx}iTc{oj$Y4yrj|c5RQ_b58N)njrA1YsR+;9V+7RmOD2YVn;(xjmh4qskaWv zmALkeP|X$avv92j$h|D5{cc^iLLH4gZHo^2uG>GY_`>(He#-DlV9V_k% zT+KlnHGXg<9=uP~CRgHf&Sp^q z6FGBDv>%M1+k4Xd{?tY$LQe2S_P?}m;hZfbZzV5&L@O$!fbI^tvcUdtn@$4wvjX;G z=={NF`+2i~%jIP1Vo<>bd*}DrI%}FDMqj*CEqGPzcacX(*>Usa)V4l9wb`z=yZZm9 z?BotDZY#>m>r12)+zw@F_*@$%T+Q@3#?JqWe38R7oj+)6*K2&GEe>j!=oYEmr3WRG z47Lv^G9fx48(a4KS0&^$!HjjF)i7bxOF@xBCSy~qT+fexii zz3b8BFlm8I6cgjEU>z=WL3$Mmu34F?y=&XsE~)nmW`rt2&za;VugP=Ln$+Y8ZR);j z1+l9D_m9)o-U%zmZ?|-W^VRqoRNG#|tM%Es5PW`-Ye7)r~1gWt#wW4ahecR|tbn{|!3Dxp&l4FJ`4PzjML zu#c1NBueY1y4MDQH@)>zF#9F$v0SDLuAqXmg4k;x+#l`amg$_0cfZAod}pU=vL+T| zgxe%REPSYw%r(+g1p0pBrraKBwiZye7Q(HW-G#?QaZm>ucE9HPF|Tc%l}%v*hlN*U znJ?&S7mZ%3@dH(ti?MdjTYnF7tYBL4B_ZsZ#VZfzsnu|X>k+FCP^J6TqA{EFObI~18WY~`lQ7k(CWh=XP%`M2v&z~ zS@vG9R)2(N+~tzH(Ykx=klvzP%Nqqh8T!+B&hcWuLF=b$1~fZ5h}onj(YU9~VE+3r z;+wC$;?sZ^su*pMMr@jx1`qtQxZ0F5p* zNljD^A&G%5ION*=d*?A|u)OM|^v$TI8M)gTeJetL?pC67={UZiZubRc@2OQXId!|F z6@guXiO;W{4fUWa&*~l`?7FDJDDUK*En$;1s&BvjlmGcNal6i%$n6FPoO+iapJ=;} zOXH>UebKIR?dh&%V7h~d@JUTPx|q~Q0M`JleQVV-^29O1_?cz5s&ShQcwYOYfD%h_ zUI@$J#61;LciOsZvY4AB*9uIKd=Gb(Qv-QTv-)^;-u!z|COsARFRlg%>QAw zE;X$L#h|*p_L+M|Og0wWuK}^yoTQ#a?f^O>s%s=1$Bx5mx3u5gh=r3grt{m)AHorn z0VUGpVtDS**z6HvvXKG9<7`O{j1U=6p5sprtT;TjV4>J9P280k7>Eu)^o`_PN4S7| zK;jdxXj&{bEciGb8YbUHa18w1-Yknt^|jlyYR|&kSKgB&>7&bLL;C%3^^#s?QoYBl zu(7hcRmd^P&5-pBXnY&Mbt_>r_(xLd3DR4aoZLOwvvc0Yb5=Q8QwiN& z`tODMQv~sMBQ9Cos+!mKKRNSfvgUy3ujy|!`o4CRiYB=}{qxHQf;B856G^KyC@ zbj=%E(s7wr0-pfb#aW3Gz24ks&6=e^h3lTMU*RH&n>x9d^}4|e{1CH<^;Y4e$hUhb zw0M5?Lr|Z)K%s7+&Yv2sB#Z+v82G1d{dI1Z%#Bt53;fH|G_XIS8j6y%TYZ7c?PN5C z2ai}wTNyIfzlZzG$<;i0esJA$YIj8qB+j##`fXIF0bV=ui*Mtu6qALF-0a=0R*Do~ z2Wo{y+qGvq^9g*cZ~1@;%U{#1nT1{xnSPbcZ#P498A7vF18QvcYOhrApQE;skX?xR z8PD)SR*)Q}y-_=KAt*zo?4))2fOu-Y4SHm}WA#`dlZ=G2lY#8?3e=xaZv?G)4!5BA zY39J;e4meX@3Qm<7DZJ5&Evo<7RR^9JMmjr~eS?1U0v;uZ0jDx18&#s=q_y3*V>apnFk{{M5jKbbYeq zh&69VV|&71yM_&t<7kO z{iC&zTjMzcy6_HsZw`)yxsj{UlJD2Y(e4&w=-S*%nHw)?Hihq3ewK?1xPo*)+mYt4 z0dUs3`;3#GSLMI$qd&I^q`rjV%}#!XDh#Hf5R!P%>C(jZ1ixv}T=oBzCLI4qnt-rm zp1&M}oZDfgR2255Cz-Deo9JNUHa}+yzRu89WU2nNano@O`y|}Swe;$JtNM`oqEZ5y0G0T6ici#k)J`Fn;B-3Ba{V4TjdXC z3-eEyl16_o+|2>FUk)hs&fv=K>1k?cPhIEyAZie`H7!#skt{meUMsrqtnyZH;PQi~ z^+!MCmxac4OSaFy)u^1^62HW}Tq<%q#6pjoa@W)C6~KT836vO!BsS?2vA_%s$TnyOMDFUsY+u zeS_k22tlwFXr8&!7p3{c1Qnxqve&4n=@$#r!#0N3X|HMRKSmnHLHs4ozl0fPx!zry zX||U0eOzRL0VZ8+4I+G3!Me(f`Ru;Oy(!Bu;p%yY5yTm@Yd_ioX)3H{+_*&MT!vP8{ioz`HOOMQ*-sp53TofnY8K& zu?KmpkHKBbWO|Iaf-|KHvtY}+Ml1Q;pzdA3t7ozkK#$k`kPGnFk4a{h*?EJR0tFvn zzT@J~;$pWqI(KI>+!auvnF1%{b^0X}olg>W-4(i_I#Mtswb5?c;ZGvNw&q9-38t(% zH!xf51=`zYT8bf>{XQW3fZ8l8&5G?Oo=SU9=7lpMuBnv4u?K?FZ+Q9EK64&jwX@hr z2D=iCZ@fQRAWS(uOtKe3y6j8CP`aYrzFtl1E|xVO<_c#KO71=KpOnQFvkRJ*%MBO) zHLL`zQ4-(?x0}NoUAh;m2>j+6O)00(_R4|u_53ZZy8+Uz`d+f8@{o|CMdeu!@co5< zZ;(DY2$j(ibnDnpoB04yYwlA6>ZaVSIK&-)yomGP=d3D19?8yM<%tNTgq*b+2LH2n z8rx_~GHG{FsrNXO5j$h(ynWV9?IYUuD=N(x|M#gIY+?GZkM7!tg{icVZ9~DQqBkiX z7VKwcd1m-mI?h3v^0WL{z~U#QRD~mANYa=gzx?*U2W9s=d6=dj{Ax5H=g*HqbdqWn zF$y%#mG^lPZJ%7snYbz5OXL79q#~}pEiJPk3hj?Q@=W<>F$Y-iqNjg(X7wFFbt}{= zyLYM_Qpp~f1wb~b_Vm>iFVe}gkjZK8QPydO-h3jQd#q{aeT2bLKYU5>WXOK0{m0F{ zsc+wx8_8zmxV-Q{S}vno0Tb!Lq=L#u^F10wKX50=ZVwPFLd{!yUM1C!lBh@r39?*z40Wg7LWJ&YC;IR3RIcxR{WuqQo$oo?C_%>>IT0BWA#cjz)wah zy#YRYYaBn$X9IB6;Ahc=pEi+)#mjQMXw=~EJ{S)5X2qX*)=zNG?Td4`pNG&z`JJuH zPvU>AVH<-hol4SC33#xS*)ds2v=^?Xa}u5VdT&+)Y2D(Rb$k7%d8yFGTIk#>ory~I zdO^!lOMsdQ6`h*)$k{k})smeIsrz>VV2~E_4I5v~HTc`zwLhcIr{I?3CnkGA^!5&ZW8LkUDY<`|H(!WOC@?fNYo21Lmn%Vx zYO7jGwz7ZdE(!*3GSr7!dm7X=30jtcay)iy?ONQ%nrSdWdI$X*=&#GK(|QGM7+r?c ztpN6%@WwX(5N-@gg?eEDeK<+fzxXq@n5h0oirLytYeTBXS@+=s{J7yBYT`c?NLBU@(L7_59^D09JT0PbY)_d%EZ%k+TejWsO z)&BEv?UT_Tmwr$zf}ITf_uz0>CDfx8$PyALuV`KufbRve#}T(3SfPZLt_vwZD2^SY z!WzDV6%J_ouP4SYNu3I{{O@l#hN?58c9pY9Pu4aS4l;MTK8qtGU5PqvuaJJ(rtPC| z>-9V~tW7IVHJ$0C3!P;W=h`CF^`KPQ`5@v+nu7qE{Li9QDY=TR+`kX;w~Arj4S7+qOGIfyvWW&Up)LsyO1HO{td^?JSHy? zS1dCS<$X=d)ft&IE@+2XGk(^n=?hyvn#c4R9U!(vSAz98MV6a26YRGH)|Ru!cjieZ zc?;>A*JQyLH-^z^!rN@@RbAQKE|tRpu3d)jRwuT3vhH|k|W&r*)f3(&_q+sd61Q%~~6 zNy7?q&jkayx16h)uIkwlUpy8Ukvy)9?k)IY#~(EmRV)m;@Jhip^7CogmDt$_v;wz3XHh5Kb3C-S%PIwDYYuuu({ zR&jK248B#t#RIR$NGtve?2LMM6W40-(wlM%>IRg(#{1*-9lwYD#HPht*#mbD==bCq zccOL%_;6rjWms;{!p;agbdNta0{f0HK2KlMAn*}me1UTssWKg{d&VIepU9SNy;tp& z8T`n4Kx(h;p(WH*CBlj{bbm(I!8cX}<96YcKEuOP2%Ax^VYJ++X|gd3{qxgLbPqb3 zu1-PmKw#tIKOpn27!dXla=f+6us}YxKjO{zne^5+U{F zV9Pkz=SENi0xS|htMfpz+80<;CTdT$LpmFEUV)$v0c zXq;HV4U%gy^k6~ipixE;|E}^H*{Z#H#x$G3s59tg;30-l=MHe)=S$&DndSwHHNP*Z zT&*UTIdNHK{Pg4N2=NNUkoWv4F4QAOS86Iigx}J%eRvA1LOR+;M5=F#4Z16%u=bWZ z3+_(S#91g{sks+-;QF0mT8SDCPSMWdu8Odu+h7EHVtp0%*Ku)8&PF% zhkQq=fSQ7)buOKQAz%Zjf>>o2>r;g!S-&bZ1qe4**R`jzDO0lhGbRS0%ZNz?!2e~$ z%+t(CBTUnx6($QVWaVLn{g9+lWL0Yg{E2Zb-cYO#MiiW-8ds{psSCyNnoG&>j<(p* zQ_+v6Lp@=n*=1>^w#FEs{=9-3U6x7q0!zwYB-)R&ee#KoyrC{ZRjVY6seV_$vT9z| z`Ri!YMrkM1aMbUq$EMTSQLCRy?_WvmB(U(|21RTQ63c1R@^ios7J9TLzIpZ!2Dhe+ zym9Ti!To&MVd%q;zQuUqd#FO&hFu#Q)y-Qjm2S-YiAM7bNLfW&uysHfC& z!HP}cQz_2vn*BJ1q8gnywH(Z&7fzN@eec04$-=?Ty52Z5NTbNfTKqPEu*Fmj;5|>j zbJz=+D_(r=>wiVL-lbixW`=Jkb)MvUsB|9<>6>SIL8+EjYjsoX?*71k1@f{|ofX6T z2eEBsi9(NRUPRi|zUKWk0qCn@5&~olB#27ZdW6&?qU(z&TufQrb9}>$9|2Ts^tQ}* zVtI5nxox-(KI5s{wCb{dyi$X}9XvV4DujroU62tL=YZaqiS^8pb)c35y8Q?akL&VGyHY%WZx@e&MVR+XQmbc#0hnf zpM4N}xYkuX7nBZ*(mtlf6?OiUxtS_-X_m=|`?tp4+MAnmgWi|sd8(6HWd>gQ>|b3% zUGe?SEjd&8S$V_clO$j45C<|{)#+GHMYj#y z%tZ_`mb<;D6IWJ_Z$}28*yQ1;>_R`{nQ}K&k!?;ZCHPxc1`G+!pxpF`Lj({; z&lLd$3Gw@e#GunL$U8w|_+>jfAuxqFqu4qFH{$#KR&cZeia<@6_6AZW3@eS|-mD*G z6=+qha)j@zXakON2|pVf2WgL)hE;T_ned#Il=1dC>9e2XauM4W*sRx>yz{f@{kfIh z3k}ZiL<+!h=S$2a(K*ZE@RR5nJ5IMue8fN1S3Jbh8RyUmLG-;K>crJR+HE!Z*8&wF zaiZ_`d0M`t-W)ih`4e>^Tuk#Xw1skukg9kMkwM1M`s&xCPy-clSJRWS7MAMhE}6-w z_QtCE+xThBb>=D*dsV&cs_1g^JyOdfha-I7Z#?|O7i+ol- zq+_pLk)3hDX46sL>5pl&X8>zGU7UJeqjq8u)Upx*d8nk>YLpK> zMf)4y7w8xWBnvRaV%<+?eXwg+twh!{LXD_YyCO#zZj;Ei(?Gi<%e*USZg3YZG(^u$JuK?RwJj+?ig2ea4p-JE0xADg-}~Xw*D+S z|L{8|A7DBM@nG@5a<@6Rwxwh()>VzsfzPGBkNxvwZ>?NMP3gvn6kVWVE;mJ3RfP;uT0YfU+ zhG9TZ*d6idG~n3vgGTvz@bDRaQWwLvnn)h^9^62;jR(DXiWP}(whEga>kOXWT0GTW zk*+M8N4|cF-9SThdVVmp316%VY_T7%auCO$G}@6$8j4(djZZBPIq8De8ERONEya$6 z=rh(6*|uPLcr4h%mh-)R?)_mDvn!Oo`1$<3NbgCS07BJXnjmbPD(BZ4&SC}y(LnjF z8#yOE57DTUBHeaST?~!K^G)PP5!dtpflFerc!Ix5<3{qRM4&tnEW<+k=V7Zk8@dtP z@bHEd`$+9~eiN9fiA~+YpmX?Yb;IFdn5)d_wKXvMLHl;0?zYlyHyXheg$*$-@;r;bqXpVcaV>@&bQc91c?2g3+GPQA^Wc-J&I{@9@qq+TX1m#~9%;=u zYH$;VOs1?AWXs8(%yJn#(I_kU|I z36AKv)cQRxzk%@wXSkOL#}DOodw6lkv3g3goH&4guf;^1;``gWkI2*lZ9GG%dzB!4 z2+AoNHk#MI$NB9^PSA@lh!e**IwkZrC8AJ)y6hrCvi+a^T#-qcytr;i1u-lv zaJ0)%C&}dN3C7Kp5vzgy+ADV>43UCuC94h7kD(gC9q*{`9C@3D_yAg3Lj3x# zCsPl+zn(@yw+M&$DwfJ*-=x)p~j+dSg zWtcilXbXUO>PQ^-h6B^-?3)z?^uYeFa_?Sa(jvbCmw8P4k9y4q3n`H{quln!#?6K3 z#DiWEg!uq>-ngHU@i!j(4B&i zQ4V&oCr_3yV1inoR{rFtaD z)awiFzk9P^e8Qsgi9&SHsjTI|biDq<4#wo{SRsuJ84&MyCM2@};{0Tq5w56v_IuFt?l&9yGW~IfpQ-RhF}}g}exnrzI{xVAM}Iw%b=6IBhOGYK z@J^#c@fEWvTVX9;0`YUNPhKKjGRIWd`6k9FfirNBuuzrq`=sVLx{w!sLKR9E7SbZK z_?)Erl@a*m7A@D>Y%Av)LVP%a&I-)lnf7PgSqv)#QZEOIKp*)#oP$oD?px@xA7IP-`}OH$CIiNizJJYcAjAOE?oePb*~Q83=C zrrZ>5hSkBlN7*>lZ2QgfTafI90S%G&Xn+YIm8J1;HBfS z$N1r-#YSn_im=1NsgwP}QCI4TLG(U>BPyhYcKQVEsf~6-ts0em459Rm=d`t_b$wAY zK*!0i>H;$tq?4f)VnycjCc=`7h&4nnhC_Vc^^m5j;?8kMYOEM6)&jJbFq<&5%H|s< z9k-*&3Eo13N+TQxMan)71vkflo-lf?v;h?Sm{!zs%QD z?bq_$AlS%q$w~vwZG0Xlxg0TsxJK3EfV#vcv}-{v+zLx&OPxG^U79*{rLkW;**^Q1 zsZy6hXPMC1R3KtS*0>lw;evTaoM|7A=s=)akro7BG|Lul!q-q*WUK;?UyoFqA1gT+ zMU4jeht$wlRW_2pL+aXP#0#2Mtj=4WP4a8AYv6&u!-C!}Q2*zaGYtVP^pInBNlTj6 zq>D3o#mR8zoa^LJ4F^n|pn^uzJ?>C7xRxF0q%baoe^{sY?YD_Kh@o&CX;8XB2H0nJ~ROKJp zfsc{bj;(no(tkST&WZ>Q$guQ`Akz)oGBxa)Ttc7n?89W(v76FGb%dx7q{!WvEAEwA za}TPq?musfa>SCDpmSuNM>MX2Qe)nrT-rt<9pjjV;A(ynv|OYa!!R zW3_YmTHd-Fq#Tr3^QWdiajKcBy(}kCp|p@b>&Rr*XMupB^_By1Z*sH#DO$d-ik|`4 zBzH*!LsnTE4P!Tl;86qGF5;stDQCg%Y8{~Jhn6F9!N-k?sj)6m9C_-z!V-km*J;T; zCEHIF+sA+oIx$2qcibV<^sP&6(hQHwz;Jn<6lMzf*NI=KD?E0Vp)M4G&4e}-B2?Fb0YmTJ^#8be54R-y z`0u-IOHC~`7v*f2W+rYZEw_24m71$^<-mnokxFx9?mfv|xpR^OtsH2Iq$nh)P@zl;Ou)rTcdKS z{H+%*IZXt9*q?Mp#3AK$fQkPZRm&~hwu{_{Z~Su==X{~8H22Y&73P|8eE__@wiG_^ zO?GLVS3SK`puFt)Qw8X-at37yKRpw$8<U;Bmu%_!(niojW;mSsPBOM_fjmMHeTjP(h((?g>5LLQlBL=xLc_*0@e+i$4g| z6lGXHueJ^Qn8@AB9WtP|lgZz%SdaN5P}WDPZk#y~G;1&u^}R6r#XSBnDh&K9bL@df zZVjJ;CjM#Z%#Dzx7yjizlOA#sM+cQzxc8(6(vXQ%8#;KV)OURon`?nJ{a)D4EQJG24{Ribee@lP#s$Y9%790>;DX?v-OT#lm!7AE8Z>MiiAe zwLHMAPMhZs3tHUvYg1WIG)EW)Q$;!v$uQXZ=48xo?)B-!nE)TT0=~$76gk9Xd*$oo za9e$DKzz{JuJuSw8p@^}y3h1HOd)m9hU{SUL)&!g+E_wV z!t!T2^ME_!!ZrI_b73vJ%nLA2Gim`~5~fMQAeZow|wB?1Syk zmp7p2)Lju~3|i_eSnIHgEZ$J#GaO=AU*##BClpD8y~KKoUK zSr%+qb`i6`lbLebB}Q^+;bI!@nz%H>kb)#B)eDo?j*kVbl*n0ygDM6}W}CMGm$+VD78}?sQWTeCMnQN}bJG^~UWB&j~YoJSC+soMzWJia) zDP%*}Qe=+a7bv(oR!qy5WWAiKjjun6xa*Ufz=;Mfs}pr>s5pftzDQ}Dqmw-bTCc)k zEL^!toYhvo@OWT0n>XnzIW9QsT0Hevg5|{)jvYWB-Ctb_>y~)#?)fOahN!T%uZ_SE zeAAmt;fDnq;ad98s<=U)L~7`Bo`Tt2T`m`vSA#dkTe`o zx$VeO=Z|>f_y`+Cu>>`VppOS4ePU<6X=La1>BL`1K$i%gO}3qUkO)3LqanQoTG~LE zPso;1;ERo3gV1&B)M|atLK{vs07LAE?1bd^uC-+1_Lc1B zXGjV+oj@CQ5|r-FI>NET*yx3x>fj3!KC6k?Q5$t5OJJ$Q?H+87->B||8CL`)VpVSM zQ5X4$GQ6$1Z7<||H`B(tuzeT zA7i^3`WsdlM6%(zv%+u4*_W(Tt z!38{{a7o_r)VkL?m=Le8JRK;gd^z{D*ZR1zL(M!o2)=Vyb)`ZAJj{r@7xKpc#O3R?$s8Xw}gY` znI)Q_i?*&%QQq&y=P4H%??P+x%-8?;LJ2!9RbX`~K{dRmOoRcaFAZIo|r(PJUd zQ&r8zTpzyaAd#!WtK_g5RB6Zd5QjPZ4%zMheatxk;8up2+Y0^X<}PeG0sg{x_hUjx zgz3x$RZ6nD;rA|g9U$Lg*51PahDSzNQRI*Eq@^t5WKll|U%}eiu{9yLRwu2dZ56>Q zLt~M=e_5c@FUO1=?0_ol-5kAa9w1)t$C+rBck^iV(1h($VB9n8yl0NXZfFB!KdNCR zQM(*^veYxmRvN8II@0TEd>RAx#A zBqG>-B-&3I<#*MzMdv}fFFAdLJx=m$s5~3~@%WDvZ}wx{)7W%+G^C~@<3KD7KW{Fv zfVF(_lv$XNkb3=UNKNxK-GZpBWkW=o(;Txc3!bki_DEXeyiL;=?z+(U)89CEM8BlE z;w12!mJ)@6xx=XfiKy;Z`H{n~l;qD6_?->WgA0&a(+lmGFfobK>qBHO7X_u@%mq=#kH~!aI(y0f z9J6wo8H28HM{_5svNTG?p-}$%J5h&#L=MM%H563-+8VAw=5x-9MfCNFs~lDB#`<*gY9N%}74cRJM8$jkgvy`_Fzs-o1T z^J%qC&%<|>S?)rAoj>aSmGH?m!*qHCx6h~}QuME@MAZ*YWS>guund_z3aGbQK^1borJ-omv$zdVFkLa~+D^5e5TV|a)A3*t&` z))D$7Jbgg-mMhs10*V^e(f;Tb?U32n zIB?k+33rylvQzZ6(=Wf`|5bO~tKPPM{_wwIwM*UV8Hf2d>_RZ}8#LFI-qrPA? zWukz8hO_@_0EhytptTkxEqx@$!JLGs}T zRZ{u3+%-%Tg=w0VJSf%VA;G-!^{x_4q#CTy8cNq_b)t}*)K^+dYv%c869~g2NDHs%+7(_nf&$eE&-KoMOKwTnjhWf&!8aPusLi=f}0l#yZ#9n4>Bq{&H zW;e+G-qJZIE%WuQmU5d{4)W^pJH|==EE6j< zo$}hJR5bX{;HLB=qTrb@2Eeb+`{UfxbjQq3p32&it4uswubH5gDXp3$o5*a1K)po@ z@wcp>x9;5;Tk{`U1A)t;d&C$hKT;_kuoWdpyb|@CLc|VKf`Fx}$(q&*%Za{8Q2 z@Y^x0quzrDE_S^YER3Ugwq+Cn+<{~^T`2_>=B>}UXRwnL_t1TimE$WJiJtg=bUck+ z#`=W~gUZDP`y=X%fhk2_-#xngWb?jXXpc~$u7A)G{WYF7?zgjm#*-E&XT`ueElP7lBO3p-Ts(u!manZUEmYxi4z9rv5RJxr78?1n<**0m+W0V zqbz9OY4^5nytUmn>mw#77^GI@TGnA!je>uIFD!~Z_DGMf;1aR#5L6R0d88kjkV#!T znR0hN9+pl8a;L7{YE&p25Q$m2?}%!LGDZ$b7k;ZnGOsKEjw7Yg){h&W@sdi!lpHL* z!w!4bj`OPLnNGVHS5n(Vs=+xq{)#nHsz({3-D){k>AKJ#7uEOq)lF(P8|O zYPtpC4?6ZzqqmN|^#D!;K9%^b87RDwO~a+cN0~@~kl%k5smT8cE>h$BTUkFcf6IOO z6*MljCTUJ1k|ej%aX#=t^D&3!Uw2}v)t(}F{~DAlJ|4V|A5CZcO=1{yZIj1O!H8m1 znYvKP@9YHbug2=;RQo#A>Zx;A*EY&{HoV13P6QgK>j(F~77mZ`Oh=u& zY+FZdv5%KEzqa?Woj3@QYBhL`-TM-jzuc-Ex!=B;vOUx@(!|>!L?h!2 zv?|Lso4euW*ecINJ|rxEG#bJ_SCGh~-$~bQN2$Krx30@U_%*seG;~KChs{q0z&#}* zU-dyJB|c*}YaK!!Ri~ab@JpMFVI$uy_cUXag;ICQ;Nu}T-Q90B#_b1?Cf4jcTj!lIrsej77ove| zeKpU=z#&cPCgI|{S(z$uUviF z6FYTS{Pw5=a0ASbwkIw)HFQIJ85&=pdRn-&+*;x(l}%$;VDb5 ztda;cJkd^bCe4Vb*M$Q9VTJ;38`6)Ng!zC>U{Rohb(@giixW{AB-v7XM=M#Y@~UbF zFljoZFf-ag_+Lz} zOa3F9fpVU7DW4~lZmTQX;x7%7`oxl4ooKV=wE>XZ5V_%iQ(=I1BPF~0 zp8z#Ds4(4feR5Q$ewmF^$+?3KPR6b|-$Lo(J?&`$$_0PM4<6pLlljfzaD9OAD zxbf)RS#oP0B1}L@VG|yAPuH$}vTdX!@nJ|AX8ZVdP8xG;cIyUH@ZPVj)}`AyCB}3I z3oeK~Cse#O3D2h8)n~4WmQ66VgQNXOPoTMP+uZ?v12a(;gtotD?^tB`GIUVx0Rojs>I*icu12BBHpPTFpT_BDg$d>bADX1FEeyv)B^bABED z9h*d;wR9S`Ru*4-CA6N{81#F=2fvzz{L*-I(>8TSTvXNcTj{XCb)P)gX!|C-174R! zkfvN*{XOR4YnHK{W4V&uP5yeN>Lt>pP|i4j+cFfNy(%bQYD#Iqji;OH%b42Wbe5r| zWRo)vVdTyH`x+(;k*NTsgq6|M*|Y2Hm#^Ns3=DU&Djt~?YjZ=U%ZY^He;uZ_b7#|9 z8_E)}Fc%ibdR8bV)wgak8$M2MUE9&jp)Q1YGS+4Zne_Z)>X|sH^#_g1J#LhPO?3qJ zddJ~?G0^>VtSHgJ);hGTk#P9H{+M}xwnUdiwvH7lcm^Wyh+J46xYXXbag0I!xNdFL@;VkP$T{+ zB}Z)v>Uq?h3P$#ubu4@DrtxfSU7ooPBL#D zGuNH_p7h`2dNRj?xgX)b!EBMP2)wvZAL22>qG6>N??*-rw&0z$1iOne}CJ zUb4b5ObG12gBhGz@vpV%h|P!e)`=YV|EFT2;^jc_On?HWLS3v3Jh_g8z1I(ICoJ@Y zCq0>*_c8Fl{urzRwayNR)D7)KL|v(WjJBkFnmx{F2^{m~=J*{SQ@flzben6^_S{l`W zMK_1MzHM36_#>)a^o&~?u8B7rh*zex%)flyqvx{^E`|Er=GaTNT`$+*Z9>gT)KV?*Ro(u$z=x7L*h1`Y2|~_&i4c<57zgB*EH@t z?fXZJ8=)*M4P|N|njvAf(uZbt>4@!=0*8%erQXJN|JE|BK4<=_2Zb~*G_8T9d^BUt zs#c*WA=JUklj@xPL5c{!>kfCB(yjV-T37Z3^re z+%_Or`}|FVA&OCIy10!7*cDP&4s+vSEb;Ys=Ie}Q z3~L92G9Q1Sp9^UqQqKOlW#haL`&HNN&N9Av7KE^T(yk#u1eUmaB16t;JHPDp6tOMZ zOJ3MsP1$;1@EAf|d-!OH$qNTLYsbpDSFD|P%l>_xmF<=VzT zl(Yp-Qd|T+qsaFsze6HsP;&RTBrn*oIiGJ!=q-S;+J!Cfj1eS1@~vatzU%aoudp6H zGQ+3_vBDyz5da@Ewq7YCG?4iQ4-4`-QBZcIigh)GYD9u(_Qb0bcc)zJMvazJng zK|87lKG-A%MQ~BC=9988OzL+p-3@zuRaaAXV*jzYAByv2!rNhK4T!o-a31Nc)Qsun zybPjh4^!8;CSJD?d&v-}|03o7BC4k~{;ugntF!^suJuu%#=cm|x}(y0-Fg}GsQ~$! zmP7QvKgE5a3IFproB!8$bMx8wF#tS}+Sx(xfG?8;xuW3IjcyFUSG_DMl)>B(m#J^D z5r2Jegvzu4z!vVGmA86=R}x}{?uvhGnmFxMv74#+A>X6{uV*lsAUGmrq4Kz}uMU`wJ21*k@SFBNV6=e`#27`M3#9~czKQU} zg%v*Lmk8Chq~g5?>ZU5&utbP6A#OK9!FwrCYGvq|IQ5e4p}DBxX=oMNyj*_up)nNP z_}>1x{qK|^AwsCg!3zb8W%ku*hCPHJl2V(<7 zOmTseYM~3#p0(`{%}T;)cL3yv*|#m#hU<^x!;H$=RE^=mS>@1o6VGAWB@->HH8&0X z^2{#!=e^ijiVMFsX$`#iHn%Qn_p$p|Ymp)km*DNYD;;KZBiuF*A z0MB2G0U+#Nj-)wvpD8p7jyf|F^f!p&EX=IQxqGEz_Ol0KtM6FBTfH6g_5ed-+Q80=z9`Dd6&|!C5!Ew(wVSfAF-pee3RJf7cx5Rx9U< z%L(QAH_Y(a`GDz?VsZj{+(a{AKP(;_y!r`{kmOgF?;ReJlOeh_D04s{8)uKc#ReeV zDoJ7d?X3PN@V7uD^DjH^6ZZPwDO+WfC8gKEH{6~X5KsUT)6BoVcPR~!% zdPQGce`|Y8H^H7WhT!*Yb>pGna@uhtFU6x(YE0OQRr2vMG4zPTmaTBgT)CORd9MLC z`B5<3edKc!%D!=7Q_6pXZPLA?Z&}~p)F|CdD4my~JHto#^&FaPwh)e*c7_M*CT?}^ z9KghU(ZvNr|KB}iLwEka>vxDf?X4}`vgikjI|^l3wfQyfd=p#Xc@%frN+7)g8hS&t zW~`<_+Pr^ZDvkK9A4RK(WJ47_;5G6oL}=qEwhCoik1A?vnP#Nu;cel`v+27tN&CeL z^|C9NzEOABcI&EP8Qde?^^=U2=AUj-+(f7lqPy+P!p6hQaRh2zcK*bSY;gy=^;kZW zb-?#;TscZWK^7l-n{3_mOwC`|;qhieVt*GhtK;wBjH#t<;2h_rmh0N}_g@PWF5KFC z6064EImxfo!}lfKaPAkNYPJtWJb_KkU(`7-Kd6Kn(4^GvFGwVduzqt{j+jK<`g62w z5G2XVip!LSDSm`(?g|&O*m35qsh!`#3=~8zUd9KmoMdka;b>XK)$%u6il^Pb6Mn^9 zwKo_tZs!*DG>9Z)c$LDJNp%xOW$!uG|aa&!Jd9{!K@D_oY^8RIZk}R zaONqw%jG0p8O2^_knUt9yA%JUm-?GL@S7}YGNcUwBvr(JUaj!a5Gc=KYGr_+8izv} zXp5~g2!();+2fmP-~e|+Ww$^Y%GoIHtK3*CXIoI{>xDq-<@N^f^2R4>H#N_JYf`73 zI1k!2YmIbWziR{xS$~v`Is+jfx|R$4MQb4wiB>{LkKobTZDxmu&`^My2d?>tx(70r z{vN?{=7QhenUaUI6FUhdlT{Yp9Ts~(FWuyQc8u-EvSJVH^l-a9WzZhLpG32(^WP>f zHesw-VM36TrXNYoRg1%idb%IgIvW>sjhhEwSanV{)YBYf&Zmz)R4#nIRb?FQ7ph}G z!#F-_w~vyu-5Kf$R?TBtwEC9Z8qM^m%U+GP#t#2XHYy`)kANxA(y$O}U(R4%@Jwzw ziljyempCW>r#`$%VeZ=q&^&J(f%}YvB%f4)ggk?XTG7rl`5I+ELXq-6Gg_>b+4Fot zMQV>I=&D+MDlwOo*fcp{>I)oIpse4bKdlq0Q`2ec9NK9uT|^^G-cUkLe4_TELSmQZ z>_g#0Av`-S&;4s`nCYR@?M{0zOnq_Ku^U#c%5oElzJxeK`bp21E`8#EO^5faebnqM zZ1U^c@FlCi)d^(70NY_JDuTt zQ*gJHKR$>lSR5)ooS;0FdVSt^{{orQ3#?+z6b^Ya;|J0`FQ=}!^CNq{Cvs*ey9qh< zRng7kPLQ-(i6r(#WAqO1ZQC~b>)^-6_hX}_;u+5dZY4rpAFo>o4#-Wa5f5U0ldfpF z>EAL>yHy;LXZV)18mY^UL_|X%!ninuc#l2H)4@PU+GT7{knTymaOQQnRW-{nn5pf| zwj&6w6z}XrUjwWH^9s0vNt^o~Ia*};^xU~59zQ3x|py-mPXI3VM+DCm%9g(JByQIK z;zTchyeNOvg@gi14^tTIto_d9r+<=F9)>X@H2S*_ms#7)+n*b?X_tM10nWlkKs3`q zkTiMepNkFVoaC*&TExH0^1wZ4sexsWs5i}R$WSbuzBf)!p9UM`Sfx|>LNObPEl zu=}%>f4?%E9FqD~7S;I^E{*r&yk8iogz{g^`qJ(r>Ajkl?dOx)wp1}?y+=x<8bU_$ z7ll~W+kNYDvZaiT0AxReoMA_&2>F2P?w#S z%awYI4Ox5+RAfifn@nu?H%Ac@EF>t*pIX{J^5GKwe|yw1KbrotEL{G1A*=&@p3KeK zqgvj0LYV9Jk2A+@-#h=afdFt>^Ng8i4n1LHgORZ>?Vvfw2J@Wdha*`W3f6U{lC4YgO$tw065gr|*0)=cR}Vc#fsH}X#vRL8-*3@s z9gq_aXTC+YWfw{OFgeKJ-?^-2oA89tB;@kcDmCF;b7xEuhJ=;+DOjVGO}~A&BqF#B z7{n9Gb&wL6@)_B3tom#kq1ZZd0x#DWpqNpOAUWhl_5`leV-l9 zKex069B>|S%b!gyM4ILKi!-#rVO+C1?fW&Y3R=gGE;T$9bZm zg+VoTQN^6QqjjNi22-42N_G!^l$tqDgN83&hm`jtbxyp`9vh-P(o=rR_IK6( ztf*asMYjJo>2n^r?wn_YuV~ZVN`TS#au-71d_+6P>k)_>e+0inhy2?Q-{3zula%b5 zIn_{c+`*a-JozxOF^q#|r&Ygbuz?F)$ALOb{Ci$B+~dUAlX)7?+9`_)QloyILpG;T z=xSlsKi`ahQF#r{y)v%prj&^Wn8ZO%nu~R+lOwaZ2r=|%9DCAE) zM1(()dn@2%_}H@h{Xfn>nwk>JX9(B89-hih$_U5@wYNlZxXVivY3>2jzO*q<`+Aky zX?N-G=r0>U3zBinM$!tXFKf)=a9kS~p+MA(xIV^pEM!!nJu&-%7~XKh@BDuYI~;d%Kd9(0Of+S4?%h#;(A(BCX+jI@2H!l;=grF5dxrg zb7zhJfrOqBm92nG`ew;SZ%t?B*;@#AuiLMv!q!XXyq-tG z%6yaHrF`)^ORj$`rKU4~$9H*%_j|jqHFrMfh#!)uFgy`9oUyMj39~JnkSMsHUdjv> zpS<6$I}La3KfdDTpy2M-RfBx{4sl;;xUJ!B94l8M6gw0o_ZU;O$eZfmre?6tXJoO= z?g?9Gb-TCRe|N?g7UcwZVSWZGe=N6#2SVVKD(2)ByKWoa-dbxT8tZW*S7OQUz&Bqo zpIa@zwn~-gggo3#sn|eH2G%h1_8wRNTS4(5>ihpSrgQxGKhaUA3Hhu!YJ?$NJAS#i zVjOmF`BR9}z|(d~w)N{VE*H|J(Cy4gu+k-~v_B#1lQb>y6-pzhhr!h-F0YA^=VazP zJlj+ruDBO$=Qo@&a+ALD8nThiGQ~h6%{j(#Wo(z3t!k;3?l0e}qgeZ&Dk>+{>7%v5 zYE))lm`jy+9`~byYRIJZ>na~n8Dv>JQKivVC6ryQKzEHMxMmVUO}_)E{S^Q>DSOUv zCB))+IIP>p%jUakGCby^xo{5nxX5Z8b{zSnG>5?g)|94RO1;N$VzLb(F2)VNH&B+v#u5Ax1TEW;5xghZ&5V?wvKK7zgv*R{hzE zccwN__OiJORTNA5EpYv>;oR|E!Na(gX@!a4oQL57q|(~l`{ZmT0#L-NHI(w2DgSjC zuKLT)n2GLeG(64@-&la|>nq_)xeYe9dD%Y_=9#9ik|Ewn0Ee?uuPopj&E8-VVeQOH~ zZgFP+F!{I&`>^B9t5A$rl|Z%H-dJbwCD+pV6xvIx?9~XzjV!<5uz`n>ohI@(`Ia$= zJ~J?ivCbVg9QmE}>ptF{F|KpO$j&%aUXMIY$%e61*?C~XO8c!fB0%jnmyL#%)*I|w>IhJ1fQS0OQu98O z_MV`;3R1q9IHgWiS^%Ky+tcGmilGb^(|Sftv9yAPT6!qqVfLonZWDMZT!xo{a4Uv zqDSUJglx2TZ>Hr_t~Vz37n|qCcs`||NBmpOMwkyJNA=g8koBw#bY(}DC9X{=d2VPe z_4_kZu`WM-{-Q7gOqeDWHIeuE0C~AA{=g~77fBrQPd7Ie-RKSZq|=n)ipbb_dX>EX zfhoP7_RYyOs~|!XF2_T?^73hX4E4D%GQ>gYz-c;%N!Wj!Op^Fag~p_szsmKy(R{w+ zV&Zj7n#}UviB^rUgx_ERgTL5CYJSjnd*^3a+nt6oH6S^uABO8Pl#;v}cJw@i)Re;XP&&(Q>OJm?)H)Yw5b@9k(6aJwEP7cWfxm~?8=(7Ww~Q3=#F$idu!WRW{R z5b?#cx=3wVjB#N(CDt0(18A72zU+91oC~ZDh+pu1)D7DCQ3c})%J1ZLsg~3v2y}Q3 z@GM%k9Db;b&thSQ@#;KdvdhJ0bYHxKs!fZf_`Amx5%gd5rW!p-;ui{t$G~s?6>#@H z?DUfak${cLHpym(jghVCb{p-nxp*-LrJdkn;mjSKTb=`XyqDYoVVtlv?zNM$ooaNu z2kP3019m+^UwZ(S{WD^+be#AbfL5|mUv>yo8qg#M83kNLVUy+*T-5i2Fa7hOI?L+Y z=Bz^K&qF9r?|78oPe4M%=t8Dx>f=_0kahJc z)aImbCHF~d($s6b&Ft(R8`C^vEZ7H4y*=-I%X#+q`g!tk)cZfTf93sZysID!iYR>F zUhm%u&_7obzXnTGw??GkGF?AB@wmyt)UgisPln2OHX`q>6`!Go{%xP|5M0ixz(Vce zmp(bD4yP1y1q)_xt}C2u?fq&k$Yv?_zS~%9VtwJ*(mRUv9}rgn;k8PyZ4aTps`h!Z z#a4D5&njl91%r=g7IynGnr+Wz@JE80@=U*Z`U?w3vc43$m{7ZO79i9Mz z0O>ko+@-nsPmQB?((||%OnMh|J*_w-+tSsUcPw^c{>g&TpPq(aL4bvM{|3L-HhE-_ zOR-_oZRv)_oLv!ZtHrv})UE7lQJ2XvE)e=)b257vO<~jxzt-*FH(Dg-49LgHnole_ z=hN60JuO>=d~R?KX~U8dN6je?@LDB#Y$@P}!?)G>`?pkY6u%+_XolfKGMQmhfo=XJ z>>`SA`JntI)y>`w)pxm&QSlDccG-5 zxZCkR%j5W|e?_ZdA!Zam4Zww-;=o5>(`lIHKt$MSJ=E{w@7W2-g~e(MVnwM_5t8P- zx$wZ-mT`FWNp-V79~fz4gyVuG-R=;B6y~wS zRz(U$6Te^GkpTw)&oe9G&*b-a{t=60mBF2@D>RcS8GLtCmb^S(b-r-YMQ9{EGBcog zxC_H>jHnaN4OAHCCsE=jYVF>i@XYqur$4O8$x0uHJOi-MeT1I} z8b(|@{WlPvtK+TP?6ePlXv(BJjrf@#%O(Bca*eb%in)eZ!oW-<{kOn-g6n%P>mDER z*C%lHLi-dc|;=W|$n-?<%rG8rU4LQWZuGz_)T^OM_FRHG*MXXB+ zD+M~Zm(43-t@;E$&GYqq@poMZNNu&UKa6r#W8`jbhtz^!&-y4Erswig+ok>;QXd~e z|Jm5p6~q8xItbf>f!g~1ZJp~36pFQaz|najEaZR9d86O|Ez@V;i6#EB30QVvJ3mIb z6XapD+(Chl_+Q{Rd-&=C%;Y``R!_C~< z42}f~?{9$GeSgA{An8&iQ&EWEx%P8QW*sIllwRm)S#Vl3o6X=w()%Fbd*_}c0eB-Y zX>oyc@w78`aG^rmbsJUm;8kH<;r+C~Y=@;)->dj1H4_(J{2{1NZ#<^oz>ww=s_4l9H_s3klbwu}YIzw8rF^(FVBP-F}JdvWP*e~9Gi)ZFWMxWPCb5W-5VSx$z!~bzL9Q)VYwxxOp`JF6z9-9cfz*})LQb?#9r5~Sw$%EfTi~eTi}B9t{mw3=S1_; zGqPfGn@j!P^ug5~M=cwo0P{fT!iLf00MFdq!Qw%=L!wS}w((3UFB{#HQP=03{#3D-nxJj2IeC!t2FYk z?6rdeb{08nuIq7G^;fMkgnLQfzUY65_B6&0(jJrA7C*<&_zAitHj)0Ey1Wo~y(&BD zG#M1fGYuj9nXkJ%H-z^$rez)Kh9F~o3KC+sSfGz5?(i>?Ap2K;Her?=8pW)%Tr*se zOZ&&8yYMqD_@1FYBVeGLk4U2i{_Ui+R*wGc%5!4Lp(?S3T#CIi+}Oc;rSk&o9>h!P zt0f?1Ek90SX>WuJZXwXaW@DK(B!E^@xT;a-L|4o@u*zr8v#zsRL~ziLwcdFLd9v*du($S6`=ci^3EXP++e0SILc8>IxH3u% zy^ zvd^!}V|BmUrnzii<5^Hfu=T-%o}SY?h1#Ew&!A>5u*Ts@YfmRN`(*()=VfBWmbc>G zOwj7THoI53*q>1QjJ0ne;#Hn*q*NH+RwP+B*~jf%%Q+MY^P&En|J~518*eatk(vGO zB0QjVKU=ST_FU`ha1nm1r0OTQLr*#H%EmBqJWLgHjd^u^_H{x5sLqqsj?trKaE?%E z#59X|9>UZUZH;0_lO*EX(<@FZ;lKrlpCUXMCQ zcZ`>Gv3_$GwkJLDM6&AwPYcLo*`#{L`;P-mwsQD_L{^nCR)w-ew#t;bhT_Ega<~x( zfdXj0X3dYl!U6mM(5b1m1onz8FOi~fm)&T9Cz3@_ycC{(EqCs7(ve2)>Ky6VeI{&9Y-e?SLZ6SL5UW_RiJ zJ6}fQ+N}Y3=;3v3JpUom$Wzcq6@*OsZ35*bnZfU|!aX;~_@#>^dX4}Jjze7|ouxd_ zZYakts{fOll6&NoLe}#6Zq68~J1LMGcd2mw_#Z`8x+TYOvYdX&%}x3yWbmG9o*iBF z=-SwK^*6}9h6ls!T8_{kl6Pml2KPiWYNU35vCzi9wLD7CbE+031c>+kh4*TM6RgNs z3&4B?xqoAg!}0)B>mgQ?%y3T_S`UZFakG2rFx+8F9c@ejFuOb>3a9wr9{#2+KVFEP z{LZXW`fc8JvF&hWFNA-^JZEi-eEg+HI$_FD{PYGwQ@S2b6;Mp{lC1VNiav2m7r6`$5k!J)fo9AEusg+LMB)(G8h* zen-~&tonQIi}_Ao30(fkvU2gH19$WQi0ha>BvtvmI!d)y~yOL^_1bOPt4eK7W@yn(iS z>7}`_6?C_iu6o;_j}TAT@_QI90pS4hCUslY&S0E#2G%OLszR#K1C@c+j`8f+x3x%x z+R@&+{HZ_jEHurGwCQA@GqD(YK4j+kLXr{LlI^|c-N@ZS3Co^ex4^-i(98a*<`0HL z?MC`uz$4o+y(=C}-;XW-+WY^7V%@YA`*$KomDIx9U2+cnT2Z@>4FRp+c5``x zT5}!PpxtHq!wYXuAS8P3KXaQ^<0HQLr6tFh{Kn$(2I;0k;nGWE0Syyr=jqWb^gCT6 za>-#XSDM-9NeRmRuh~+Ty=lD+A%&_UHDHaL(U4MNZ{%n@ql7ap9L*tVZmqIu)AXdbe|I6J-9sx}Sg+-%{f&@;&~hY-*z#lA72%FFuU{~6?ot<+$p~c7G@6?1SnlHjhe^A{$cwS%0-qz907|=zi{48u_>5v-NfgZ>thvR!%q_lyHy0c~tB%CRp=x9?5O7 zYcDs@Ut^1md;H;sJP)f8^tkCdqwPdvoHKg)MXPct0jv7YouC*nlxEh&uSL)cI|%!m7fmi`gI4EUYOJB8AY+~?n{25B6-vZoZFE~p5m6Q3R;HbWeFw6{ z!)~+u|L4nZ3wTYq>?$XdRfGnV;Fv@tegWX|#SeKAQ<#rOiv z^PBa_bBRiZie17rl@fAU;m=O(zpLdGU(5bSlY5(@?Xkz%mrdna@vUTS(X8n3Tq_Oyj%Vbku z81CUa$B;#Ox5f|uj)b~$gj+_Z469&(T&wz>>-5zkNhi}_4a5^GHb=F zZR#9d$&iI9q4PFk*v#+D$q)(v7Dnn>z=Gz9%bsyjje9&6lW97unMIDPho}~>V~imB;Nn<|8e!^@lf>v z`+wVA6cs9EEo;gyG}emjOQB@Xl6{b|k1>jpgzPbv?Aezw_N|m9#@GjA$vPNgFf+zF zzNhIqT_&DLdpf2cE93!mF{D7^M8=9eS1Ikq9LB_BC~&Rl}m01a!!H zi8}PU9okQ5)bNKCb-(A@b zdxO>WQK8ec;E;=z%ydr7?GSOmmFf8!1E;3=j%K>KM=g!E#T$5X?UrI5CC$|qD7Pe} zZ!w8aSf5hC?)Sf3PMDgZwznoSKttpQ>E<1lv# z*k_BH-3k_gXX{t;DS@0b!<#CF_J8E^3N_)oS4fw%0h>yI(g_}3&tUuALBy;QJ*%{8 zb`MxmrO>s2H;&-a;JJ@i87p=wrvJWy?55q^xTg#Np_S;Uxq!nrW(JK)Bl}DV_)KPx z2=}6x=fp01+~asIS#&dR!&Gfz^LvBOOL3LG2SMNy*G>ru)bLlZQ2pPrGJbqLgDVOi z)<5pN{^ho&jZkI7n4*s>_qJ^}qs7W?D`CAEBv6)}h|ye$U6>NKdHB&^v3D)0?j7$} zo_cXmaA<`&JcMx&)GrcjuI2aRd9UwurR0+Vmi@#SE7-gKIUg0}>h!LBSQpC8#WMp` z6#aB;1j(_kbnzdy;qw*ZP(?^)Cx}=8&LmDc0rC)?HqWVF{SAYE(ya$NzYt+3k_bJ9doVCB1!SZyLX4%!g3uSjqPbV;$w>3{QB|p|=3#{-v5ps^; z*P#^yPrCeGh(8m}H<$raVHxGw<9;tx64-x~l&1+tc{)xsym7CFOO8lN*xs)#*BgQ= z9U(xSX9#L|A1 zh&OyA2XRWKic#aDqzgieAY8~*Z89kITLvQLK&JzcaycO)tps7Pj6n33k}`3{`JUS_|2XK&)i!X>rt zWy`Evk-w?9?R@0PcJ^*@f4{!+qfo%7Pf(A8jL8=X4(eIA*Gyx z)U+^z2M126>`nik`#=l3$$+5qZvbj~|Cc-mbXQcFj%-M@j!S*}ymQyt z90aS;QGc4nI#(ckMpY`$Cc#$wuZR5f_fIxt{ANCfq+c#oy-B<~sz#bW=3t5WC$Q#W z`TG!FOV;gYCm8`>qZ)$ZF5qr1Hx#1dpzS=OdffX41Y zY+H-|NxeMe(bMNz!yYN!-qZ{{x7?ShvDej}xyM!jSh0=5{frWE*leF+fdMVQp4xpt zJ0;lc<`B&MAyH#d72||UBHab}d+xZTNEcY{4RhE6_$E#N*?R zDbSpXK2!cUF>&bjj2tl!Kg?BxsphF~i(j%*lWM@bnES9Mo)vi>1^Ca*U0)qadnCF7=S`hO*9+Cb0kGz z@_+fp3jF!y7<@M1sU`n!*QkN~cb3-9hS#}xg$X8m%l42oi$slyRIbMFp?03y$0)vU0BNW@7a z6Sz+5Gl4a;{)Y@l-%N3&d4iRf>D%Hfw~A=dAfrre_t@R%ob{SA4IIOc@@#t?gZ*)H zPm^)mbdmjZ#(>Y80UGlBBA4tCL_9eTs3kO+b&c3?E?s_j@lmGCw?r*fF1*uapGr#u zfdbIS>R+pU{ZXvD+Os3Ve`oi2L*|<|mHA9yBCD2my-|NcChq%Z?j8>noT(|=04ef3 zEgPVnk3L_qXM)U++kkLhZ}z`~DhmlhNZ&J>>HQok2kYu`f)zqwq&`2-aE$n@GX2Pw zp{=C={NDx536RLI-tGJAtFqSq`_|{5=6E1qwi@D6YH{eO6YZL;LYmQ2N2{^QrN8Ay z{cd=!P#6xBo-9u%eV6TP3Bo(dx!9Xk!~~%Y7$uP9fz0N*xDw_50rMrue!V_XQpdMj z8R&url$~wdaRQaS*~q6qn=oRA5HYd?sA*BvPKAfND_`nuie>`K-Z$)4ifE~)l2H%N(?XjL&kr`ujL~W>QD}P~h`luX8t`NE(mKzk7 z@he7VJZzYU;L;h(Eum2Jr zS8vDvN#lLD?((V}dko)$3yv>i`x-qFViiRt4hIb{y@4MOD^67G4}-pgz`2b z(i?1Co$29xKqBjxrN$gcA0r0#o^^o21Hn(V8S$VAPy_49{;uR*mAcCXAt~WmaF-4*6w4!%*A5cYXi1u^JTfy z!O7z%l8uksKK?OZnyKP=*xyCfhR>qlUQc2hnv);4o&>T21>J{Su$f?C5zU&kod5+*h))yJS?$v&bP62vyB zjOwvqy6!jf`=%jeqsHeHxuFcTYh-AQ2LrX+^%BpUvi)Vb6G7l0J$a$+=G7+FUMR`N z8Sme?ib_~d43#Y?B*FH=>RMaOddOER?)?Y6`X7)u>{m(jU(`g$+atSSqRO~sc$-i2 zYU{Mlc@yLpp{qp^vKfj-0$8n^Wv9!#(!_<^&_hm?(S2LXj*?YATL88%vi)Agp$NN` zYFrO#N{#ON{6l%{gNMeA(UYK>z@lo_J;?#I!bD0-x1AH+P@a~S70*zVL?C&D;Erg8W2~Y7t zb;WhA3UbZCod}XZ!cw-O!d|d92ZS!Z0F5EZ(lyWfqe#)(glICgJ;u&>G=xt`A~c9PWLr}W%M>=qd~UWeJF%+PLWsEWGowoi9Byp z{k3Rc=R$#O1Bfs22rE@p8lNfqW0?P?@Cqlul% z@oSId%OgUvD9-0i^j$81^bwOaVX|ctTWLcdjMJ7A-`@L8J&<$5t2l>oQwhG0uBS;Q zDbSbYY9P#H?P&_2cfnuToO<7eb~n<@7)BvyJaD*yIyRe0Kc|jL!w_cR)hq@$ORf?t zDdLf{=h!M}kaQ~-qihM5P5WH?fkF}c_fO|1&aQ*+x7zAM@9!mgxZj*HJ|d%C^g2Y6 z_I_y<*CBL~k}s|Yslh1M1>upA+>yJIl(9ccPq%T>W);;5Y4}2u^;}r|$w;0RO&yK? zSaRZ8I{$Q2ZHvLCj!xoly)S}q?;AELgNwOl^IIvqVzr7utzUicUC{Gdqr9Onv$O;%;b2<%I@7*A9n ze-;tsiLd%er#dARXkf`XKks34pIdw$H5uQ<-FxlJVBD&lD9;B#w&Pm_`rY?Y%| z=M<53k2sxBBLo9y`W(59$R@|*a0#AV$KQvuCJrT3>0Usr**y8**5O*S(7(c|k13IV zgZ#a%2vgOX%Hzs5PzXl!aGc43l&ELNXF#COoO{9xqR45ym6-%8n85w!zPh(LT+1;$ zILinLeOb+!)gYn9xZmf9{nj~E5y8sHB-xXVI0Gc`lTLvW)zkbbpyE_F zXQ)7MoqnD?-D%#M&{kI#jha?wt)A^_wLH#%@t&P=qKABidgC7>)fH(`FR-9k_o`)8#P2hR?gK zKAyS*mc0GA^c!y_aqn-EbqLk!Yf-y-$LdJ^2-2eYNEpuEP?3@b5oHW>+V`rVS0c09 zY9)QHz26wAI~?{qSln=zz^=;nvg-#vG;<4B<5S%a!d{bjphhy9^{K*HFqB8T8K@pt zTv)OZ4EN&uY4Fp3Sg0Bl?#NmdBX^`Y9LU#pqmwJUSoi z*BJKZ44^6&s1Hn+QfQSz&ioj#z%h^cHEF$cYas#p);-{l%eZ;kaTRCZb{a0ZdKt0w z%aI~`a~q!3gP8bvF#-R@I9i97kZZb@(H8S<6fOR}B=%FtYDnFBDqD{~(&Tio&Xg-6 z9{*JQMOjEdHTyx5YdK=hEDfuO@7{jlsr0G3p~84OSmetIO?^nK=h%$I_WlA|tD7v7 zXL5Ij{JIC3$JL+|{mlS@if{Y;Dn30Ml~?FDG@DQ8B+IjO4l7UvHz9!{IwXg+SQ?Y~ zo)<6XX~yuRzuByfj_*%h-~^CsfUdwR*kIK1x|V>lrBfQeL%+o14>N!I4*H4?tfK5K zdA4jO>jww;*VQwR0RgdU^}h?#t;s)k_mTd8>nE*2|Aw0v)po&u4Qj*3Fyv;cnL*Co z@4w)8Z{(kNc-G-0&sAxWipLzs*mtnfcUzN5@i^IP3u29xv3nL-iZv0$m?gG-A^Tzu zH_SJ)|0GU?TVB^e$UX3kC|mcMF2Khu%&ThEvi5>#>y&25`@ z($n}mA)IldA+&PL@sb^<1>IP^VPp~>b}h)WIC?D+bh zH2gjYGanBmytLAIQWSq_V`rZNp>_|Q$=?6)`OlRf(na3lMb;l5Z0EGxw_D@N0Q!zC zH4IjduG^`DhTcI1&h=8Em%mAkDjsY$KI&OxeG^?9cY-(V`s0~hfg6*l0yGDN(72bo z3y34tF4Q8~L;2wR6DqepB0Q8Zan~>9@?1via~h~i(UfA;sb21y-VH8IpDg90 z1bn7UDyy<*6Dl%f^>qqW;%U==nav+u8os3Yae@Q-Sl$VAHWCKw3beP0B0nW(1s<@h zynPa#)5n4XJzUPm?Q}n%U?8ej-Z`1c)?q7<_1ZGGe$MdYJ;Uvr zwyB{SikddU@VB=bEntiIlfC%Ci9lB$ilN`aY}^Y(Jau>rqL_o`T+4EwL)M-Ay2zdo z);M>bKANefP_g+8oVV9=AkvI~u?mT-w5p!#Mdq3@x`qU`%how0^cameq-ZokStevb z@9HMLQZk>VL8q_02-BD$1Ad8r_Eo}Yb3+HJgyEH)hUhmCP8e`bRl0B;-USFzCP8-Y z;y+>y7xzdoV4l_+i21vxwEI=^_Wv_VU9I5$8;>Yo*eM|v>|r0(@4k{L65C&%Udy_B z-}m4;V=bDH;a28jT{xeH*DFUFs3S|b$0F&L6#$xe9rZp?`(pLf#^_V{=#yfJ5Caec`#XCkC7_L-@uhBU^5-mc&4Y%2dO} zz)f@k*s{V0U7wui4P%lOJ$FW0O^<^Of8gYO(mHqU^~q#4*7i0foAW(Eh| z@Rb4c)m=nvpzOd?Qt*m}o4ieDYl`q}j3clw2AEmZ`-Dv-P6c(DhBL=)0MFhU8C~)p zu0)B9%Qxv$-nD+6n*Fi#f~2&gE8F+@5;))Iy2RvbORec_vqk-gQz%d)wd-7dhrvXLy9< z8kF~B%c9FuoyIlGzguyr1{(#Seh(|XKxG*JD%5w@t}x|nUWWHbcph4(fj2CM0#kyP zc$6$qlWX}P<#Q01NjD5tP^B8aLTYK+JP60egqWA4AJf*NQx3PPFTHN6%dRoOr-MsK z`Bfds@&>hC_!oF*k%z|=r}w-q2jn9f9oe?Oar~;a3qa7G{Xb9Wgec$%{W#{IgXn^$ zLtmuA;4pC`#l*=O?4x`Qrn6X6`=YRhMTYhQ_aD9OQ8J@A|GB>l&L2oFH(ElbwYEe6C_xMQOqZUKXt9LbSRyT72WyZ z;%R)s!7MB08U74d5F{8kD(qp;4LMU^C(_Q}0i3Id*goeQOWA3=;7az%dQlxX_sW)$ z(VFj5%G(2|!)x@I6<8+u@;IJ?efKl}3qL`5B0lTywMRNUTxe_3$Wiia+PkNG?m+n! z_~t2Y8g8hQH^VqqsS5&IsQ{0k`(MrQbmRjCf1#lkxt9lv&Jpa0p4s!UqUV$zJ<#5X z7wv^QG-&#zTpQIra*G;*JaE`2sDGIKC#@g@hyvxw+P*TqT3`oZlCRggel{PSMIHWQaTGA?-Il8pn)hTe0Cm3I<(asZnk+Z*W;d%|fp`SW~f81AJ7 zI77DvT7QZA5_7CWW>|ceuGTJVD*DetDMX}bWAE3ZN3^@A|p`TDbo6%7d|!Tz*r`HngH`Df5%cZML- z(6$%FPU6Z3Q_yg0gdi(oDaqZGwOO5VSEqVLsfc+;A5+1)gJMo%D!tlr1d#}#P+HJ` z>!Le<#pxro5a4w6|KQc;ssE9&9H)=R(sokNlUYPRw1uOHZ1vd1v&%-T{I5Xt3e-t^ z=0&y4-*=cqesj4jQOI2Tu*2^YyarMHR(uoWE7ijod#jyC%uYN}zcH^oC=SUK#dA6* z2u>=zyG*Jtcti#sUWOEV8=7iM_yqXfmsKcqi~x^|_IRiHA&V+Di=HF6gR;-b&g)Va zZsADi+LS<>7eKC@=Hg}Etq zzcwhE;caANgz20NE)FaA4rVICsX13OP~&a%Ifom=E^As0pCMezKp|}1$%|s{eQCL7 z^)&@B7DCzZ>pW=PvU4DqYVYo*K)7W4>4B!cPo5)5&O-ZH>y6x>d#B1{s6JbgPy30f zmTBpwV51aE2SoCr5_KsJKk%B<`M7Bf>KrQ2NeQAA=7XJ0LFHg{Z9V$*P&~xdSIDSA z*$|z+?sc4)sp#O%^Ar>A*Ep+T1(=`BoVZLIJvF(P@M1ozu<4SDz9L+cmCWy3Fl8Js zJfar82x28JV>m0K-QvgreM1Fa`U&XPLJ<1ZVc>0e*@S=Vb5sU#RaSv!N%1MRJ{yZP zX-ey=S#0RW7YSML7p26{oH)SeKgI5CIw)u8Bihap0_R@`VK3mYZmdBRPlMckxjm8x z`_Xp!uyme|zq8jjTv?^?_M zmy`8AzwqDf{%&-vO8vg=_5C)Fxm{0rzr!ZSSJJ=xs)Jfl`%Nfn4rDC;i%FN$q4O%u z_Rz9~`=1<3_-9vhKjf9389%f;vsbxie{KKwk|!KhCbLr|vCPt`k>D6Fjkc;~)a6m0 z<>eELsQ7*!U_f9~{-$3A7|ro=JprD+)8^TDBUg9`rKG~@Z+OBjeoNf#l3A(bIR%0< zFZSJm$OPAi#GSP%C)g$9>QuKYP|lYx-I`V1A)MB59#g`I{8-us3L1l*J#CY9!nJv-1nWVj4QkJ!O)h0CbxE1F!8t)&PW++FMJAp6KpjdaINo+&Pldw0fq ztth%R>2mJh%MNrM4iqTju8|p%?PP0@&Gj@P2bL9mPSJ2j0nD>8(TvkX#r@HjWV~eUyKGRt zV=O1gOO#1J-mOt96Om!mK+;StU>1&_0_vvkgYbI0?*}Zdb6m()eVke6=vVsr2cV=m zMeP0tz7qOLHx#;_n96)K)2V<@)^e+fbxjl3m8ei-n3VbC%E^F6IT7LxGzDe(Rjc1LmyxYzO8>BtX$p8r7 zKBsyLwn~mCWA@h@40|+dk~Ze{n+M5p?upbOb=lI~X9T^;XI%$iJSYB{w}zjGSv8(>(D$shbK&2ViAJwc%ya^Ib*4lo^zX5ZypxE(jm z^ofl$wwY9cA3DpNY^r*)wO?1I#sWEDgBzyp^B#_5wd@}KPmqS?tY~-p@mF?JT7T)U zX#SEK16*-@^C(31u)Xy7srHWLc4yQR9)499<=;`}48qd2NzN`5;PXGc*`rQQ<1=6j z!lay1VTM)KLKt?+dnS{@)j1td$}DeQantmRn*_vJa5|!4r91nC7cE+Zp(=A5p`|X+ zqygh@-1XT5g-JQuL*m2M#I%qebK&4q*{Vz;8445vh)dg-uRzl%NKvq4!jMOi?az7z zdv=e5FWB;nuFxp3o#VD{WET~zVwphiToufj5siDj#!sNMtM9SiE-D*5;t3%CfU(S= z(5GVukDon?OuU<~tE|b+@S@zayISuBCjYI&1c-Ge%GrkXsSQ7U)I$*>5n#3{hx(F4 zT56vfhgcom{-g!4WL_Aj{sC1VT1scI>nXSS+NQCGwzLYy|59AeR=?uY^u3XrFM({& z?#V3-ZXCBZKM~Py%E)o+Vt~2?+c4M3@)HgH3W+Cpefi9}w8 z)UPWf^G|f-Es@VI?Z)) zYN21V5B+*RK1h2*y!HFVL!)Z5S=HUyDWMla#VsF#Jk#^FAcw@qUQlcp>*41xjBCV^ z?d%N&`N`SdD?cG$X{E17rBGaJ;O;|)xw^lVNW)~xziZd472PZT*Zs z(wj$HYXJ}r-|~`vn6jd|npIn_uIq;s*KTYp0kG2MPc9Z4;yjE!r-q|;(!iMGuAktI zT#2S@`yjx5C&8^)H$#IRJkx2gCif1T7SC<;c$bkI%t^AU6Pg>ezhq(>9wBw-Fne(J zCj$jxh?Zj?=2&qox~O1OPbR038iL`*Tot{D8=D4ktJ84lu?K((!WpL$c{km%xA{4) z`K+>Pv&dWa)E3H-j>-vL2U!^4rARC67_7LYU`n>6S~vUlxn{Ic%h-1&R70d!X~koY zu?ma2uUdkZ9E)NauxJ0gK+73*VO_tfU0hVeKJ>(8aMLvF0I;+?aT$pLBXK|JCdYt4 zb3gl01yeKGPyXB$l+%_f9q6E`aykV&q0 zG*E{;`N?-|%g6S>uGuO3uVJ1emm|1(kzB5JNKwLq!eZ%gpV0omb51sb39dAu>&9_x zmf5v!1)g$Lf2vBe!hEGov0?vCgJZpld^5*Nrpiv#cg%Ie^5+NyxT7vUm~M&qEjsby z{<&Qs;fNiAb4$|n%6qnvDprtQ@TIPL9v@uL>KdX>J83pbN46^#yVvxIPK1d^Pea+~ zNqKcrSltv7So8t!^pg^-S8Zm^G!A#1xW{~*;)iK)H0`>A3-StFNTB&$0?- zSlEpxINofC)y%${JM=x>?IzR9;0`vv9oP?3nx1@5w=OtcZq=W6f8d_yW7Zq1(}u?- zq6ynNrNDxE?4CS-k%u2&Nr%%lw<6Cn7r32mfUxds6-wL*yuGurU6X3?>ur1aRZmAY zJ1+3brAk=EH2*JrxAz8)x3w~=ZlB@`GUJAk*$<|gbDvkw!^aw4iSMScPTe0kj8$)9u)OG zJD0GNw%?GKK)TRWxcBzG@P($zlYhRXD6}}lx+SFe1XVL-m`)MuYny7fU{7Gzbq%^- zDEI9xq9pXy+SIe=#hGj3}4=nIL$Ajc12cEw|^}cPb&m?^TpBu@aB&KyT5cRywZ- z-ZEkL-aE2giM?jv5ZI;)%v-n_!|JU&DNROB*`MBo+;Ley;}>?`{eswOt`iI zrVT$-rIg9)m%?LemP>iT=A11qZ>bUD{d+|rfx|pGmi09Nsw??-3(lQbuNng^Lgik- z8TdtF?5FeYZKxTN zYi<~~%TsQ8OqQ9AH&OqXoy~(bHS~#l*U0L#8-F9P^P46vcAjMaKud7l&)s2*8_LR!CO(j$y_1-_$gL#g z5n;2ZtQ7rjxXjH2HmqT{9*~j3Mxfc+DHcGp;ztL0v(&j_dNh;gOtuCX4-T2;A^8Ab zCStv$t8P8HRc zCuOMCKmpl61pYD1wk2qzq0RcjdX{{l5-nI|clsQ$i_n~*{aT+HL+U!bxN0T5CLA_f zS2GnZ|Gce6-|}FhCGcp0$aypyLPp?b_jfx=;P;X&tLCXc{_QwydWTH>2gK0q_^YTn z1U6I0c7N%@bDMqcyG@RBGF<1r`ye>l1m_XoFD!E`W~)P*(6}EjBhRF?Iy(glj_x7H zo@l}=Y5`wOr@~M%q%;t=CNJ)&b%af65t28R0j#=fnOs;7eB)ZEMoO5Hd@rLz@9aT3Cw0_)frbdUd?rY{ zPPpl3Vbhq2jrs9WRZh6aX^F`*n+)rM`!`EqNi~iZh+Y>9Mx9Uy4ixur1}ND>ICLhp=ysqsa zglU+@!VgHSS(;Yv_*!$g;M$E+Hj&Xm>k?AT6y1qHBby)w#9$^Psl>@wS zT&1io11p2wpULkIpitLhp?|gnq*Y??X;Ny(3=QLE=t`AYdYO0?yuFhhSC=k{Ij$a) zJ1`NlEfYPAz}zptm(0re4Ugt;8J*n)%_e?bct~_rDHjk7BQ8O@5chr~WT+6L;(Icr zpZ289{xDVBGO3AK$9L6jvs}1YHGsssYguAw-Ks$d*`oeI8&9eyczVCINeVtU0!Nh~ zn63v1-yMBG3%0ZA+Iu}_HnXd-J1yVVa1{GLhTYbn0NIe~|1R-!U4PH#D1Q--6;&M( zjz_eJ*5iXa5O$+33rO)%=qDCKWA8NF7Xhd0R-Bw!94%^TX()V76y-SKLyEUvbO3yC+sGpk*A{2=M@t$|g# zhGH+^0^_es(zBgCfQd(apqSoJo1Kim4Y?Wa_^3G6fmS5O|La^cJAm&qj9ZPK7~ZZU%Rdb7-BLK89s6_@=f=4YTfTI_jgxynxm?A4d{HNS<0X|>2@iu9P@px4T!33lgC*F4SD&NQ*}P1fMz)-ProsvqBw z=+Ylz8Of<%|EitjeKpUZXdUls+FTtvu+8_tL*jQtr=l8ftWWO zMQH?gAw1U^>EI{at{1!o?b5pP{9HE~upm2&BNH=;-?IlEfsknQnYw5{Q>d&r$EKEt z#M%_H&^QI@df(C#%qN~ z9WN7ZQ#^2=imEzKq$GF~n; zJ}^jAw8S#Pyq;IV zX{|XPcB~@KvJ;V_vCTIbbiY>omYHj8*KdJZjelIPu=U#7jzuMJ|6w6In`Tuq1e48< z=3lnG@MASYdA<9JW3Kq8%EM8->S7MAuhWNQpSL4Yd}uj+D^Cj&BOU944TEL?A|U%V zptn4KE5xJe*6)l~fp394OJSB!qSkMD{rk}n`49t#qrP{69}ReWTnUCpEEyqRC~lMB zPcI5D^hMp|-9H-7;%{dmdgy1SwM^gZqYoJz*Ee4h%XAMgxr#N`^#r}V4^>!G!pyPQemaB+p_)DrOSYW@QZe}TPEU3^$2 z^H7<_r{z4}X-Ld10z1*`UdWeEZ?gC|dDUBg2M&@JIuW;0{sED|?RTPkpmJ#N>qRjE#sl0eI)nv{jZ!S#xEh&9Wh|%C&#+9)FEo#EW5-V z9&AG0t=yWYUy~;y7@<2YiSd~*Z|W`ksh2wx3HN^FZ=<%VSmD0m;VhT+!s8zc&Bz`3qMg01&h>dP5@85QMHt2j3c*x&8&;;X zcA-8;k?__V0hh*=kCdi@(_XxtOZ>=@w`aM(b8zOG1u8^Y?!jik2P4p_Lky?TP0WSH zfz=7gUiJ+9KGx?>y}*x>^Or|>2GLZ^)h@)}rkMwv=-(X4_8q8C%QmM*{|wN+i0Vy! zFl%|yui1dO$te8|-Z}w}uRut2$;lvX$DI`7cwj3ufCFPbO#k_Qfs_BnH1Kcuu3ciU z0|McEY;uVkW^ygaEI=aM?oxHGF^+NP!*GZq^jKaEq7#QG$A%E2idi@ zGAU!BhKQvf4tg_FfVjsZcor|Wi>6Ma+ET9GewEULXS{D6(Ps+VSeXj&+xVE)kNb?R zdsmlTzGxv9rl+s!BMy4rD7VXtXr`?v8kf@cm{`OFSdD#JzbQb|7OJsE%H6nN2_`;5ZO)y*k6GU+kXr>y|x4BiLwb+TaZ`2gi{U|t`v zbr>)fev<>JBBVUw`;A^^WbEDy9NiiEAueG@czcibjFr3b$%Uh3B-)|s#Z&Xo5@PN) z&A#c;KJcqg`A1&&@sGvIBjT=T!jp&Pk})5^uD~!@3|Ra!WW56Oo54Ry*Dd?Z|Hx-n zJ7kqbTg06ZhTSX%{>P^W=N`1z;oN}Pni*&B9hZyMll-;zle85z2KFsDU+#fgu$Hv# ztY6qWuQ--neV~H=9O@uH`J#)?r?b zUEnw3Y2bTWEqXnK;Z)|+wA_QY@zp4&O6yBJW_`rEiIL|)1yCYHpoLc6=|HvI5eX@r zBd_n_SBL%iHVEKr>P?U2gCz$s-;U@jep$GkXo)tO<}qEBT9KmJZ1;=sA2-$(@FkU2 z{;mI>`d3embV&p1+?^t+C2yqRG*#0RCmm^=??N~w8~X71LM7hTPLV zY$xI9WoV^SRwrn}@IXyPu`9=ZrO-ifvO$7|_gOAx3rQ0+;tYAUN^2@I(3eN&-RH$N zE*C?}GklAfy8}5nm)D!m*H=9LJ#>nVVESVqs^6-Z?Fc`KDpNO429V;$94YMCzf=Ol zS1pfet;3U?Bz;%_!=E7Ln(lyRZQ{7YdqV4Mp-=LWiUX|!{i^ZOHtkOUQBx>8>qh@3@J)c%ty?^U!;V_fDyLrOQMzQ_(IC~@J~2Ge6u2-rHOoa6h$YHVRu^DDLE29%Xv zV8|3NaP<4BH9WhnfXK(#8Y%1Y2rh|4-xuoBE)}CYu$J+_Bnh-apH*R)UbiM(zOZIR zsu-p>H>35NW*oFrpq##3)61}VQ)2XfzsvNkSdKM&F<*)*OxxNI4LLEZtDkR`AoiU< zocf|jWsjA67-}uv8`uA>*Gh*umaawYhYcognDzMQ`8sXG4$`gQaK^ZF)R_evc!(pUo+%yt#6;}6YvuW@273o>+*93?In_mx zA-tR(=)y-1w?JL$lsVJZGGIo>H=}BsK2Oh(tNf-o**xI)dDj#>O-|cfIJDg9CKw?? zQeI-Ah2L7jHeV~7-Z6z%6z%1$P69{BvW&RK$S|sRtAvWjnRD`fP)cREv^zsJnN0M7{bgWk~@ zGb?jJwY5yV{1$L)#yhH4o34FAS;_1Tj@2Z`t%;TZ!W(gKC00LruYL3tjH@$={5T=v zMMueKgrm19rdP{|qWyg7e!N$yr#|@n5B{8wnUTrBc zh0Gdw1=(;oE>6sp6Fv{D#viDPUOp)?vcQ~ltU)jrM4Ewu*R^F5^+h!(_fLF^R zygHTH6=n}k;q7?+>9r9&#FWl-uul5Z*YlA}H>ZPi_g$m7xc8NfA@qqmC0VjdwHn2e z_varUNNE2mibKo#u=g(Va6CLjlQ>;uIA$%VO)~8H4#^4lBU`73%on~0XriY;BWqcB zZ{M88+CRT9kUrD?i0NRsuZ zEqMzgV`QNM0dIf0eMw)4{r&EZMG#%X$_H~XxVyaLGXF$w%&nexy|=MkVyvT@w0&ma zt!=Sm=52n&O};*aT)OomfE*r|cuCFEvBhlo%f#}PSFMUD3qRXmK`YZP;{NvG!Af8F zCLo0ceUD2OL+tf|L7SRDGa`7VWuKZ`DzhQr{UL9UiSq}`PAp@EhP)cVoPck_#U2Z9 z%b~ts3wDT)dBp}waZOCwXpzlPSsiIyK?C^Vi3pC3o-C#6MvuZ9k^X=XPbrJ->{@mS zc;r>YMIlVKOsoC91y9_n=`BN4{{RqQw^w5(yO6T9(vJ&$svZ72#%@oM%tBGRZ3``p zvx0i^8Y4#%w`Ldr9K04!bRTWF%Q7sxINPz*x(U6F{ixX_AF@-mlUZCHWEmNRdR83Q zfBeU-b=ASuUmWrVdzSOt8|&XQCvH@XDU7K$TG?OoD8=o--Tnu)MF>kd?)CeZAJ=TO z3k-;}06fv?CH^>-L)^9Zvn?0mJe~`EI>+Z*622GdO!A99;CEk98#B!vNo{`aoEOCW z@PqOS?D1Q3>DzH1Ye8NkFEzY8$bRjdij%-x&`gv0k;hxDF$Fvr%J=-P8^Zm<_4m86 z{I!FfwaF*EbuwuY>CU{l-!7P`1*)CG5>E zKv78SiukDQPbtjv=-Z}&G0wJ7_YMO7;lbG95QBG36;~lm1FD^6*4!yC5&1xMCa(>M zvc$h!{&Z}pbrRpyUQaCeD7kC%B+p5{x5rj!tN}J-u#bznM_H^v^IvbaZyvYepENVz z@2%Ho|C4mT$cpsgrc>gF_oe_k@CPcfmb+T7_)?eOA>#X@KjY0`_IWfDr|TSUX)i6$ zaSMbnw4jLMP2wE`FK`=uX$0d%ilYD?hkhw_>gZl4`sFooe%oM};G4TD&E@;62>dccTe9OA{A>4_tn>l@>G(nQHPBD4;*M$2iT#HpJ^zb_;$+ry| zj|XZEFSe-P|Cg40_3FRR!j3z`*Vg6JHny?6Kh9!Ru#IcqihiTe=EKqBKARq zIAv)e&B)NLpk!)ja#_^0q=a6a=Z}{|Hd_%sKnEI^GsVVAe19sd-ak^@PoC6O08Re| z`zpLHds7ae4xR^>g*2Om+Mn!IBdf-<%3`V|B72j$5ymS3XIoqX4y_Ye&$w+p16zP>Zst9}wbM_3k&k=K8e9!{lo`vhJH4A8=;ggE(mdubbd10Eu zn;y%Gi-BUr`{@b<-Jw?gSALC`@~^DrEBt}9LSUZiE-7opP#E5|vTG-C8&|??Q*7E# zA6th^28yA7$o|P@-&`vuTM8TtiL)QLm3i-eMGXaRD7WO>r-?(wlN8*=wHvI1Jd)Ru z{em!0py~O#haA5pota?`-Wt+iQmzXSZlC39*r48BU62FrQv$9LR47TOd9Y>?3YNJ; zo4dDF?6lFsMNkFUM?i=Q=t+RjKlqDe>#F&Zuz&CD|NB&IC-OHVK9+H-J;pbUXaKKS zdLEuxatlsLOMc*m9oC|Y?H7Ftc{P_=se-30ak}20QuNbg_CMvlm@$lWtx#o~))|nV zD^XWwixRZZdsLD+^ySNdV~&mQ9mcYs8~=~1_YP>!AQ@Jm0R`};fY<9_{@gFhVcJf5%X zIB573XgeQ8(TBy3vRlxYI9WKw<{_W34w+x#)< zzl3yky|L1_M-zV=?#(;M8(i3bcC|sE+7pXBpWNrHPdE^2ibE7mO-RZf9wOC-kJk~! z!qaUndfiGL7n*f*v&bYX*dwc`Rbv%O*8hs!?Eq=mgGuLLb-Cy*dnV@>5EJOd)j&5a) zjAY`U&x=T!$(YLYdb>ZvO6QeJ0cDp#(}*Z-#&v-r%uDsJ(f8@k0s=Gj%5}x292?%>S^sJG1;a_t z8?rZYSfjuK8>4C8yc$@n1P>P3I8<7XRQc9<&f{-lKPfS%M_UUv1E>IsMHMp^e2Bbw z^7IVgic_;O&@v(9zkK{c)O4HH1xw#J-W2kbeS-U%kN{bd9OMri1Fsim9Zsu_d+!{z zy>lx{&Mfy3d0zc7qdv{fm zIzg?soECU~x}o#vz$DtYN)jv5Ry;A1!;3s?Z$Fp|39+K(wb_UKA49^w`1xn*L8nH* z%n)?>v1gWCdwsYeWASEOt3=P*cQWDUCFR0!?SK4gQmnsgbl=*t)l~z?_!}(5`)cLz z*{Psfz_I~`JhM*K(zE``@$l({-q&d;$HkD^pV#w!H}8Fge~qK+h#ZdewqwyG*z!@$ zbeNjpM^l;X;~GxP8Mk>CkC{Vljl@yYS*LqoM#KBom0i)VH`H?Df_Z$Z^PGRu_Oa~n zmiX>ti8mTGtGET_B(tF0#ubGV$3M60mZw5EBe{(a)Q9_Bv(s6O5yRD4gNn%MJShHj zhbQ#R9&#?#96OWO+fl72UPV=Us)~8hd$yx*ZUPPwSa_O^mQY~Py4w+*{p74E-jp{EVYaqgLHQolkTdNPzO_-CgSQn6td?cty}y> zwTr<6Pq`B^rnX&^M8DD`S}k@Gd*?_xS_O0Epq|54so?hIp3G&fav2EsSoN6TaPr*E zS8hJ>VvN+o0#BA`;t!<>NzV$63)oG0G!J9HN24m!95($_)!ltHGV!|Sw5F>3K6*=8 zWp2}?_h#JO^llNChJulc5vx8e*Gv~g6qBQ@{TVa5Xo?hsvKp68A%-3wiRm<4F6*){ z`M`ao4R@^oB^2)ylxSTUXFxT^rF6RM?T@03SD&`bRrF4+mz4L#qQgn^&^+WC(2{_p zJX%^IMZ1PK&E?&7aZWycnVvMgHa8Y4Jh-bd_=B1frWPA8qZb!xT|7q=EdqJom-8F2?xB6hl4jcA3jx9QMBo>kP_=T%jc#8f1cKxp zEWau}bWeS8DpoynE-R1GUWB--Kv9neY^}?@?O!=}7!68s-}u>-GNWqjX*?MjN$)Os zZwg3Y7wbZTgD(pgij(B$*8(f-0iQ=Hf0RRJkb#~k5}$|U>-ja3>+p_x0Y)Qe-FG{` zIGf^t4$QTkJ@F@@cN!#dTfrN&soQBH4oFKA;r{Ph#j|7B_J3TH{>wXm`#a`{o#Wf_ zA#FbwNkb7l={a7;x1WfrMb$O^G~NxXD|`3;eUuM1@p>3%A1`W+4I|B?Z&3EN60Z9| z+=K^t(D~If{z}z^N!5gVyZFP+&Z&0J z{elq_>OvGDBr4*}B|pAz#*wzN+R+f`bq4p5cT zT*a(OD2a<>#JHO3{SMVql~vee+x+$3zH=n2=7;gEy8SLwg4Dpom2~!gdz;S~?HBgp z6WS~6zvdJ7u8SE2(k7*iwLRa_x7x_=jx@x$zE8zijC_J>p!ju&5{2mi0b>O;YP+(}X@m*?8}6Ya+W@AbWIJIgWukVCk5x6mq&d17R+ z;0^yTGwAM2@2Uz(m+M{a&yY3vtp_;}2BOpDC2{Zdrg5cLdz_2-pMn~V5zUEJI$Ql! zO>wu}9e@aY!D5P&ZeZNQ*HBXzHtOCSL{-f&SF+-LJQ5J(NLDOr&B@ajXc52x;1auI z#D#mG9ZVpB`Zv^#=31Q0bJUS)R%)J#mVsv@eivt7%#(+eZ=Kk8YiS_$*Q`Y*R52U+ zc#pLf^M+aMZ)_LA9*(8z{=W&GLo0i`@89^GSHFQD|Fd&UJKATzrNVLbKh8!vcP~3r zL$+y%mo-_+%=rcvl|PJ-v!dmTK|;$o`J@?5o^lPtgb(Kkq?ak67Uv{uyXd{7GoxpM zK}{MgX`iNlvU^||U*Iw}(S2_OBinuka4@iWXuW#h&9id*fi0+Z^$M-nreF@a3P;2`am-3RK z9p`)E)K_tPb$q64Uy;!P0tITk8TfP5g}kJ|^K0(EFEfHoXYDU2Va;S`TW6Kba2#Vw zR0o%Az+E6kSFiv`Nh>P09H-SxJ5RBh=xS#NzUai;$*c`6AcN9VwkOr6{xZ1BcWlnh z)%w8pE*fF5Z=()!vwR(mur_0dR{KgU(s!p}oiXZ{6%7EayFk1JtMgOK{OfYo&^i1P zhI0y;XitTUC(YjNBG=T5)0wrk-?;MiPBe(opieXSB#3wZQEXO*oKauj)>qH`(;s)P z&Ml;W!#zr8q^b|ZJA7N5Y~Qk$iJ?rhm?D$@SDHd z(?@>$=`ABSncx^}=?PN{mn%!p?*j7Y68tip%5k@KhAuJ-ipz?7xdjl_OW&ktA5x=1=m4tb9^mh=fJE*cP9`#=Uq z!8RHwG-&aNQDSZ_c#z$O2CVptHe+`*TA*1tr~Y<>p8`8*u{rH7zk=&#WzVdyu(k&o zI|%eO$v0yxzkg6i8>D8glo)MK$YZR(1J=tVOJ7#jZvzh1P0JkMTDdgin-d@a0ELYk zV5ZltW$cd2u4Cs@wrqK@V^(D`!#<5u@ZzzWUtS}G3BWTex{CV~nN^9Oz^6k8A$R%plz6@f&;pu$1@525!2xo^-Mm6F^2J#{veF1NQYf|8|L)Gl7g@gtxcDyYENEIA; zI$aNo{BiaNQG^RIOUVPw2755xL|z@b&zM!Lo& zMWYi(?4cAIuU=?c)lYj<=#(PFsvzpDWyCoqTm?}v(_}#d^?ZT=<8DlV3cAGnG{H}x9vy)1>K4jgqYDS($c!RDP zY#j!>0$SZ)PXgPVgjj(*CPk)3*_UYr<(yKnZKSPnkIkrOh4}EnFzuhWgT@=5a_#~v z0z<3po9=)_rw%tAgKL9ZBLxJ!hd-{j0=W*3J3$I>14aTC>+okv%H-MeJ0~j}UCB?e zWtzu;>_dwsq5QNapMZ<^RH4Jz)(|+*_vdjzQxZyZ1liu4WY`)HOt9JG=gXo8# ze|c>VDl*#S-LG2PcOqw_uQ;pe3W(kN1!G@JtMwfdxe*F)U_fNMwE%auzD`rh(o%wN2|9OF58IzTXH>Me%RA;fK0-UZ& zN(BZ0VkWq~9|hm2qNfYy@OPr=r0Ftrm2244P~BPY6Nl=He>k0#meRFca@_f@6STYn zWMZ92G)5#%U?^#A8m_+Y?kl{fhBgQhN?O$_lbPa*K5*30`%vzg*>F2~oz=6=HB!>? zRzU13wVT!smW&OR({4(|2;M2~)!#V2>9&AXv5iN^*#I;y%_&$c$8cR@!iw)ls)cjd zbNx30&9o_Cni?);Qlh{6tU}RP5D5q_Rrfqmx`Ss~baMb{%C94#nHTB(` zz7xRRjUMXv>s&QDut6Qwb3tz}-BbOL=6TJh#(HOkfT0$T+^))Ex z{|HR`iH8U@r#{~o@iWmN-b60j(B(E9br#iC}TP1+cC2E zT1jl;37ZG++K7VB(3r(%T z5o{%o`VLEfyP*Bk%S z(~=Kb&d7}~bnTqnhQ^yNLeZ?I%P-%QyDD=~%$G#~Q7 z>FjW9+e>OLw{LMwxOt5NI!mraD{4@Ct`;j@7+?Skjv~EZN%6{wCXOVq%EViZS+^)5 zgx8-$1{-4R0n}jQ0tHk6P5|@(cWvZSci^LamjGPfh9l8s+X3b3oNqsVTQW``Tc^Nj^hm=bg_r_Q2rTHO}HOQ_a>;!4fBZf0?f*h z<>;6-GX+pnDm|dCyQag&2p_>! zxmT^J4g8gH!v{^h_XB8hXMudzcLwAl2wQ5~pqBW&tCnZ|I&B}I4t{rIbp-EtF2#wa zv*uTMNdV-wIPMkT-2xr2tL7Efy*>KvGn;W?)0enJoDrl$56;WSu}Ly*{ZlE-XjSp6 z(w_^MA2`a77mGqW$-QD7p{&+5FU^H**m@s>_##$N0cAK4sqp|w6Uf0jir}F-{LNzR zXV)Xgh|OCSYXKXKLZ}~7u3bO5qIVI?!YDuU=cD$a*8-O;(wZddAB&(!73myFw}c zFw#*4ZJ^7wgU~jfXY57G!#;c*!H)DgcKtxEm&s7NwE2H!InLaA>u%zT?z*qB9|*+S z@i&>k>$84E1bfD*2G!DX2stR!Qgq;t9*XOQqcv^8^_g!(y<7#O;1AJGWC_HWqNn~1 z{46>%4Oyl$5gdKit3-wwQTP}5DC(* zY{*CHvB^-P_aF7#T%%PULEi(bkEgk6COzNj;*IF8AM_Jj4zmr2xebyPrIjUZFbKsv z-hb@T)m=^rV)1?}o>&mBpm8=~ycKM*m*eAq(3znc8T;%*P=MM}w=xTM+LE0y!HQ-) zAfEHyQIQQgkS_@!xK@G!Z2yu=ByrJ8O>&2f8*2Y;^)OfehovgYec`XYZI2eD6GHh* zo06?LCGDxG^^UC`8CQr`NWC!v4_yMlEV?aliyYD3`^cG=7$kZUCFO$hM`90;~z4*FNo=?ud-gJ ztRCuZ326BVH`_sNAD1J!&YI`d&0k7r3$OPB=&bil%&p>?)Ug(@lY8%AVwW>#KQ06l z5+KdP?!j+8Z|KTwi0|iogl7X)C+u@VJi?sv_%M)1Hb@>xd2owP+#}1^1_hxyzS!|l|oc}QzYF-ZP-mcY{W9-y>yb=zS8F;YJw{*XQ6vXXP%~EZ2`@~iRBr?A7UcqHT z&pYnM3Vzv)9v+SoY!tXpUjKzH__Cxp4ZuW`pdyJA4LK~^g9LfN@EGdK_Vmj6SZTXK zvh>m7l!zS*#cl)#` z$pJLIf+=r0Vs)#w)wKl{0#)L_&OsW0)y=EZ7%|w>oSAspFukhyGl1L(;C`Wt%CV*`N@lgvKy>&hD7}RzLa4&Xq3q5!ImAY+B4&F+ng(74 ztN95ya5qaF4{DXlA3g{FW)n4#Y; zZ;TL3PV?L{c@R%FX2j4>dB!FI3_c!iRu_#g-gY`2*BMl|WrTP#LIRO0ci+u0xI}eT=OKwvoJX zLmTa)r6pdOok5lI5c_R`elLa{vz9cL_vL=-lf`CN?`T)ZAKA|C6qcfWP8;L!;XcDt z>X!lXMQcr2V};0df%;a;lCrUhPD1M3wKVshF*u;dLbDXzh!;Bka!5z@*o^=XTE0Nt zK({fsk3V)+g{8GX!w~677C@UnbwT+?gmpa)kia2PL?#oF3Vt2C1nQ@>xlZ z>%izq%Rg{*(Nb*#-NR@aHB0~b8v&e2}L}h`I=`$5-Hcg zq>}wO>WtLjl*n?cPg2k5xx)QRE3oQvl`fUl zV#s;;^;CpgVR8cCNB9qCtGGXK&p&W2vGWGJS>k;2ZN3SimP!JtuywJ-Sp!4Z^pW~< z;`-b>&us&mMex~PHa?t6>hs`IINnaA>|`w08udHQJ$$k^#+P;gZ%dgxl-K%kD$rex zH!n3h5S@;jIwh{@e2ffjpqsC^df|3|ZQMm6s9BOqIdPy|C&{nVJl7igYK2QMN&)yA z#zDO17w3;*@X>?GhSN0~An@$WlX76+ysD8~O*ssHOh{YPjp9+N#wlgn~=umM*S zVoaLl!^+WfJ>&>=th?f!kb;-rKZrUoyU-E|zVcRJnZUyR>w1dbe5P&xC5ptouZR;p z@L}C;@k&a%`)fP zRt@XpN-l(<*ee=Zm9eS7s=l0J_3dZ9jQ6wK`1mZ#qlR)a{%wE0fv+b^rqY4wb9hJA z8Z=E;sXnUB?XYb~G3|5Hv|9Vc&sTP~Db5r_r=zL-m8d5gf!;CLVi&(V6ea^EyN=z? zavfh{K=v&S?Q-Cf0%_rvsl*2J621Hnj|E%4)3xK}z=lT3sg-mXm3ZaO9k>N!hpCn_ zMiZa7kZHs_3Mn9`G~3<7L7Mnmii6#=HkqyFibhFNhD>g%gZEz@m4tofF4 zVxNU&Swp?r#KfFF`be~9cE|5uk7QC8NZ%?CbV$bJMZ$0V6Luf9Ts}DhB`AE6XN1XuN*rQly z5TwWc5sLHBS53BWct@5LDrkZ$Ob9@|i~|O}_JqSB<4O(s>QC-W;Bm|8icuCxAh|$U zlb%Ay>OB4LQ2u9;Z6n$|2k@&1iA2k+*>{0=ldZ;upeu_DzD?++)=T<4*?B_ic~@LF zywn(GLdYER&^NEWHc>*=`i^*?IzSMznvv7;kJ^31Nhg>HSZdhG+_&B5lN>`ae3 zG|uHC#A#v!kZ{_(2`^3AvJUX*%+v;nV6)FNhM?x>0`rCgMeN2-rP?DpAHJ4`ZtopT zIrOe&;z@R78~S+jX!ASw0*a7Rq)?^U%nI%<^^))_PXzP*`712zl{kvVw`w44E6ugF zpH(n9Y7+Q>pJtbHdTddD4B=~|R$aj-vkB~9Dsv>G0Ej1!L^ek~%s0Y-b-tJ3x%p}D z5kKEg#_giE92TGh6BaFx-WM<2vrp-*gmU%=uJ&|WHAyo`v$L_()HnUOlTY{OhBUV` z`-b^CaWtZCODo9y46VfG$n>~)-QNaV1fL0&a@To~wW)mcRX1?%#i}x!J5$g)t}ZeK zuI3vxdiRosYX*37#hHKn@;Ss2>!QoK9>JXDRXTT_y*p9T$2T<@TfXAH>Id)M-`l;2 zo&4Dbj=I;GE;Uulkrg78Z?wpHlh_pf)uf%pv*w0REzyE7*QM;|;$?lx^N6GS<52AS+VViw{F`(EH{k(+t)35w@`NWlo3*DE{~^51CD=77kHc zyBwFAAdF)n`X^l?@3y7Mc8sZkPeX*O^`R?}OdO$f+xCOHX9?PSn+&yeQzbT6OX7ZK zm}It*C*$(~nI_{6<1Iyp7RDD2QF0}z;%jeMjyMM?7WMMVw(11qgAi3@Q;@g;@h$8i z%6w~C#x~x>UV+(S7@s_+kT&e7kFm>gfXupr)-v~IPuenq8S68S`4rsrI_(by9&PYr zkGqIl=ZPjr+>Q3b1xbw)p@6MVpLjei;6J|cF4jshp`BeU?I3cm!T?@1qj$c4@Yk^D_VIxYhB*?srNYhgWf&k)npTM z9N(HSbl=X6=bvjrETuTa@t?cjxb%GN0#yl>Ii#+!O0bGna1(+?d##%oAV-83GVl~S zQaoL_>)d9fnQp9Vz5B9Jitqto;yBwc5`61}WYrqbHaa8%RM>m;Y*2Tex~1|LPFK{{-Ee*&)y z+qKx9*mqj*W%HsmMBg&oc4>JNtKZzDfp$oGx#nscom#oc4BTJzd8s;RW$5P3HeJr>^>OmaW$wus<7#l9>okM*0f2sTsQ>m@?CV&5Irr;}s%%(6 zp8TA?gX|u);VYzPzwE9a)h(sNAw5491KKSjaRC22FW3Ak5(j2hq`y{r&RGY@BM7PF zprR|TGAaZuS)w%Y7{YrvG$7WxHKUP8Jw(XmOEg6FF8GJGc71-3+BFx8Jjts z#;unsjZ+q=uu6`{!pqI|{bB7IVj%wK&B05T)ae^UL->L;OY0XBFm2a5&)K%BoS@0r z1BpUH=Gh2!4`-r>c>V^;cTA1kkV7Z6L|4{68d)CmG|5rB@zc|j@ z_!_4LALAq{C4qJCR;zig_7$ACXJ1?EFV@?T;wgTr=V~khc%^X!(Gs0X+k#+S<5S_X zuWaHYztsW?)P;%xK1UH@uEef?USaEc4{Wo7s$b0jL1{r}<-b_>jkRgQEOj|)wvI_( zQZqfz?fcrJf!{iF_C-A@1AiaF{RS$|!!Ckfq7da%nM$ zm-UYnCCymYp;pMuF6;`caaz?!9Wf%&Af_#dNs)zpa1=iiaY3j@&dlEC9Om}-v4htO zD&Hku0hxfU;)(O{nkr7UQ!A}J7CJk6rUhnIhL)f2ERk%N9qo9r`5st#x_bp2exG!N z(EN4{C&~rL=r_Js=1dOu9-19%%?D}~xL-$`t?z4v_pH7I#Vm}($shf0&ieM7h3?Nw zI~AR9d;qPYfylC$g63atIvd>4$kJ?~>pXX!_wZO6(ej>f-hW`9jUrr@+h8(^zbze~ zxZ*1_{2_1RS}qG-F!kRk5HH^v(ax0j)tgiFWI;0^99Wvo3tML6e`&k-ti|(5hE90z z=lq$v#c6+Jem_#%$`#zPzv{ZeArwi4T zN*z+5IysOhUAA07eB5t$J&qdNyhBtXj}B zP<$4{wsWm#>oh{Or>;lN&P(L76yUt%0je~68jSERb-nQdrCsb*YGjYnz%N(xL<=w+ zn1gT^WT`{}qkTE~g1JUZ-Suyht|e8j?K;owfPn_AZR4z8NDkHd7gCBgB#wFY7{Krq z@dQ`)^-KvRglVb7XX^NV3qaj900&^77ohrrvc2L7ugtkcT^nH?8!6rka#V7ie};Tj zm}DkRt8n`c-~epNA&7Fyt3b2gz*F3D=C7_iS((SjMq$7&Jh{k(#8aiW*_~X9aJ>Ge zMn(c?vKWF5NrFd~Qjf0BdONm-Zc!KX2)1Dx`RyVG)|J+f(%3Jq{$@?(l0K^MXDr8@ zVZJ4{MY7^AL2kY%RY~X>Zh~d`-9ip2 zDq@_!_wnC<@1#DgDtRa{A}RvE|F`J&yyJLkB85QGZU0o2@Ifi@)7@}lZqceIRx_Ip zWAk_?l=y{_Tl%j~UPm1Y>_HjQqTb#4*ZA(nhmzQ{=CrsC{Wv5bqDoNU7(W+}9^H zfP&w$y+`}!mb&yBFMA4QWp5VM5@zz8S#MIjnV7E{z0OXNUy)dnE{Q)3oxp##tnzuNN6U9f zWxSL`3#3@s5N9P&5|DH3r)C1QLx}$Re-5GE|LXigS3<6RsM5~s_g-WsBgXs~jvc?9 z+zLzhv3)f6aIMqH?y*4&sOa!lZ)q%MV%=0JPIHVM4|33LK5UtMG&5 zR=u_1UX!(HrLV;ki_6u){Wsoj78@cYsP`YK*t>-cpo_UGPPO0jmnppzX5Hk^Xc7!F zq$SB8m0t9o3aL5IeOmDA_cPpyib#7J1^8vE$YT3K$hip3>?Q6Jb*5Es$z>Absg0nw zq*M58tA|L;+pHUKq{352wFqc>A}jduy*u{{fw*jj7$@b=V-;q~uPDRjS^_)952O^NbXrU=#r!&%4GT%THvd3e?93R$<5{Jh0W4invgMe2Lpi8RBmkcCw!fE7 z4IBzswvDk(qf4hDRe!xe3G%!vi1V=N_V1fs;hWkDR45EBc07@(;)swh1T;ve)-gO@ zElRe_7yuB!~HuV%_T==pZJ)xIGy`@+;2^YE$&v$NuOak6(%$S8DVGr3+7Lrs&n15UOH z6f0n4ryyqqlE(AX>y<`M2Pe5O!mR2?6{b{uZxOx_C~E>`q7r;#C-?{)+M^FHpIRXWNnGr}htqBWmQ3~9!|RDi!R>~$2-`GZccX7x-!1CN zR9fYS#bDz?X}k|w>t9;vNm5nuLt>BlhdfH$0KOu3Jy<=Doh)7@T~Tp(`U@#~fP^l- zK50&D00*lLY-knf!!WSc?IoXrxM*a>N(;KUTy(4kh-te}k?Kz9{XW~ZGfQmf)Hrf! zKiN6^im5Cq`CJn8Qd_$x>p1V--||@dH%EuA3HNN!{;zz(Z?+J%h|_3Vv)4lo@vv?E zbD(&2b($6uLt)$z49Ro-Exnh0xp?Pnhb&>-TMn>Z-OrPAYme9zOoE~+Jd6^h#Mh+F zTTD1+cS9lQY{ zC@BIl-9UX8!iNBNYE@4giU28V7mUNeZQjPd{bbpE9fbqr*I~6BzDM`R98memnDYmk z@&aGmWx4g|-r4zXHGm7QwLkXE?(?d&f?t~1Hal*aT=Ic!&i-D3UAD-=pEWrYQXa+|3pL7fLLJNxo8O82$;K@B6kbwZ%d}ygq=#nL zB`+z3>Jw(twbD#Rmxj3~mcQtEb=wJs#(e;Fru>sLaE^CfEvcR?rNW(m8S@}=%H?sN zteDZU6lF<$t)Y~t&cEfAm-`&X6 zeaCn2Th5B3rKEg%?TV?dOvDu}(Sg02p-L}V8>n>q z%V{e|Me&Tdc_txsV$^Y_=1A4J zc+%?|E0KF!$m>|~-}+`3?= zDf3>nnvkHwzgn@l3Bd#r*j?1~>7`M;K%XA?MTV5%D@(qj=vDOeU~?fshB=LF672Ov zONDIWq{7s-5B(I&!xs(Fq36X4|B(roW(dksxX9+0eOui@Wr~nbcIj50y1-0U(XJ>n#m$HH$; z-(gRV*pto%|Iz3NEW#Uhz{vtrdR+p9ed+9{?c(;5#oq29P?^9p`_Mjq; z!M|TPA9!JXEisdd6LKr(x&@hrM{D%R(q*&5A>O|(cdtrwvI!^9^)yHKF~UDcBeWjU zV51;r$X3fw>WQ^to&GO2g`|{Cfxy~F{7pXMu~(xTIr;j84_f&L5$XD2x_LY#NMGj0 z=y|~*I3TMZwiq}l%xkFwsk(O^c6g`!S9Xc~x1ikMtf+Zg7vt?@2K{da%sINiWG+a; z#MJ?RS>2>_4l>&*r>dSeJ~P#UA4uwY4C1x-q;=otq2iFEIAWCFwv2WT5uBvJK1BFc zYkD_90EX;8BrEkfodpr;QxSN#ZA_5rvXLz$|AVo0W%OJc;pv{L{)_-`>wc@~K?R7u zWw1wQE>~j%^Le4#6O=vOBVTdDQ*yA5;5W5;x9Z}QC0wKLil@2)YQ=0I&_lCjy9DaG zc%Bf6otR^UMS)KnTl^J*TH9cKM8$TQcig??;nj3hcnY*+;p@X9%`ZI-X#-FbuUr-IlDw zP?DxsI0bUZg>YG;fJ#7RoO!(id-Aw}B-t93iCK5G#uu+>O{;x04;HUGevrJD=aS+* zg;}o)v8LcTPeb)D=Pd37jVlvYFf5pd#m9g(1v)2`ZPMCH-;kzHvj=L9?!K?U&I$X& z`sdrGtgatpSUfBZ)*KA*RjE~@a+gu0x&XWrVC?2Z!3F|uK z;Z;CHyYbtKy_V38OaOxy?`I|HVV_YYCXG}E{QUINj3D%K$26hm&`zRet3cdiQ)c2) zA<*QskVgQ+9y!H#-B%f}l>n!P z{r9?aER99Ymryx}c9Cq=mCc;^(%KDxGHpYuMnOlt=5>eIl}SeX7|SQeG5<8VkX$Q#yx?0LP+=?v zyzpS+EBq*(KUy^UHE5HaNfbMXxXdo=1uEUVWopZA9=&6~r<>LO>``fmzI%H-{7T+4 zRM6SgAAv_!fzp@BTGt>+lW9&0JRgdRjpb{94%D}5RGc*g570&&o~P9P9aYy{7XJ6f z6nsba!(u$^TZ(<{89#MmC8k5+19_XJmKCp0qGgI-ATwJ9f71K!AWk{)yZ9zBrr&zD zuzs5UM{S^?7pE>db-@3)@FFx$>^{?#;;4@bM(#5gvrp{9_%X|*jNAZDllrNR-fLUJ z=jjvYm!4f`yt(*q=L_?F2v{a@mHnrBs$9np9?&*@L|abcM34IUKOVdt@3q(!K*>P~ zD%WQ}pK$hiYYnvc@*-W9j<4|fX7r2*F&u84bL8QTxY2cwtf>|F$<}=o2Tvb}zJkA? z0L4%ep-D!@O9nQs!}0y548?kj0-A^}tXsEiB>$iT>#hXUp&HQ-+-lSIxH7&{;1q&LHvs>x%10G- z>{Cs+4BeUg;+427_b zp2&5a8t$(!>j}djhh($Inzfh*{CJrcwe>Qu4)LB-?#2rPr16(q+l3F@02I7gONN;v z{??SU8?p{1kZ8|~!SS!bQ>r-?1zXAfukTDO6Fbc7hz~Nhb5Oa&X6t4@k7Tpl!GP9m z_dRg6R*8Ab>R8AQ1PABgyI%PoaYNU7t+fI>bd2|b7B>_(6}&UE!*F9q*7x@2!Pefn zk8=n5B@KR?Y#piUXGIk1V9W}L#8RqYN!$?1z_kc60JQHJYaI-JqnaGwnnj{@B&V+_ z{z@i*yDerMb~P>Nxl(0W;|c-~>&(-!cShqD{VU9g|8Ppu?>TygjLrY~?zv5sJtF(u z)OCo|=nH9NKy+w zm+mV9aNL#hxQ6rL>z_@)ATD(+uxHf-uBC&edcyXbG(*lAUQ4Gd0C|Yrbkr;ToukPX z9}Uh$Q&+9iSM)GlUr1->1uADDowhcLEQ2RpS(w7{Khl6t# zNxebY1q|Gpl#sq331ueZj6B7hA=fiL3*{a8so%c3_d#AwkEb!uTCI#DLiR@Py4`o! zgWKK07h4Gr?ii68lNf@x?>|*TaM3a?GKJky#PD>X%(_m@X}KNyFo8#ZCWWZy6N$Ql=F z>z1bNB->qMnGti>fu5x6!TovhbMty@ zUi3I&r8i1T@Eg~QC4$~Q;8jX3>h&Frwva~Cr6%kUG;Qhmm8Ld%^=gH&Xj)bH`@o1o z$ejH$$>#fz-pp$YwrHj!>+%7+Mw)PDj8`;+a)-sKjfCK z3vSB|2E+sc`RZi9<+#X0SUzJu-8o)aQnK^A^?sNjE>o@N;Uzrdhsn>xr^)=eXqilXRzefcS(13k=(@ljr(QQCS{1M8VCQ&DQmFNsXQbbeUCK#EQL@7PV&(q*bF@joP&-wTYdI zSu6I66)~Q>pYQMYdY&2C{=9!E68d%YMQAmtt(`)KsC&e{2*(+ZW%-nEf;~RwUWLYd zeCGdTnCfI`N?Lc)zkD90j+%jEGtUYA^k&f01$z(6#CLvR+ELPB(x5TBOCQz?Wu3WJ z-5I$v_U^(nFV0WOP5NWkO3ZFL+G}xoUlZwl8+~tKzDA&}6DzP6Vo8&R&jO$CH#+%Q z(K?>m@%oE-hVc8Q(Fnv>lWrBQV!?5;cQs=j=!iSTmovARQUgl1_8-IZni&wT6LKrIbm8 z=Upb0>n4kjStVWN#jpCwUFUb%Bc!rGH<3A}V%ITm1Z1tMqrpiZ?2zvTgk4@AWBaeK zNE>5hO0yoclA|NqG7ageEN8DtKoeG2o0DVDI|CLDUWASnM7UTjM=og#vSYd`U*ScS zajo9T_yybIxh?jX?3^zCi8dW;aXExpJ|**Sf8hSrd{Z-dlFJNEF;5}Aknb-d4ZUkZPK zRQK_3_v)P$GDZVM*%{K6YZt`omY%G8pvsYeQ9@1^LgRkqogyjKqJ;SPjTRfvSP{NJ z=qbbpBtvb-ypX7sJnx5v+j!2OJg-El2;g*{5X6Ou_6%e9Gn?p7{o44OWnr+-dN3g5TV} zz-}++(ONUO%L%RSY-WIK%Jl}#%zv8d*MjU5X_38a`sZf5S5n}B?1j+$B(~S?V~l;M zBOn1H2H5)&1x?+TKdr&;-d)ZGP6h*0hl(V{nHSFJaj_JQ8&1o@PexZ4?SG@($Cl-J z89{Ra+dG33_WQbI5G8(nBS)zrSE+FrCsHIx+?*}Wr!T%C|MYSh0HGnD~)Xg(Pz4&Ai_#EvO zGR#ZloT~FLtk1^>d=U%J7wsF0Cs`i*6)L(E^@^_ABX0)8Bdq+io$GS{h)EB1sv%D8 zC&&;c-J@2bnL}(hd4{O&fGi&1LgCoQo@?BB*K}e+!z+K*cQSfp6be{kio5eYp&NsZ zs;%ARz<(I_SaP+$#pM-=8wHr)^%y@=l|!VNd-+ESq$G zuJtzGX2Kei`O>?>MqUF z2CF!HlI2K*{VSbW%!(SCwG_1(ihS+Q0P$ae_H+xBd`Vd648aA&b1_(%8wJ55JjZkk z6?qR#FCw70x<+Z0GH@e^HfAk=RfS@DWKM%2qHf{Hb)8=HWU?V8u~%Bfr_*!UC`kp9 zV&Aak#cWBx)fK@TX_E*a9)1Mq;Qzz}bX)LB_S z+LaoYoeZo#3S!%5608-O!*{H_Nn?o#@Lsi8v?xMuIiAJ&ajc;3B$= z`{`AIo!3Y`diwXha z6)5`|A2~14J>No5_MPn5My*ydp`@sp^QQt`(qLqqhe!YflmrgRe3OMwl3OxN9jcHq zxZ`@~)3vR_Y%YV(luoBoOXg6uE9m5Gg^hfvwa!#pN7N$5y|sl--0y`<;6cpNT^ewn zWtDd5%)x_+n1DFXb)kgmcPs1qt>m;C=m>RiZ>C*1+8wt{+LdvlX5FcXf+mfX!1kg; z$GOG19d~XWC2PtPT=|>cnRZ*AtGgI+>$*n|*+a0nB-u=UwV>PY{Mq_Ieg3ZB{BoPm z_-?gUKI#ax*MivDB@CS@hQ-YJJ;!!Onr4GDj|Ugu<9;cmQ2et$GaUT-Z53LeRPC_jhlQTk1ABYdJAC}C6bq^3x%y<&e5 z9EyS$9>H)kf<*zT+sOw6e|076438;B;dZje9fLd+_F}K?x~cWDZ(;xmZq8Lu4x*$k z6Lhm|W4Zg8uzd|IfvanGPlHGUNoq>{aNuHFckkcFXnXMy*PVY?!-K=6&QHAlhgkqU zX>s_EB}KT6A*kEwr}NFLytJgp=cj+Y%a`SWod)&v;M}G{%P)J>{fKL#c3p#gN=ev{6amIN!e9heIJJzkbdxw^_`d_nF z+$e53f+7K$C=*ipQU7k2G=uw86(BkL1hVz+BtAR3cHW$wZPT*%H-4!!NY532o84$P zN$;ndh0nK1WubXIosVKVUBsJV@tECj9G2~4n?VWx@f!iUeU43XbmFNB&F zRne*B!+nb+tQb79r?S*NELm@X*uGyZka`LuWJ{TQ-O5-{ERv*wE~SX!RY^ivIG#pMiKVhNTg#{2roYZh2!EyaldWYBho!9|> zRZPxrggj~JH*hL>#7xdhWKc(tEv~;)`C^RHkxC%8wSKyc7-W^XF44bNq9I3gi5zB_ zOq-q5fWtrcj z8WzCngSG!&;HQ&00vgl6%rO^=wl_xxE*F%ice-s1?bv{Hf?=g;O8f#6I*1r)174N3 z0>5qlSalgw)lJx>=a_TDrZDWHtcenI+%CW-0aRZ=hO>2Mvve~ z$5rvGJFAi7GafK5mhuAuvp9;X2deLW0{$!|10>D&(wA?C$s?%@cJ7+IoK zT`Q;ljkKh93IWHfZ6Y-0{3CcmRG>~1JYYcLD#ydVhq+|}uYHVpQhLYLf2Q+w^FO|P zFot1Tv}UQ})#xK_HgpSkh}2}O#dVWE-bT=j&ClQepyoHk&915pXC5fmdmyi5g^G~b zNm5tj>Acj_X*7iraFyP{BoVGX?k*PGDF|DNyQrp-+`SLf6~-I#Dbp!MsRI-Ow}ujG zE&Hcw2L*IzBjdDu_}z709|v7NbL;Bi@OfZjc3h9T!jTDWr#Sbd`4WLGBRx-DW>u@k zIkvU^J7bx8d)~D*iwLzaM%{32=2e9wg&TJ>G86g*G4}oE^uAmsTcgc~yeZS90M_y>@x7I{pEI9zIP ze6V$GFYv+Eq`#RK07^=H+mYoTwTOH|RGRWPi*YRi(YD$g*LE+sBo#w|Nj~06k1^wI zP3%eupA4Puz0!KX-5$@kG}K0&W})gk_>P7F)|jC6bI>NzE`CPS>w4Do$9cqDtA+Bv2rlpO1E9kK)l6 zb{6l)xW}rIv;@qcsDigv&}5=Rkbu9XUOfI+({qP@TL4W-7?%x&APARv5% z7F293PE|+K9M!QgxCvjL676&#Xnjuj;q^H3#YmTq;v*C|T$Eh1|FTVH0u=LfeE!4U zC+4BN23SLKo1t$Ibu2Mbt%h_o$UEj_Klk%X3~cr+(boCxv;(N6_!m{fX>8MiRC={V~;t{pij9mV$#DQ?pHcQMqr#PhH9zI-kP3Rq|Uw-nT;Vs zOiqbz$#+q|xbECH9S#1h)fCcPhL~@m$ht ztYm!v59)jEceY0Wg{*#{t)cThpt0K&yy2exGwZ|2#>LzaY={ylfb9?XhW|7Gs=4NR zU0sqRK6p<@AFHt=4fG@JE*9)Usw)eI1q=2iJ(Q~M0!-u7=SuQ})b6(q@5MHqxjgQ{ zbGpn6V#(c0zoyRTC2u5&L8#c#eHHyTfmhI#rlL%EmI3-tzn1UZEq9T-Kf#-J?EA~0 zs>mOYwr*ssQ(+(RDAQYtS*+cUek3(R9XOE+}yJf2Gk1!wL}8kV{r3J!Kvg-&4iJIcVTaU zKMtZ(W;W=ILOvaQAY3bmaN+w@t!VmsPWJI}h6HnYiKeNCc95w992VoJbHyQJX+n4< zl+xOsyC=BUm8T8m(H_slDUzQJULjh7$hj6Vbk+M;k^)ox2TOM*_Qt;N_LwF1S9g;( ztyiXhnb}Y1x0~=6=jjsCQ2u7f%m)n)JMu=RPMCv7;0_+~Ag`{*+66B-o|8LU?YK2) zI7sI3FiLu-E@!qk=l^He?rg;VtM5{=hdQ@7o-%&)iVLx($z(mBsUSRwyqUD6UzM3O zXEY{~h5V-Y$0KQ-lcQe65ySUu(*YTIZxI}ExX^k>xU!IOChf(jy8Uw1t~p6#zj!%@ zbc#}Ug`5hOnjPiFXz>5a)6M*ydaiQf%J;T>@H2*jMGdZ`wMU5rPU@id$$+YBMHx&R zjbDKiRh*=5lZ^=qPdbmoPK28_EKVC#Sx-FnM$D)-PbSbBEUE(4<9*$XxVTlG?8}KJ zw{R$|arMBfv&apDpsWbe%mMp8HGoZeQ{2TB9@h%=!c>mBm03mwOk0~M8?or8mCpgDvOj;&hc(P_I+2r ze#_q<#yECmBBKjVy~l|Ea9-@W2-6WjU9fwl!w!30d#yf@?WZ~1dw4NU*M^BlPDpLxtY1&3(pb9LS4}rNvUQqNFsk*4c&>fn3!{;q5oegyGoJM@&f>D;iez~1T%!|d=FRK0U zR`EiES;4AO>&2r2$;QXgnH&)$^Z*<{B`RAPq=H(VBbL|PD zjD0{zV{0(S!(J~9WCo)#Q|(B}>8<$e>E!GOnQ@~>kn-Y zb~5hbR>vSOa|o_Gbkjzq-eVm=y~D?<^X!~89AQi%W?u>tb_{rnu-DUzM)EEkK98iq z^JNR#*IoP7AXI8R3;Zyu$|%Q<&s&1%#IV#;IFw1mhm9skTct6YkUFqK@Y;E_uN{zb zVVK1yI}Vg|R9C#CXfFI!`gN6|Q0EzoCKrQdfZd*E!d~$kpwL!2-w?7stdLdOjHx;o z^8_DZ-8&`nIs=biaX?E;)#d?eQ^VbO#=7XZ!fOw)2@4bSh)*B)b)NdlEW%mYHs8f< z*2^5{X#%|^f4TosZQtWVfip=_hEC}QZ3A;C1;Y++L}Z?%_oHDv);crisuff@mqvTz z=y}x;>y|MdV$34a+16u)5qr8^xz;+Ei>1+0H9pnD)1nmxI0epeLbdjtxpnK87pfJ5 zHAp57UkxAui-=nItFo5dl}) zQW}s9?)FJtpX+xcS7VY)$52JZDccQs?;vA2(8DzEY5yyNH+FFb^GAa}ce)9FH!5?p z^4vegohCP*IQ#o<=4B@=HrtvXp=HT!7u|j7wy*GrAiVK_|i{p|mkl4YNO4;^b}Dt(>Z>I> zj)@xw>ZM$)%&t_kS9>?;8pfkD=IPqf^~NXiOH1NxxcVoreDA#)am)0%D`Qo4oVa_Z zO^5I5t?!rbyi@6;r)8&Q4_^ups?|>8ajCTbLm^W24c+o?ik6|iFA%V_wBz9n~)c~dR2gLPo>w&vf^-YnRO3P$R;>9`O8dL}WPcS1ghu3c`p3D70ZDe9(JkE_X> zB6am}){-ywWCyF#;n93wefdm$)-->QR&CbqFKGtH!drnwlpD6|1=W_8U4$v5zRZDy zaGnnrR0xqB-8(N^!N0y`W19x{%3K*d(>wGTY-$%+P1W~Bo-ByZpIL7EL6yYT6IG>x zpsh^pq^}2$0|zJc0hz$e7aXrR{n!(`x4q?ioH2_NA1oTp7A@sT5v{*$k86;LF~F(5 zS(JDFY99qBOc2O3dxx8!at+J}Q;D1BkBw$L7pl#6$_(2OLtcS>nt1*Yb6BrfJ?+lX zpl(gy{9b4AW)8N#d-b1QF%#1|v=mP1cp?03{)Z<3*`go(3*JD-&z7J46~heuBe#GS zg3Mn9_W*h{GvG{UJA3cZ!g}+#cP4z=mFujeXwxWkW=>_+RnlaXWSSY@b&NtLBqNera|agj4JE5*%=SJ|&ikQGUVy-?=rU;N>ywmU?_)kkmqk!Z+8?Lf^^V>pb+FG=&l%(4L| zur+ThBaDlJUP{CeXbJPiFILtMu&=baXQQ>DSwG}@ix5Vk8=t%L}b z6xQqHr@wqDC#-NuPOZvT87leurSJslV9j=4NoS!hNYo*V(ism2f)NA71Mx4*5 z=6hdh5b-6x7`I3IKz#AW+=P?RC1T+uk*j2OK*8WyFw08~M0GFOC-G!;&pQCxFu13M z?=|h%lHNmQ!}Ip@!2a3Z|R|;A;eaQcP$R^s7D=|!Lucdf9Pa+j; zZa3rcqqzMbXRanQ8MP<1bw*z^+T;|xZ*~~7FL`WqWxJ}I|I6PN#Ak2h|MnmN8a;g4 zXP0ue24D}L*pJLz(SIVxj~HJaD@nJVWtaSUj~ArzXDGT~b|f;ZtKlKi@erT!y8QcM zi&5z@HmqhB7Ao*cy41fgh%du-pl3~KMP&wigMS3ITCZ{)sWeGfW`}erj!Ew-$|^t# zzs_<@6dh9n%~{oQqu>UL8>i)-~WFn>u3Nkrym9X5tDu}F-0 zaVh^8rd=ynVY>n>@G?$k+n}$!>K+*=!!cdbKmMo;S;jPKg_L6{g&zY|(16%pJwwRjTR4A7aKhej;}7~)*I2u$ zf+Yl!X+GCZM)d))1olRM1&ZTuCk}i*3ebqP*5>rkQ4t;lD0jjLvp}=7@QvOzX!546 z>-7rlgxUE5fdkD3-UDgjg~%`v5WfSMz0z36eLg8;VO&s2J?M12`1I{2N+Li`IAy-)IpOw$*BeMDdfbH1V0QrfB)6^S0!=Mo!0Sk9>JEv_;2bchy3Bx>{tCwpNjqe>6BQpPW{l9%i)e z51#dr$4{NxfgS^J1$RoV|N5WZeEF zhVJ0I$X+YqYXcM8pD7gq8YkXUIzx9s%Wpx;Ro$n$_VvhGZow1xLRe!iZ)5IPv2l#D zM&t2Qk6u(;;B&j0t%5~zcUYnszkN=zsIW1W%V}z}pVGnNlt!euaN;RIRenHf?;7$9 zI5J#)?kZQX!_m6Qaa^UlXMMCk*&;>H4UoI-E`FEO=7(+YUyX>Inl(#aZ&UR#*CVPI zi3$#iaBqEi>}p|(t4l8~^ZHA?JpPDoF{5z4*iqNoDe02Wu6O6D(U#!`#>=i|Npf8t z4@0$Ut`|mEp*#>t>ZBQi>r_?M!6i5w6{xjln$)n*bPL%KxO66&j=x@_`_X&eKS*&; z_vG-DQ+qsjwZ)i91Ae1}dC`O|tHBumM*oKaWI3)@+ZQ4(G%23@Ozz_t2M~<%3hBwH zPn!jpIHZ=^ppULF=KEq1?bQ**k7=_);bthl99V!WM%vVguerL?TLW&oUy&QyXHW=J z(s`(=Sv&v%#Tbw<`W1kq6OmobSkR_7$VuGyHYZVB6f$IX)CePeyqlOV2*hV4TNEQ2 zCdjZ$Mt&|r1QtQQt@>dGUnxCypU>4AlKIOjlO>+hp*%Iiaa!)JEh}yn>PfvWEbz zu&q-mZ0M`bL6?KL=+00;y0hN) z*oXh>C_uUD&gPe^sE&o((lCtm6v%XKySo<4Or{F`q7{UGWat6HT*l|LX5GQ6%5%*c zK~>N_%Cu3(Bb*6aDAi&q8|3A~3hHS$IH=T*KI8u(MPouReKd?xpU>MjY*f)gb&ax& zo`Y;iLsP)#pP;4B9f~wsO|npnwtqLwuP~R_{l|Li@lP2GgT$5fUueO8Y3^*=UT_kz z+Fy%d(n2+dw*7#ux;otQ_o~PQs}B^42j6%z9k<8o`g`qO8M7JJOR<2t%WVYZ@}lQ& zMzhEJFSt*|o@#32^GXe(R$=F=9PhSkFHe}$KMeer2M^ls@{~>O*m&No5-8L3z3R?D z->Tc|y0NQe5!)ZRgm{^~3ImZzk^6uA`Mx5Mw0LOPW{s==q)M=E?vZ*bDX_!l3ZuR$ zs{FTLN#8|Rs(Y^$PXuW)A6NzOEsS%J5o`CgIF~9P2T^E%<^XGm4mdL;BxI!#D7q^5^rei-P_wXuLp@QZ8u=I|pFc;UdnlkBg~m8g^mUwhB$5{du(gSqkFor1Doz(JMG6X?hP{xUeS!{hL`iqh2AQ`pO3E1X-w+WEXvC;RVia^QgCSC9v_sE?xvY{_KjEY%9y_?- ztXd$%KWN#J1I0X~^DD==8Dxg%mq!V+oYAgxCLFD@ zHy_6gZ3fX!ds&VnZ_=^LH?iL>pQMkUstJP|A7arRF0D?3%DVVjsyU;uQ(3hiA@o-i zZ`Up>$Nu4LGZ9Mk*ZS&|g^qCLNzn=OiVoz2vmbSWjvjL7xyJE04GB!6do|YQOLg3I zl*ESY;R&M(lfHuracYfYKFR*oCYti`ieH4s^Kp6;utlgV+9W9Rpn4dyt3j9#=!V?# zQ~8~Ut%47EEerFq<~<|&F6Fs85GKjoF=ufcLtP-i252yDp`?Vt_Hr?nZ?kG5)o@XB z!?Uib8Cfek4c?T&`;St$_azs=2N-qxUfb9_FV;ZOPB$k5zjnF3sb70jK9i^br({AW z$?cL`PXPf$ZWw;naQ6ui%P$SEL?|5ZSTde}Gw8Gyx}lbIF5c67dUvC_xYm9BMq{I0 zpxc&~FIE4V)7i|L-f{Rikhc%a=K6HD?@b3lwouXkWZ^_5Aiw?VI-7+>>kX|QP#>QH zkH@J~+4`Bpt3WYTN?B#e^qZLJ-7LR*8tyll|1_(evDPF5|nsCqh@Yn^m|OiKI^>QL$`|GjdVJJ-K5SqYVv*i450D)?S`o{r$n#DcE<(B zm>2Z10m=OlZp%^UV%jAW%^cF)dEe%Hg0!dK}Rq=U;HZQu|_8a&;?eX_P&Tzxpcn&M(PDO8sSdq zcr)2o1JmFyZAF`F18?^C-I`qNVpp)#=5}=A_CY(3t)ZUPheeM+7#JJXjdom+)5)z| zi#lkDbcwlV&WATY?Drbow;1m?5w72Ik5t%xz+Uld$R?)lp#WfP3#2GA$-f{nStbQFrXE*bumGk}=m2S7R>_6#it55!fZ#=%)F$#(-Y z!+pxVt%M=VdBTafngoBIis{HFGM=IA^a5(5&OIG9b$U!{a-CU=K|0u-+eCNhY>~-I z0jZ%7Dpiai>ygRV z%m{BRbKk`|cjxr%GSw?y*H8A2v^q6pp_Gu|;JA(qp1+7}Pf z$Yi2b^&*=R+s?%H{&6OJZXR!B&(C|10KTd(4@4?03ix&|4wCad7*?;W<+p5D9Ph2u z9-O^tZoE_VpK9#TecR?#*hKH&wXOgE&nON&`Hlv}ZdFqM<9GajlK11l2x-6+nq zoLew;@D(S$W1o57hAA`KqLb|W5;B;1Zp};gK#O3-U;Hc4Oh|2M=)M)f{WVwXj7{M< z_4~!4PPdm{Nbq-0&u5qjkB0spwj%(?#6GqjFgI#Sjq1z%4OoQkAO8IDO!w~Hy{CLU z^WOfp1xrYL>WwM0MV|$*K%tJ_2D}rids*S6ro>gCiR5*WuPO4H?tJy5D`*ZqC$u>8 zs)hRUgtb(K$GXa;B<J{R$r2%i7N>lW5zp!$v*4)Jg7?A^- z@aH3a4-fOt0y-+1SBcJ*8Ug6GW;woMh)+@7Dn}H%Dc_HToJq^w2ksGes->kEN9&*N z_Y)VK05xghwq?lDLD70$kPg$&!%vmndOb*%`du#E^c-_Y{k!A4Aswq^x-4$N;;}`N znw6yRd|`B(Hk$r$d(Q8n&@cN;PVean{4uJ{$_AWg%J&m_Mhf)K4;F8Yys%hED2zTP z9%$((CkD;OK?`05^zf7KM^@MQgb+v+(dizk=?@Z((S+#|ypb}Ke$ zPa=8a7iS3UocQz$Rgd|$w|TZr{szI&e8CQ1c*Kr0E_3ky3m&|q18znd_i){JhKtu5 zQgt`rp6T3#uFv!UK~q1lkg?k0L4&;gCa+omNy{F6b=~KTt2TUN^IvCsO!N8w;OLmk z|LVUF{z}1m+i#oxw>XRTo|Yq_YT4GStbIKSQ?5?LJTV`9Vjd-vzH>uX=xZLBoTww` zT)Uh8Wbh_vELmac(nteDx^crFXsulpBb-$qm){u)9trbb=&neV}M8D{KOJI916F^+0S% z06ycd0B4a}lNBUnXKk2$)Y%@Ph36Zz-fc9A_C#lHoM5d$an}oaY4y313*Mrb-s&xU}WqWU5JW8rB{vvi;BISAmcTrL~a^(8tXL)eS;718eP zd1AE^DDnLK z4Rk)UF}7yMM;C*4+Nq1uJ?C2xk8>r|d22p0^$UtWMXhulu#KViPjf7g7Wpyhoo<~QH$^Zmzrke8-A=863P z1_2DlvbjS9SI5<95t7fzf|MSsfD#UXQ80Xaf;wX;S=f5d8mSOkrZerK($=!HG99#! zUxnQX?JP7Ca1U{^GePz3 zTL*Ry#r4J@pp`SKl|Vc@nf4(TFINC`A@uJ5&w@Yx#m2U&Pfm_k#CR`4O2HAS(HDOIBZM@Tp{@lG$>9CaN(80{Lr2*czXpRR0>(!t6uQXFgAr* z_fb#;0GoY~9`uoaYHhK#C>5Ml-lBm7#-?_!zE}-CpnawJT+zNMswTufySoNJ0)SWL zC%0EqY@5Ku%YthgCPNv}p=pDL?tK2gW<3(+-cAC0AeP$!VF{To=g1rV?`~Y3I3J^D z4qr!1zwY&%pgdo91iE1gH+#o|Tb|y}b3$=0)j9e>KGZtdKvP%Tif*)bzgf+MUzo}n zqjSeIfNg1iis!p~^8abq&riCMja6tXY4|g58@4H0gkWxm%c|ZN9ucnJpsTEYcm+KW zDEH^%bTe3HYw~)V(4;F~_2&2T4e(EJ@8^&yD)H}qeBMbNKJxim^h}?44StSS@7KhT zB=1Ly3=gFx_Em@T9*O8@t*HK3p66g~XQPT*I@#rl9H71s0R=wImGI0@cy^i7{93Je zHAYMBiN)ZLF#C1OT^BT+N%4ei+>%I<!V#7>?MXYfq{ML-0qb_?sgzVy!p1=LluJ z?5xSJbD*jzszVqPtak_aQYX^2RfP(?)!M*+iQJNp)4uKAIB%)AI`R z%G^K~L@Nc-?Uav9WP{Hpyf~8(JCJyh5s?&m;R@?7UZONv5l))&-xTkD#_sA)p#(*6 z?al3t0v!4)QI1{1E0XmPe0yqxgV7i_Y+z|(@vAyl=E|xV^JJJ{0J1k*LD;a3Sm+Mw z?^+=DV}U${>^NZBGd3$}CG#_CUz3=%79Up{@>N5hJzT@H&*|sL z#_3jV+tss~;~NL&K>(H;6anyHxPSh`?LvMlz4)K2ZYjI;&p_U$%|@Vywpjx>|F_s2 zhmIjlr&3zpYv64(aC8Hnz4)+Pt;W8KvKsLQiZA;#4xaxKF?Id6p@lRS;a8u9N%Jwyr`}zA~gJ2 zw>|yW7iu!FHRTt3I!Te-*H5;N2F1oOF%JFg0Sr!IxdP#w7{sKh!YI@OWH+xWb3jtDANrbl6j*&pP)=EyeLuvlD3Ak)UuM#x75d*B&Ml2z;-g@;@lhK zhH6O2f`eN!kSC_qCGX?R`EL_R5@%TZ3|w(lX)lYO86Q@6vTT7As>J1EUN9A6CLGeR z7!bueNj`8jQ5*Mvc$(TL?{e&qZxh6fB>Ll}dSINhZl{ZA3m_{;{VZ?VC#iEg(=Gt1 zocZW1fLP6eO=l@*|0{>QZ(Y!&V6Jg!6 zsS(~uHVz6BrC4fuuh-y2x!Zv9z%YwiKz=iVv`kI~^ST5q%i;?AXW zB5)n|`4Y$`F6g05Y=;n&B9$LEwN9&>U&7Jiz~V5TlO}Pz;;s5-t;rlAKT0|<`GQAG zZswwTkYSuj8bZ>?LZXiro^-qM#@}3n{Vbv6tmPt_L*KYw0Z~ z8k!G^n!}nJFWL1Z|pxeZ08Ye@%(;s zSDUCMI9neGAi|To6k|QPUf^Rgh>!ScVg!PK$bAp$h*~W^&Tw{cL<#+s_*5^2=*X?m zw;m^llhn)+fl8`h)dYTyw1DMX`&*(xQW8Q2$!3!;;@DLiU4lz$B~~W+Vr3YnJ-&0H zDatFC(+a#XZI&kK5i#v}<1cfu8wqVMo&+1d4;Fe2PAW=#ks9WjZ8`Gv7hColGkKfX z_FO_|m>;|PYY_@mcqd0W$My|U!zuE@mWnKzqh!-a;~b9~oK?0^i|a;*P~2x>bOvr% zZAD3~wm?hRenTJxryI?Rl%6y0BP=Hoey+}b7^|KV+AzxzL%{q4Uc-v7|P zO4tA1!o8^K5LbBGgBzW=NM#M-LKD{6NaTaE4CXQDJ+^m zd=AVAumKFA*6cGj0BV1_u_)}&=$l*NA9d!D;xBnRCqbNlvvS1o3K&#eA)$SD{Ub){ z@?pKza?Ny54l1dqWRs5&#a7a&-8284kyRsb|8r!OF8$EjVAqY%g@zG0RF~PNnNv=8`-xvc+pVxXx^Y+;;}DhOK$?5obDeUI{A~leV_#q z^$}LHk_473<7lB(*GAqc6T2C9war9%C4+M6J9sH>+ktN^+$l}JOm}%jje*oVR$pR1 zvVU1#ekx|yb1OmAHT)F3mp7877NQgi=e@qy z0IQjVe^|DL-Ef+UJH{@@B%PfTovePQY9(EjuzB7Z;ezeWTJP3YLyEd;qwA7?W**=u zxA$}{XRLRo@<%>xW|;jD;2=X#o)tCzCZ$+z+d^!4uM*4@xjqFAGFv)@gJBKWUm0r< znA|K3no_z{r`eWW`>OZ83TfLz$#1?)2WpE~2!$a#DKngl#~C@6R-uha_v#DOF;;#X zsKA)TO89h${W=vD;G&!S82$Sk{h>MxSE+r5W$qsoDmLIt#UJLT=v8MX zNprDi=I(bNfwu2h`4oOzG+6$P%1RF6$W+ukceH8C5jD9!4a-1&*U}s_(KgP>m9l#UsEh=9Wo+#q`(__0 zo@B9#`ZTA5E}$Y%y<=3G%MFG?l;q33a1AmG^Ao;)h^)oUNM}BRbVm*R!eL^4UZ9zb zl#-=4l_ln%ai$P$D=#4QOnFJN8k*`#6L|2d$pzhwR3csgPPlJM!JEYc<-J8b&1o&e zC<#<#+OrGZJGZ>ik^A1#2}jLdc9oBInz@~u;pWi+le#X+Dc_lk%yqDUk*5IOJWZ}dtFz7{i4_0F zyQyu*LST#SX(0adc17)1T^P;~L7Vl=D>9k5d4rIzFosh7j^x@k^?NS&w)bs1SZ9Oh z=>H)$C7zIfzJDM6H&o%nzj=5{Q-9AkBo$l4;pIw+%{>|P8MBtZqn5vx$h6NT@Xb7n zq;u8RW5l|1Hx9esB#ld&QZhRB^!<*UUO0HB(_|AI_NaQwdqo!HctLo!DsY9Map1@s5wbt^oMGcE4Db;!>=x(l)4SDpzE@%7*$S5>tDW=RP5*oA1c8dQCH;d!ZD1el{f@#>+yTMUEcB?I}ayXkGoPb(3;h%y|+?3MyMcG zt=K^j+xMmC{r>zu*XNf%U6*j>dcN{{Js$V_{dNZv+>Mk6BWZ#l!`S3N#kaIRWrjqY zEEtWe&P!NY*Upv6+Bo>!!bN>$NNw0RO#N#7p1)YJ&oO6}%36EBj_6HKx>Z{PeeQ7W zDlq|wCi9GIq)|+Grznkhs(L2cCe^sg*}9iY4L?6TJSgy>5r%A~c}$$C6N#PgqaMuJ znc}^ntW2UE?9ZBx%0Z#FG@{y9(Oa@-SnO_(laJ{$PlMv_y?g`vmzO|37zmml@FL_C%Kn@qKR6j8!PDOXfUo~nheA@k8CMEpKs^+T{+an&0(N%TncrnH)X1G?8CEP>V+WBqG zpM87+JjojF863#5oULPeqb)y77kne3BHSBORN{UfE3(8Eu`F=L0Yy10WA&FB$XQXK z0{0yUqjZ%$*Ovac#+rY$;ywUq@Kvj!V4^HUT4~1dy%~89<~)Z29037Ku#=~Ix(EbI zvB0>l!bW8WalT@|b#V|#Ec49st%!nuEWj^$O9q^?o zU7L8hc?Y$c#=)VvJ>9nhl^YZxY`s~CE4*Wsyx4K@s>;<6s-wS`<0AZ44@1=00@)eM z#m)x3v||009b+(G1H?%)F69~3yEL*|N`Lt)j;O_lO>R8-oaU)r`-^&&z&Go6thqcP z&e|DaGG#~;BrnS1J_Ol6(bg8U*qz`4ZTqfnSFnfb$S(peYmU+O+{3J?T5+aZe#xF? zVFb<@h3)6aIUapqJKL4PH5Sj<_8YVy0gX}*O-DZYHf=K^oo7QXy{8@31D7zOb_l)NfrQjcXFSws~_B!>lV4WQJA~z zf(L~!gBDIWTpW?z`Z}gV2&SlspFAC^6h*Flefim(tz|p8DOpwI060iyTJfWsrmV&i zS$Held4Dt*xqMf3_b4467$GTK{MO9XPOYf<+-+QY zm?+1{lCE(#jOj*-+hl;zk+;fwXkMvQ{_cWiW}R(!!mlBkK4a1%`U9WH?FuP;`iM3h z8MIjS7;F$bNhSXHuN}FcF#F+p1UTt>q{B{%c|z{?n$t$ic+W+*v2;p~un(mQJ1i4B zm9qtN6~*7D6OB)L^jI^IylDEge2MJO0V=M%__16IaQOyt0|?sKU(_K~BQ-kQ zY28ulc_y1(Z)n@4wVm;lh|hE(qdc!g(i8{~&6t_itBCaQci~{V{aYtj)RwLcf;u_4 zj8b4^XZg13o4oiT=G0EVRi8Q8gMBTdz|DwyCz;hN+tfVY9Rdfq86sweAFK30jET&n z5g(+f#9nF$_mQdcmUh>k>@Z$IcX7r3P?QK-{Qie+GG0lf^&IdrXss-8NQ|Aqj9RT| zk);?gUj1|W3(HnQ5=u%Lega{0TTfprjxBoo(cBuDJAoH*KXX)g7fbbaFZq0)9)pGwSOENqJMN+ zAiv9bN0mVTakuE;n*$h>goy2!&t+zJa=uUFq1@BPwgZ2dYQ> zeI+9`P=3Sg{z-=0JLuWFv$VbR6M}f#G?&cUZ#0xi(67IE|FfF7V^Z9?!wuS>5)Ini zIkV#kR@Mx{nvu(HC3|qNHC;sG>Vw-i36^hjUABVYlvqOgvyp1*f@D~3%IZg#zhr`UdZrh?f6cwjPA!l- zRbkO4rN_YJSswuF`w za=B;g%2FRDuELN7>w?+%K%>j+yz&xtccTX5 z*ITUR`ZS{C`oZH1(M8jBtP7$9Akc@)-K$&hhAqI*O-Yccg?2^LFt+XbLLcSXrcfMh z{ahe!!qAO;aaTF=j2j1;K{b~R-avK2?Ueese))<_-9-LLdscdGyaQfV_9lz~bmil- z-(a-*3;%=jX|}40IvCr~IC4VUEAp;0R&nC)m@a9vpQY5d&WCqq-6iQG`qll_f&(>DK77N9BPd|Oc_ z2mAVizcfjWb&Y>Bit*TdvjBwQY4jsrdo-;~EvD?z%2gdix`tPlMPEa8O%?YKPBeN5 z90eJ_T+65;%6~SA5w#{)N^HjgFlku^Ny#3vgD4D3E4m2rIDi=;aRzW?UUNZSYzXJGd4^_uGhkrh%mHB9ne9LXyf951!7%LbZXIOvIAZ_Lj0r9f*$2T;Jua#+Hg8dgVgc+vyHR8 zzW&v7DYB9N|3(Mj;Umr;r-M0pr)1iXgMx=n6Z^-xA4DXG@aopZAh%Bd;bPYJR>6T^bw7+xp<<4M-roPx3*D*xY`VDha*?LI(MovE%3e6_2$f>`z=t;RP{(^P%jd)vMgKVgciH| z{+BAG9UbC`?hb3v&km?h#TBxt7O>11Kl3W~@00F7@E3{QZxNWWUZRO$3(Uc!aJThj?&L*N zwFTf7SbKgUks=iFGtTe@5|jpBT!_1hLO3@Xow3{W-qO)_H$(>-1h~LEA{;I#)3J-| z?R{24h_ZA7y_9FTQ3vi+z~wEfobi22^Ru6%;k?=*RB%-)SZ?IQcIn1ycV*dYsq8)W z3+eH7IX*5CYjr!5YdD1~N=>NFXQvDzv2)usjXS+}4jLUX$2asyJaO}j>T(pTMwf{N z`RD6?qN%6cW1o~r!E@W56HCd+jM?gvm2NEw|`UQuAPW0WgP&4ZheFV*cjsM7bO(D_swR z-D)KRzb!k76N%Uc^yCEepl0}y(8ZIujGVooW2^`pR+1YVos&VFvtPznNN$y$N;W+x zLg$$f0nOVyJQ-~@13scni(5QnPFx-A00`Dh>%#|AH`Y*?iG@2OZ{)3V( zA70HV-_F??lG8N9%f9~5NGLP(=ohofCX0t$zXbVeho)Ih=cx?~`gO<9xUvg@NoxkX=Td=eJ^ma1? z5!V6YRfWwqKi+U|u5s(I+4GJsR`A(fV|{5*9s!_PZy0q`z;PnSS8U8X@nw|f zZkKiaxjLxp71Nk&eHQcEjlcZjsvOIP|2m$(iI2BY$dRr7C+y5(1E3frvZ52g!HLP`+>(}r^blzDmAe)@hjZm&_J8#)5nrQX7BEZ zst&>MJ7495xEiKVxfy*CM>ocLx~`!K+{<5L9E<|fLb;zn+WGyIjfyZa%Lz)5AI=4> zr+&!X&)&)-#^vpo%w5vrM=>F}$b2ZvlozHbEzzr4%5AIOT2hd7AkJnY%F6G{uGbZG%OQ z4f35mQNDp)^`F{3OXdGc0|v%a@k+Ni$RN(^$zS@3yDb_uTF|15o%7xRd`Js2w?QDQ#7)LSWbqScSUs!b!1-z@<%_}`_Wz^`71Z^%N;(#GvyBg! zgAvU+zG6@~MV4~%-RVn9racHePd`V6AjdHxbEod%dacRXtkPMD^3K`uaa!(wpQYu0 zvkT9y`m@F@=S@bS{gbWfU^0NcAXQhMd9Zj+KPLYKV?{57{72jtdxw}}kr>|>*>x!2 zXGh-x^)1uHM?MwR_zHg#7eYZyEpT55`9OG4ilG?#IM~a1^z$~$nJT>x`3EwZ&qYbZ zryR04;L>SgaKKJ-=7|3die0|tW|siA zEHYIz$AZ~X5HRmxw0dAh0TCb+kPCP^ox?rTbNx- zU}tyEn_n|SN`~Wqv`V~$R&euTN$)uG)5i;cDhY0WzW450zw_VgET68>DiGRuuO|(? z@_QFfWSOdQuhgMYip5HpMXhb^`A@{r-_^?S3{)|wDb#rJ;(~cP$$uU(Zo<>UZ<%!5 z=+fqzpT4HdkX3om^4*jfOx>pbP7nb{3~6q138;e=cr+5ZH7`syCx?Gp)lA#*iR6(H zf@}@6$cNDb$}_<+L)tlVI+TPv*tynD+cwageD%cLErhPUbBAjrttFW{(wXgmTPaeB zy7zvYAJZJpFLKgamJhr294Js&zbb2wfx)Gq>i3#HhlaVa?-zzn%36cDRRq3Mo>XJG zpps&PH{-iTcrVZ+Xa=Hb?xdj^GpDIP$S?4=)KGy!#rB=;RGxKo4e2*ZL)^GzqkBiB zr~hh@dzg0LB3s(?I4$qCy+NeQX=fBv$V{1gPW{@?9vUQO?327WP?5Bz@P+&RyvPZE zU`LyTvSW02XWpL9I?J)Jlt-aYCYoHz|K@ShiJvJ#H{A$bj&5!4Ed55w-lB^F=qp5U8_TL}&LD5?1d zzOM^XqN}*$LFM!ZhzPJCA;*8-dtV9?%vSGVDX_kYWoT635_D+$HMo&#NRCoElwGdn zhgcCn#g29%E{s7a865aB_`l#RJRY zC~1$G@i4KygHiWJTiCp;Mn(oe{*baojOKMZzhe~)c8mAM3OzswcM9Ou1nm(E{_ZHIa|p}SA3uL?ZuPkL(l!qrW@056zS|z zDOcoO`!?pD@7m%Nv?lalBZ1uD9q-(h^uvB;PQnDA#cs*HeG%tWf)kIMmz_-br;f$? zw4Fp958xkiP?O;cPNuERJ`N|R_x-6t{J0%QduV2{SC^UXQn;I=aiHtAVXhnuSdPf*4*U&nrZGn*I5CtP4AJuf zONX4?f_HTEcjP-)_Z-#-ucw=(8VfJT7v(J@M4gLaoi!g$VOAA2_`l*}1`AO}fe??n z>piK9IsS2osh?rSCr|r7;4qy|3xIuLmR;9Q=tQIvHEHamRnLXa8hV@hrF)m<@5WOTGX6s=9X_&F?>D zrR6HptKO~E)UkJZ#Uq1BprWLAWU_O+;^P~eMxLO(+p#^(in#ZE*hSao^`YUA@FmWN zg@gqBg)@W8+iTZHdDYUzm+Vr~7@veEKaI(2;b zcCJHP08GvWo;BkJY3gVizNXz)3#iu^IU#*@rHV55unouLZV+E-eT|NK4T5&nXJ|A` z1g}5ebd$F@BdQX>xX&C311pLu9cEcbZ#=sH%3HW}lE@fmPr>DI@rtU#v~V9gnavY$ z3l!7{Q+D5$YQOuK;JA&6-319`rZ0vbj#^HkSw`Z9QI8>C^37T6*lmE4sO(K44qUqC zu(5(a27fnpH*QJvpmlXS>W>K#?x7&wK8Z1lR2jEIU7B*u&K{(!>TMbO4@LIzd6t0V zT+&BJ-X(t}KV9>J2+JTlm1sma{{u?}Zrru1hmbmc-T6%+Ba6Vw&BOJE1KEx7VBkgr zUzbH&Aelea=4r1z@<$dRXr1jTICzTk>cOJK)Fa@&*!Y*#@!_EK#e}KL1{M8ywF8SJ zNT0La!s2)9z~x}#?BuUUHk;@y`zOG2Es8!-wBU2+IY8p#`Pn-^iN7QF_ccEUw>~ES zZMW$TL|GZzGK#NRU7nf>9=p29Dlu7`^eQb+k!ZFE^LF^+mH(27Cnt<3KW<~7N0wZZ z;8(U%w3h$>1 z!GxXeipG)I_g`M7U%%Ip(50VB(?qgnmr1O+PHS}_L>|B7Wsqtpbj*C9V1?PG{%~n)+4-OD>0grb9Qn6Rhc*^={ZdUWrPn%+ zs9@Oc>upkQBSy6r1U?J6yueUr{6F$JFFY!3G%?11n5E#7y0b@W^yDQN z1(`iFn|>lm_)y;RjoR884R!uVxYoYT@>V=fo?Vgy-`;AW^#??En{3XMJ$(T z`c`|ZY;4YX#ut*sTm`;QB|GXd0_`}NW0jj} zVI?dhIW0_+Vwz~?xe3WEk-*a?mq>w}x4uHD3QEJXUccT9WS`oFf%{n0n5!!25n3v{`P zSUw}M?z4%|ox5qFd%w>$_YzqwH)Y)T&Wn80z9v-R-EU`J7V&8g5*c|4c?r{v?~U2v z(+|z|Wy^k4v>5KjR$z^T)va>^pK!?t+H}dJv!@-QhrabB43kaPB`lN@0V@yR@w_k8 za^13-sFC|lP#GpPbkLBPVO(l~n^>esV+Bo7eR(66x!!o3T~8o#`3B$a2sVDG^4P{?m+)`}cb04~C~?_Wehuxc9AU zukCw_-YQZWGjxtFr!dPwFP)z8{SE@|m7W1v0_n4h45tgX2mb*sBmRHO!k}s27XHmn z{rP7R%bWq_T%0+Nig$#+cO;z6fj1cm$;weoR+mE&3~Z;=AeD0Eo1ry3VNC7{PWFb* zxokEKn#K)ROA2F2^_;TN_NcwcR=v5@&U^W427DV=rLf^X2Cu_Dta}VC&vfVcv)0&hc!U?0iCft5b;}tE`u&{v$ffz(XddIl2q}YTEaC zotM$~88)H7!H;9tA{%b$kp&@nAq#MZd(#{v>LEAiUb`d81+{b+40a`2un};sl=N%y z>nyig01(T7g^bo~P4HSQQYb36)3G*iJD@S^;+ojl2Ya@^1peHg^^LfVzc!bTycE|P z%fnhf#`Or-8SGyuxAie+HSzLp>CG^{<`HXy$o6Fqu-LOiK_iZG8~Il`mV%!)5fH*n zR-p-NzAlQ`D8I!E@l7z!`WwfU@-$UP<=kLFIyw;A*}%3LW9~!c$v18%Cbn^HBrOIi zANSl4eTT^r)6CSK-jb>mImQ>K7|j=P(RSkdM>U3PwCc8b;_P!EwKgQD6m~rbisc$~ zk25>=3l0CIr5-BFcR~RxMiThrq~ChBRNTl~qEdiXhu^yhnv3fTV7ON48U87hMfASV zEJ8cG-1$nV+NR=)!clskzd*>4ELNR!$oETKcBmW2eGSvTu6z^CY#(_8>HC9e(qEIe zYBO9ulCjh(BjiQ)6&PAy($)-VV5c1{_fi=j)6X(Nj#31gPo|u*t^C)5vYP8f+`I-Z zwH44ApqX!XD|&EsBA@l&5Vl1Hi#k7anIn>w1tHi1VL_RNlXq2jCwnCI_gMW;B?i1I z@x#G4Q;FqUYPQbst2X+n@QC`@1wXadm7bcFKM!$zggDZvQLBST7# zKy2AlEpCy_cz>ZpyLu%1sE~tn>E8_D`9(oFhvfmU6Ksl>)+DwydU)EKusAjTD(}bPWuv{prn5=vAq(INnbf5r9=N`yR4@DS^b2| zA%-cW-S8dfdy(qUieIXZpqT~ZU|lcST{Z76ZUf7n#ypZlxB1q?xbeZ&1sbkDEo&R; zje0C>-~D45&WfjZy+OtNBZfb-!GuEAj5Fkul`s`irgqNKQWg<1qvJUo^LF8oaZ7ma z5u)Nt*oDh*YCh;f$)G_1k^b7ISuR!5H51K@Fr@iw2ce)Nv>0r%FM^!VezGrcn->Dh zpYY$2rFgI#YrFX;1TZA;3`%9@HMyBQNE3Zb5O9uU>#~F}SiZ^rzz6HfQn@Nz#6a??}$-a|m3q;+QteJiGc(;>_LJ_1$bG_%Xr8;2K~!1v%FHYwX9G=Y4kP z!mhLM=05cX_%Emrog3wJ2dkO}H5{X@G%#+iVS zQa*4PSjoCKpcX}rqH3n&hprm3z^l#K$3$pt@`kgpM8zvPz70XULDfo|0{MXl~$e-+s!7ILdr`iM^j4F z)g2#9_d+He*u7JSaJ1kJHaDIbmJ=Y2zVvhjMi@}>#wjjz?#nHA7EyIW#3)6Q+}m}0 zs}A2yTw;He3I~g5XJ$+{p*9lPBmPK`dGGA^bBTPgn{bNrC{UM1wP$O10d)vm z!KdkvuZ9Or>ILNT)fZ)Hkxz-c`@U{^L1h@dqQ3sT$^(Pbq{y4oEkEim|IG6BsPUgK zEar&Wt3QkC>A=$crqyk@13}00b<6vR^On*JzhOsr?jUb?Z@>c`(~8P z6X_z~-7W5!?JfM@`Y-fXk40p2-WUF~*!~0nh!hMb3oAsIOW`*?0mn^VZW9xyi=PYo ze5$3~Zk1+e8s!IK;biE0+?q?Naj{NE_S+iQqMtw8`(s3%n_L{s%nssmkAx8LG3F}4 z4&;{;A+&Ex+{j_ixZ=eoL)r*QI?!v8*e*NMKq{|CHFK?GwFzjwBt6_|yyw~@ZmS>b zh~(i@*8f31eoSajbII@^p>?Pyef^noXlv^=`QJ7aK4cGQcGsqBFr4>Ov>v6yC_S?c z=5S;ymaA)DA1V`{Rn!Yc70bcy_NwO^cY718HH*ntznWh+8Tq-RlaIMpUgNm5w_Pm? z6*anBF&w6c?~~!{lx#>X{Nl>#O|%8qa=s;lf0h69)DG?tNm7DJYSRh z9tu-h_gN+<8>N+ZQN4p2N z?6VA4{f}&vJ5&6m4k~C^L}oDrTon&3FFDa}&Zgs9PHSDWal2eKiQVZQlHD^_7I)9H z!{H@Gy9}%3nkj_x8;g5Cvb#j2I=ck%l|!Ul06AUJZ+gqp4XZnJ1%=4zPfpB%2Nt|c zm&xahU*$)5ve)H)?K{d1aM_uvv6K(v%#t?Hcd;nr@285L8eUA8k~!<`h$nq=Xb8x+ zDcptYQd^Fo1`dCnB<}R#pS|kw=fOb4@cXBC9?zZibbSnjAk8T_-7BARECL8GG$d$E7jRNq_D_6cvZ zL*Tb>nzr!LQxTedT(aL8dqmICqWx{b{fgQbW#3sJLZec4MY|lMJ`-tvv5FV6tjBGN z98{>g0-9IU5}tlj>Tnh)89lfi`xE9zFk}E2Xun#1@8_DF z-CK5MMLoa1{qowEiXZbf8JFzWtIg*ZFV75HCOHG2vV%owOB1(ScYjqSqEsM*Wr`d64Z1l#f9agocsj zKQ8$h6oj>WcM}oFggO^^{5o1S@sQ1+Km5e;!ZbcS5Rh=z$|5#tKWKa0DKl4?cU%b# zl38SJY)Ys1V5*V>@&%u!qh9-_01cSZZ@JK9AI*1$>h%a(Jk-1Z-51~TYvm%K7MWz4 zuVz@m_-*|o)}R-4lDm<75%-RW^J0|z;mUGT6~c#R-l>IynNy&?h&M-S+w1`^O0J~$ zC<(4yb>HJ_n&23nAOsZ-AhwQ#RC!mVApS^hQA(MY2THwZLa}(bf3^8*+@>h(BWm+b z+o4(g+Wj>X+Jw3tpi?Zz>4~#}pETzeEn+C!T-;}T_#V!~^HQM{+si3SfE=g1*TiCX zT=yIM-9h(%2h@k2k>`+Iy5}}P8YTQFd_T2h|BLvd<@uO8b6VVlu#T)D*0nY)p*x&B zCOg(+(zE0UkbsX36SI3-{eza47eLvxb;FwYonC)A{9k#Mif2BQQjF%_996z1_&)E{Paebf3!FMLLeC{o3tMh zoyYu@%gQ$FC^4T<~naHO;o;__7#f?Ro?Gnp1wIS)%1GW>XsiJ z!SxrjjBMa4>ye?mHCp)lbCn&g2nNHi@wv`o6P(ZYM)=)>y{PBd`6lf?Hl5O-Vw$2) z1RsGoC)#JGkGQAB-G1oqQ(OC8je|L~^j|j;+Q!WP`KlwKFjbm%@Z>dgNa_K+|GMY> z!Puj4q@DshGrgL6Bz5Gj9if^2je4$qoRGJ?p_)P4!x5Fd{`%h05b%qYEl0FbL!Gqs zXkM*Ops8WQ>Ucu#L75ZCY`G+wdfT3K;?=~qjOK}zLsMcijwUo(WtkPFrN#xG!jv2fl z{#}}>k=ZycVFR)K$H@B35w&YPu9zT@S?3PGpiKI>3Zv*-R)A-#@AZ?B#QTufOzv=Qn`%u4XVm!B6X>(Y zKnvv)FgyZWWZlbe{kCK}+>t}fi!t(2R#Jd^z;AJ} zKPDQz^Vx~u^hN4YyHC>Ego{NVVr95>|4#24N)`!%t86}L=0lJN>XsE9Z?4O_^bp9k z*$vo=9~IN=CkwAd$37sskoGqWABpVZhAP@ge@mnWrf*DCbg*oh8wRCsJgE}wu|G10 zl9VT{N@?YO{`xTfs}))3v0kUXuN&pCp@6-MZPKgIr~E3oRaDfo2{hKK02muYY(`L| z#H7N(-PNQGx9xP;u9UEQ%7(>JU&VONB(A|?uPk8?;T(T~k`|L=ZyaqSoRsccYPp>9 zIAA2vRYW7yW$x!8idZ_FZY7w9gz-PwPK_lda}RaTgK-M_g>_zi+9b@t8bj*0v;7vs z!?SyU)%I@^!0qq2{QCm-Q@ix?KW5uIjiXn_SI%P>WUwcTojL%8@{Ft|Nn;Uq*hf*$ zQ;5T&4CvJ1`wn-f;P17+xTLF{WEh$Hi@56c9xur3m-lrad|3=v6wMhvc-AJOypTVy_IJA zrab?4NKm)4Y3ozoJT?y>n>7VgV)&oi2MHnyZg*zhAF50(%_t}&3bTm9vJWgEAhy`v zOC_;wk}TpE#2F46ultJah3J?oXwqcRKj&Fa9BOAc$SxP**%xs3W2POEn@=FA8)@z% znO%ItOQ>g@%%R>^q(JC#l3psVAU@lm?Vpuh z0_@EUDZMYX7?!ExGv0enm=1wvASCD{w;DC|J3ekBIrCGw_G7uXOw9rrzC;!TJIXEO zbR^H8ExhrDObKyXRra*a-rxIEq={xG_hXJl(?D)qVQW-^N*o)&3G=UlI{Qa2>R`X*51m2(zzrb3)z- z>$Q*hkWINaj?wxfOfJG8Lr%!5w5ul)#wWR}wk{`Bn5chx7f1*yUaXDOrc8>DiDVTY zB$p%kCuqU#m6#ckil6lRbt*1BT^^}ymND_`B`QgxFXPA6D~EjF{ec3?0~h#Hx_P^# zwk<2OP9278U0$9#a;Z)!k#JHhRI8kat9Q#OqAYKj+T|XD#1HM^(wTEX-96T6jMv(4LA}bLmWrWmIh{S!1YYsoJSdcHz}~rzTBJjo%k1TB?7| zt-nzVX0vLuF1#`aUzP4ZBA|gh7-i{-<8SYQI{K>RX6hT-)0l9wI+HVvp|$#RIo4Nf%Y}@_>h&c;Uk>-2sqNsy{?WEJUM%R6yU z*jLS{&op8{IQrzC#xP6y=N^9CUmSIB%a^#RcC`37Z{_I6u$2HMyD2g5VKWgl9wARb zY(SM%6Yd0rkh%Sz51+94PKR?3oyaYCI34Ro{F& z(30%PIrMn?;yx9Ky)C(2!D~`|$I$-BdZ?X?J;v>2>{?|d%-)~Im4oFxVclNItGcSi zL7Phz$zkMGdw==Vk?qp6Nd5j-P?ic>>Iac369$LGGC8;2t+J2en-+9-7Ttd0FpoHzkw!kfxj@rU4Yv zZOL{N1VjJf>AzHQaq%IZ{f3AP`{s)q`Q2x_+NEZ3?_iW$Q%eP7D$FPgA-+bAOwSD|fViE=H7`lBD;x>aHf0IbZ^6~i=Vdl(t&PmG#; z`GMe*NQG!@f4yGZl8erAj(pBi;M7?v5=SeIU;qp_Yujdb+}Q8;;N5sH>;_lJRqVK>r9rUFby|FI^3V^!fHPD6Rz8tBMRLv|q)^`y zryx3ZcRAT5fEZGEt8XYBe)D;LOWzUBYZCwTBg$*g;m%H+zNrW?+oVX+5Oz{DC?&ca z=Ry`biG7TN;TH{Df_Jz6o|u|85Vc!(c>gu#3`8U$5np5!C`VsSo{Bm-G*XWrp{ftE zl$#$R55)`5Hsz|N5B7fHRSy?H0v2Ro#&0FxbtPGyk9y~ik>_tgI6{r}_w?ki0Y9tL za^kkC58Uzu&o{>Q}H8X#!j>0N#9 z+Si`2Uxn4XuB25+URqjXa}GC7s3CD&`;pcyI;FEG$@*Yq0pZ$bR8CqSavWj4NtDl{ zxkG%v4s(!T6vmrOTIP0#eO=TJ{`+f3M<3#1=~Nx<7tx^|>O5~JKtCFOf{SK6htbe@ zh_4y{^KwJp!VoLn?8_|X9EHAm%TQ<_-c{Rxy8nooTE%R!^^@vQG(K@yMKIDkM<1tL z-jF z@3Z&SFjJoIp*Ng+q&lO<^5~DMLnqe;rxim8A4U$D#DgR%1oiT<9Rccv#)({PeRc2v zU#*@o=WqOq=Qm$>^kMECzZ*RNdSB1BZ17Ikm2Z&a6Ns1mGl!lYs+UqX|Lh13>FJ0_p69!9Ceq{g&g)xH1c=B7 zW%0x$TS4ASWk^22G)L_6mtt08MRC5SkCKFAxA`xmQ#2NE0yYr|NzzH$UOL_6z25~x z8~MYl>_Q}pknO~}*~IbS-}OO3&b43f+8Z5x=zdDR5KE}kM_PJ=nCvFME}Qw(!Mys5 zfZ=L^WiV~UwiKP&2R|ZkTSPUwd-|QWb~(DEm78|4RZW*c;xo*4;nP65_|~luK)CM! zoflO!)hXWZ_{~r#kUINXg><9@*Sipmc}gd^jmGyJ(Wg_1DuSESzRU8X!A5(6J3;|P z0Fmy9fO#MAdu;}^{3c9Ssb|A&F~P_`2QKW4Wj!%Jo6+MRFU#m~NL4axUfin)D5p}1 zn{=V~Hpm?Mu52}&chSq>v$34u$tA_wbbOwj3gB3}w97yHiu(zhe)UMNI#&F zOS#_Htm**N^e9IKJ)kvxVRG?;xFwY*aKi0&w(j$62(V6!>WiSuhmFVVhn|cAQi)YG zJpC*Komr}!0*K`GF`ir&?ykz%v=X#Dl9SO=IZ94;s5&8u;IpMWWzpa0BPoUg|l znP23^1axafe9o1}fQjo4N*4rOqDJ3)}{ zu#@*)mSuHe*f%Y}vZ`UAgZBlicJ|oMjz?SP>#gaRa$~)hyi^4HrHst4O>g2-ba@v(TEd4_$yP9J7G|bkJHebdV!wM zoW4b%BukQ*eaJrX#zgP}L0afln&`8kSNjWrDJFTJcfOJ`K8;bi$7f9+TtGzJ%WKL> zD6Bt8{ak89Bd_|NEBMCtCmLZ$O!3tkLB!+LcsDT(U^Td(bs913IKO8y&BBsaI!NnL z76pzDXI%-Dm5iX_=IyaKx)S#FI?stONNiCecFwN+P+gbc6r#hjU3m%EL)54+AaIYF zEp#t&bMds_m2}fRfpSVbUtS+BJFH~XB>g}QQ~5JD{a58a1Lsrt)b)d4bs zMg^+V{mY|w&+vV*<+o(`Fc7?hl}q@7jOy!*2hQZyp3JMN4X<$|+x+!a$j^nEdn|J~ zy&`$qTgG!APP%>H7$cnR55`xY0)WMPs*UeQ&B0*vA4SI|M?~f0zARE&xR+ z`nvO$LO@_s(}w7JyEWXCc~ZNXq+Ij8RrvrMMtl?w{Vx3kOvg|K#9q9)tCRzx7w?UY zVm!8HkNO8O88Nj>TUoHBWjOUsSZt)ueF?^a z^*&FsR&WTpYFZP_1Y&16vKcS7aSfCGfPI*UR{$Y%7nC>^k8PUwS~hA*_MTC!-=FSn zLfVskBGeUEi#*b)n@>CxwfU-B^ue=d9>>QMU`4u3Ma{pe4|enNxAre{E1noLpSA7j zz#Y$qWNfCnL9N&Rn){GB;4CiVcc%w{G%Smy&LEpiTI!4Ed&f$bsrS`e)@U?p2LT88n~dRf=HL=8$4rBl|TZu4jGO}IvI1^cTPvqhnu*+;Pymk779)?y0X2jZXNJ` z&LMATr|Vr7Mv@k*G(6F`uNlF8C5y_IdUfsd-y0x?;wUu+T9DG!zPQS&n^)>}?Dq$9 z{k=I}L!<4H)OH+THmbJ4Mg9;Do?QP(+3cq;*lf_@V5KXQ;4UcWsWtjqBS+VsUx+wC z2&eRxODu47k&~W_g)zwY@~T<$W3XRx`z;0;u|?MQi#%rP(^LXVeojy;Q-25&`F97&J%a^>6qTQh^T|nMi&GjI-?9i)I@Ki4nfqINl1)7`h?NP z=);|Sf4_VG_gVMx#`1!-SjYM7v(G+zPr=;10zwsB>dXGwmhn+m+v$Jvj&iA=Y}a#( zt@@i@CI$7qqou#dj|6geye80(HrKugujZ?a;X6(I?{R~as3K)p1et{t-Fmx5#gcXR#rM2|U+<8iZ3O!nCR7e$D5rz4yJzWR9i8xKK8Aa5$mqx{ z`CsqPxSLq_QT`E*jNgM;+wobyHPQ%RNVNBRLs2Pg=W9YxC*gN243kYKfn0$<{v1h08 ziNvFyuee`a8LrNzDAN$?J<%qe^=!(`~>YUnk#xqs#VUb9WhNRYvb6rlP z9>g+X8^pyPR9QHBvk%%mfxUgvOp{=CX!sCt@^ylT!X%cBVV@ zBaTW^R?qPjTA(Su?YnIvDz%AH9k}KYYK1H0A94-g?zOJefMcUg)}z8_9#vPxK)p3wLFFIL)#-RbQ<33ZvxP9XrD`BBA{$JmmaC z-_?7DIoJuocjU67);=Gj>mF|muut|E2f5FR2#T%X&}K?6Npjra=Dv|7)$mWa|>9?!t~B>bJKIlv@Yk4tdl!5yV`@;GmevCAy~ z;7-*(Y;Z@U-g5pXBn;-W_Tzj>Bct0rW20&vC}A59b$`*rxqt5H{zh9NL)wvVk$^8{ z43RoHNz3K4xw;SU{?u)dOZCX1^$@r)aIBzp0adKk=gN_8{8};<{beh17bwuzb*3UO zNs1^XeFSGep*i@k8_RoXfj%w0l$RI{wMbdw^2opulYLkiczc`6b-M{VDpC|S(?oxc zXzvR113Pnp!@!7Ey7}I%S*2H-j~kkfPG@>M@&3FY+oyZ^+RkJrM|$z;&Fx)?w=*7# zj4`moAmI_f`NeG=DH7k^FIvLR-KL!nbR@q;C;m311@N&m3^0{2U)YKLVNK~rbsTB@ z6R*VU1ZtYp#MJ^oViftY>%aVn+*~mng^c{V-bYm3HY6bxJNK-pj&HlQU~^gMDP_21 z!us_XYNb-L(zZf8*;Vb_wNE65+!b#B2t$cPc=Jgk!tOPw@?Y(40+M9L<;2c^78Vsl zAAJfX>@ohFH^`=(omf1@sDC@z_7)x@C#hK0$QDdE?MMnU*;nT>{B*pd6NN$fcfSca zy;(mG;6G*f8FbgFcc8symK4N9k5-g^l_33!+t(}PSn2A$2Kg7Ud#$d-ftx#4WLK4B z7ce5;!QHFNXP0bbeo4G)NlY*7gl{0;#D~f*h3@WM;F`IDmxg8)b+akO1$kaZMNqv> zYVf;fbLEh@xAWLwxq96l$=0SzHQO&V$&mhmj9q4vGX8ei;XsrWmFBkM>T?k9eGS`Z z@Nq0_$b5H`ouVHnRfZRlusxj^kB)l-jo*<=P5H!{BKGOq@zPPn8#Vn(`~{$bUbue7 z-|uwftPHSgozJ(QhAVPi;JPsw)8qh&Ymqt3BFoU8CWW4VG;Cl|yBkBX-*R zh|{s`v3(57UhjhwW9>9wcTK*0pO8d(9WL`)lewSr)ti^@s;M(%MFuJBjh}{v_h;Fa zT=L7>JnY3hyx;rzvxzU1=~v8gk*(47^M)^^m<&<=R0`+l_geGWlBHYbX20vM`a0iJ z{B({1qGZ7y{_^_bb&{7;q;X$Y9oZ|Ync`df)JjbA`oNGh>dI zPD^@gE3^t0eG_sglcApPRZ(g(-eJhTvlc~|{xf;k7*KB|sQa0ZWlZjNu5LSi(8oDm z@t+?p)POBWqK7e;;9A?XgP6{{T;~gi#(;f#-3wD~^`s{m_N87-UmssVu#uy%;lV@p z!=Z2bRCsb{axOEj6tjuvZ}Om_!tetQ8J$Kq9itd!P|-`(1akSSHPg zSkMyy+Jh<_r`Z-7ytn;rK=ZVdFErQHj4xlvMgwsd!6(#6&Ygex!oqCqyGGa%&NTh*rU*m9_ogO0X|YkyuCAWHTJTF|M7*v> z3WNXq1uBw;V{fSIBH;75jg4H<8RKq7L1+R_GZ?wH;$oI*;$b^_x?peYC?x9v?MZ$sQ|h?heQ<*&h;{HsZpV_V|c9nkTll zq-ojds2p-$db;bT+3PvT`3Jv$aM`{6&-GIX?JJBE2RU3H4Sz=z3j|Doa~TkSbBlj$ z?z`-eq!=@0k%e-SJ=}U%4oTd{tcH3nkHmU@f%+qr1#M6KK8_D&7etC3ieq1!-s1L< z|L%iK3(KyZhtc18&oypaQD{RUrcqp4{Y%CAw#0gg3C9s$YSKoO@>eFVYrLcCr>$l* z^e5u?^$wjNrrNN~yCXEC3?u`Q+Rl!ci$hYVIdbN4fo{m&!WMf8eP7GBwezXF6U9Ov zV%7(T9r}pGK&%O6h;l;8Y3?<4a8@HS=7GG#gIPQ9{HsYZxt#Oi;sC}+;~tw={|!%j zxWq|1lKBIA*y#&1w)b|A@BMv^bRQ$|j=_#>I!Ngch}SSmGAYL|_kp1KvY(lU8>9UU z3CZz`RUK@tc3Rw3sChA_DRw#M_u|)VX3C#*4cL)%(@@i)RgEeSI%L)Tt~;pOxB7RU zgB&Z5H-N7`Y&}h}H1%D}#F2Q2>*tZPYz#?5x;A?iB;h-?dXjRag;@Mt+#2#i(&K|+ z=Fx=GRDLAtr}d2MvQ!g#ySK)m_x$--XBWd8)YYnU$EF`A;OB>R4yK2;E~o~sLAfe* zcrP|De|=h&jK?F958(HL+<3GmmOAfkF`~Wepqo_#h|D8CW1yBDa#6UwNktR9+ z)$_M?$1+#XDKhl;^L9UB&KBXA)3q5)=fx*nT(VjiRwC*0*w%60FX+-l-L4fJHsuBxW~5=fi-rIE5-v3b!2 z4Ym~RhmOqu{n^ByJ4DYMKjtB{sg{WmzrPBYWd_m>VQl_*3MI3*wx=mFopw zX^N3))gw0+ymjmu`^RQQ&Zr1{LctM&9Eb1lu64OZuCt8#A(Hoay@{tPo2j;?xdsvR%n2B4=YT-O3PjxxHt z3Ir$O*g?|X|6oKYrWEh}@vo)-*WsTys0+`f_9Tm4B!AVxnG{{|J&TegN_HPh8unne z<5|AZ^U}`xn!VCruLFPgfj2(!qmXIkp19M|sSpyG(Q+tontR?`^oLMvfiM=n(CeAm zBTsKc!C9W7hK_ol3)Y?GGW<1$B)OaZb?ulTxkEC@`o!8rzIM7!gF;C5H(w*iqRJ)74Qpj`7+ntE@ zauJ$wu2?AP;#{;4jDQaM+t_CAojT|yJ{N*Q!cxhggcaDE!^Tmn9AkrA`W1Bpp_$dr z!n>$?DNH&4$RG&7H#@<}Y{8spDa!ca$I9w{@EbpL(J$yb=GODu#E$o)Q1ZO6(CY1a z$cAGqc!ToCnZ@v7&y35Kf%{32_PWKWd%oZfUX+8VuKOSrodazheSSV{+;lm@*oFVo zW$9Ex>b?U^|BuRubO=LHQUH|^#XTB`l^6@f#tP{6LSI(4-h2>j$Az~kq>VnA<6m-T zKTp29YWL9kbWn@D0ya$7!h2+xt9sRnBT|zi_gCw-O^txlGLi%DR@&P4i!x9TLi0OGZ)E8|Tw5?A)Ds?eFNt?Ig!_^< z*IrnKX}vMrAQ=;pLRQDy4>?Yxene$Y41kq+qIMQN#*Kfjf{Xf$`czB2ZO85#i$6^> zA_cbVGOeyCC7WgeZ+f;oa-Or-Tc6I|>OLP5U(uHc25T6{Apl$^fqSASEDsX1pzCIk zoR|5b8D&B?X{nZ_??u|>cw|Rej2%ID`u9p%w>h1qi0K-SG%FC9w_g~{N#LCEvb-hp zuP?s6EN$FLcgaH=RCp`N_=VSzBs%)|Aj4>$PZ9S8E7P`5v#LAR&1ZOJi(@_EUeuvU zq}*-G`7D#qlrkP!(@HaUQA3)XJtRRB!^|w%9^F?`kdU1fqbsnFJ$!I%a6mGl^Wj16 z&xhK(Y##DQeD@}vz}GDsnqzk0;T+zd-N(EAc{ck?edazG`^qqXM#MDnGBNyA5`Q%7 zalMldt2i1lSB&vGkSbGCvPcv-I9d95uqn$>n=W@%uVU*#)C}oFCf%gT75yMnA*)Ok zB|ajX@s!rbhUB_+rd}Kdpa)QiZ9r(j)z6XRgJ7+KPn8ALmuo{}oMJVo)mtqE+K*gA zGPVKJpr^Q8l;)+R31AewFWHpAw7yRI+xOywXiiY3=HR#18#?$42Wt)EdOjBvRyWgi zpVR79BwV_L2YY0l%4Pn!izi+n}*s#bXnKB=JCjPbXKlw8-`ZwMOPugE- zzAV-dX-8Zit+tp-zYY|t{p*52x|k?WnX`S^7YjPp(D2yK+&UH38<_pTai)I>Bc)b) zbbyPq6ST^x4_0s8N|K>7ZSzB`uzkxK0`m$yI?r+cGns{)_DR0<6?p~RC>1MGm6ke! z(>Fs&PDFsX(NC=j|C~ypKYeo-oUdR&xBatrWu$gMFFj^T5I~ai2-u|B_zR#Q4rgOU zDm4b$nn@1vnoSlq47R)iF*oIM>^eN{Tj>rZwbkWZg5N9hF}I-l%5k|g!oPeU<7AV7dUp8tba zcwFpHp(~8`%|da!WXlm*Gr6KnTXl?{?(s64;IZXK5cSar?S2IAHh_Q)?;gfzU%i*)=%0NbNLfXoz;xN%&H-o z)3fK3!Qi+FKHYh@)TWUVVsS{Q8dXJ&RY6)W%nBQI2dz?8=gC88?Nqzz9U6NqiqYfh zYq>7pCQTkboyUh}J9=yL(g0~TjCVj(%p;5H}7=14{=tKG% zxOXSUyO$N+p4nn>MfF44sXnp)6U4eFM`gbwW6e0|>Jvbx#Ng=jDAVGWtB}XTkhNsA z8c3|m_2)|JpEZPwaO-9gJY$D-`t@Ceb98|de`nH=9KAM->)PFR&!!;uP}ie>VQ=*c z* zOEOUaWLF~eXn3Dokl)4k31d39$*H2Q#6KAsRV05}uk%1iLGo=l|3No@_tESI+l-6= zCwIUEk^1Q4=k1Emd8+cEYUZtSX8nn?L1BrNF~}C&1!V+1;Vf-o3Xw-^(1eYZYPNS*i`}|5P;6 zeucj6L&Fi;aU-9btWy5o)yjAdnOYA<`+>C>cYXe$*){Q%8#HK>9E0L}!@Hh2`bY0> zCu%%O>#@=boy_DzSfq@;_pS!U5?<-1(uq%Iysaz=P8SZNzc816p0GpdV(|VXr@RI{ z*g(-`_OV?1R*=Gbw?%^bL*k^>wylCVLn3=jJ zwo;^%C)K*{Qc=#a^pp3K0a8yxDG~&9Lau_kUy69~(C`a=o8)i2Cd)uw4?xnjl}ioT zS6r-tNq+8f*u&^I(xm9tTN&Gx`I#<-_sF<)tA9VF|iCqT>;$0$qtQD1lur2rM{V;HtbyniPuWI zcO);TgxJ0nRs_CZw#=CO40e})CXpUobuhnQ^$@}U(lv8Sx!`*XoIo`xDpb3>l>f#+ z=Y^W`3L!L9!&h$9F)g%fKjoP>a5V%PH{vq=WBu^nDSMrg><9TMHN8s-_~8m;xW ze8_g0F5OK2meIdo(tfL|oez$Hg>9!z`xL9e<@vtd_PLsdHLN`233-X#-KxAYT6bO1 zOYKD-1mM{=Y1E|8;J^rX+8A6_0FWWc0Lkc zYOJf7_SGjiKsg^3NtGx~G)x@f`xvGoka+M^C6UeUmZEok>?iAAOLGEuRu1<{Y)SBM z=T?m$ZTDRK@)*d-#}HzD?I)7&cZp@aS>FWTp@_xYa9SX5f9v@gJ=rg5mi%a$`ut~W zR!}{a_VV#;wVI4|L(3tAOHcgscR+0ub&ra%FL65hGS$yN6elXIM9QirfYi^W zB6?z}RT+9a3Itvs0dA3k4fP#=srA?}d8U7yQ{sC#=Zuo&kT>F?DbY zA&7nE>vTBmEStSl-TW$(v$tNI?$L^Za$}(KPlq+1D_B8emJ(CXd_4$!rbf8k1Fj46 z^Pw-J#s!&U>{Yy#<5{A;3wo{08CSAi8YYp-7nt z@}hx9Dh(x-pH}r_9e2Kq&5d)I+^YX-*U2!c+ji*sDr3ul*~%kv+JslWMO_o!66S1b zLscP~8RA8pMolzy`37IxkR8JAl_>JPJ)P?K2VFB{+j_sq(e#2BQ;F_pTj8Eq2K`R^ z`8s^R+EUYg0x|4=-B!2lCMlm`dtW7l{OI|F3FO72Z|%Y8_E7gvMo&GRZLEw@WH>rE zDt5Is5HW6Dny7TS?G(016-GD-t8mW!x6%W`-Z1z?Q~com^WVCE58}QYz9by;walM` z5aMTLH4$@8tIGKk0<-JN(vZ;srQ+BR%cqx7CJ{C)>xLg0YyM;n9Vk2;w#YZWW)T{! zub=Cvfd_g8C@&rFtC8M?KO=H!nC=|qKMXogtz&YrUY@z_H+9u6VoxXM(o!zgqXzhR z%=o%-YKvA!2Y;Y}bQe#gG!OAqekWh8KA)~q9cPYpRZE;L29CwF@j~-#8{8Xz1yu#F z*KapH*^&Hb@hobmb48-!r*w@h?l7F=mJ_k^5mt^&UYw837eE%}r5y&9=?r?fIAu*C zH?vn;E#0RoF^A7Tm+duKJL*1OqsddEOlXb4a2XENES`lj5H1)NR~Cc18kN>~y#nL6 zcUd9x=~@EwwnAl2_~UC9BLnCDq)ILIN4@+`1Ayi!hJs`|xfTOW8d$`CeVs&;96XAC zWGZq19YaB$fx(pMxx5p*%`5h2H{z_SF{`1pU)x3Bt+v272EAKLTQ38*H|n*b9>4}H zY~4&xrQ@u(yLkP#!bZfhLDtB)gD(gw;8D#%8a@-g2Et8~=5>t_y-P`oMuK5$@$BpN zP0*Li(?FXIxReBHcLae(SZ(ZtJVEKJL!rB}sL4Rs4k?!iKT%I8+$l96>bEOc5*v#) z2K`;F{c+ZkA?27+D+Iv^>n)WQGUWC9&o*5t95N+CNmd>7oiVKF@;6^7VHX4kinG#w zQ%skBc8fOs-iuowueANAM@BE@4qR?(h8`6hM-r7Znyir#9y}>4{WrgzXt94UoCi>; zNc<3qK=wfrb+V;s4l?VjE^1+-{NKo2g}fPJ#jeeK0G}~0P3}mVn14Z%R}P!jItdI! z__FU??zy>Hic{b`x0w4&OZb|53r8HwkLE(UeHtY+r>GbtQKZeuD`m-HzxwC>Lxoeo zR^wIk4bOEl>!h4=Q1r@Z94o#|mk}-I`35q7MTUoHQ6T=~*b#BC{bYY&l_}Gi%40Eu41J)FO^a?) zm+L<{u-EXDU&KXhGWAlUL*B94Q0~eo3PootqkP;#9&!h@AauDgU(JVIJ-(|a z0KWQBdJ6`L1N!!^py$3$I`hg$$2-M<1szqQKViO3`VW$ld|)?WgnN&IjUCL<0@#|A zaXa3!2-*DY`@HRYwcFac)GF~JSNxkrlvH92l$fgV4RUQ!^h##QUqwgJf>Ku?tgM{C-6W7MEWx~)4X_tTIQ_=ie~Gv_MD!0Jl0g*E)f>b=t` z%cQC>mRU~mZsk)YpuaAct>4i}ooZB=_ff-%G;!f9XUD4WNih4rm8l^Uko4cO{QGI1 z%4-;NBD(2)eCYaeUv0qGf*$;-Q?ewhsU$K-P1^k$Os6!Cz%9){C?v*UPuBWklIPR1kc?bf5^!3=!`RM-T$JC_?Rs}_XSP0}? zs{r;ifmS`Ct-sKrH9I^E&QdeK6|b!$7$~LBoKHqIVKW{7WSi#qWEY$nENk*H&KZ<+ zhO;~=^e?GJh@^Sd91lfh+3u#H;t1pN#7#$~nV0+11ZSFW zIce4!??-B@fVAH%AB+DKq@Cc~MNthyklE*;Xd7tr%Fg&Fj4)^Oxf_!$&>i0YERuD_ zq>kjbU@+f%+HrlvX<3e;8&)twN7knB6mz4f)2E*5OVfH=u2v;V;0HLdR%*2HSM=LJ z2DC@Q?f{*2Vf*9-LTg1Lt_nAX|`jpMeR`mtBkn2>7-( zF;%OM0)C=#_fy*^`n5VJwaZcXww$x{6tHXg}jC6t~FH;b#+)DOt4@2D5A$%D0dwFl0IQm0-=B7K9ev2S{=$1W?6U2j z|Db&My$3B4tl{rGU;G#N2Y))=hDwL+UBqv9O=}*5w4-^A!)KoI`g8%Y8d&_jp$O!n zK^Yu($(RTdhuy;JV*};*u)DOAn$nOTBBgK+;#{s8Ph4I{@vWnvc(c6id$w6XZNR6D zo1Hov;FHA&)-_hYkhvGM_h63-pJk^Mq`s6s89T|sN7xPK=;=?yDp0ozVJpiiW8H=z(KsG@#i%efk3V+W~=gNFRgE{zEjk_)7pQ3 zcw0nsN6Ic>t1gU91|hksAfHlXy`RH%7Fhj2y9q+%Ipq*_UvHn0*~ATY=9>{jtn?ugchywYq@f&7#HaB$|3BU44DdM%v-{6VG~yo?wA@ zPW2sK*R(?)Bu^g_w7SO$XLMe{zM>Z2*EzgHg)dJ-X$lZgZ?StX93b!6`u$?ZfwiZY zwr8ivpyIoN|6J?3Hn`5QbijsivXGpz9~;XWH(@J-*H+)WJ;l(Ect~r!aLU_H7dy@{ zmxj)oAHBd5i(;u_-JrL@B=u$#%zp%MXljGqv+mx$5bsG&8Nd5Qs2yU2jI)q(D)^&P zqyLLU8Q|<5zcu(JTz_ZTyICAJRNvO2!(i|h60coNW2OHVZHEP3*a|)c3hxI-K1L{) zRviM1L)9+{Yvj(R$Q0OFrY&LCO3>bM=2T_yF+G&}d}0!auG-dZhT^@Q4Sm%i9SZ%x z)01BTd?wZtoe%lL?pTC5+fSTLwm6PI$MLrP+Gbw2?E=9S-~HZc3bY4~l#OsboaUn7 zs1{oV$SeWF1TRPbg~1@S*)7)hN0Ix{v^o)_iumU*7XHuE65Mb+|3dmwtl)BKvFr4g zpQExLN1OULLd^WS^-vh^z{$C`ohJEhZ^-@5^&Eye}zp1DbXK(t%ECqG?< zVA>rMYJ8nA8m+Cu2Q0YPIyU|pQRmFiX&``J*2XUB`7XbyYnNVSZO+?F1PxVVL=1Ji zHfBzvWS->CssHv>kMV*VU{*|3S?|R7We7NaC;?FW&gVO1kZB6SAMFSu*{+I3(owmNsK1^K zrGa}~U-Szy+5 z#ZjEhrbx_*wjx*I6yOD**38u)$OJMmqOO%`ef1kW;#n9oqe z5rUO>VnIwPbh+xml)=ig^il==!6O(Q2l7gN$IWH)(_|EvvuP&!NUlrFQqk;a$^3MF znBF?30dW|df^8|NI^0+J1u4ckd2OY+jk|Q+NClpnm6en~7=f>Se8+7%XEu@I2tv3QeDdns z2fZ`nOmpRuYikE!PC`NthzG_A^kLXb0$=dO4&0RlXuieVKhcUVS`fO3EB=@K{1@%K z2PVrS&MMrRyt8bz)U0dlXLHnQ1aAB!sg4rK_A7_!PZH<_DO{}$wOfG0*DMgv;pb}| zYvSo@Yr*s8g0ZHx@uxYsy#aTI)%-N;LEn$T=g5l2Rc{XzalB>BusFW8e2@$`USyQX zhXX>MI)*9e3u;c-3O=(0I9eC5jh!=3`ir9A8cXoF4Mlx#4L(;@!tBs4e4+%R#tVQ< zdfZdCV8_{2QY|d{JBy0{VZUy7isvOET9~O-`oy;~GTdQ9g+`pu7$}047DTftlw+(#f zh{a{!3>$o{%IHsvJD+rX`~)J9NdlbOOOP`{NW*q6wUXfQiB+CNr*^cAM9^k~m2pXp zFRxd{@jR#Ij1ATRsvRUS-%>Df^+tuVbaA1D`$5Ifg6oxAnrUcAG5&KW?9;U02~N!Lh)n@Bmv)2j3{<{QzshlE+t{Ps7xkzM2T678@ak7SogrxF z3l(?<#CC-qfsb*6<1=$=>Ye)0NV zEA^Ue(E0IfN%BoX>$7583W?sK7%gqe@H%Z;Pzu#%!}lPh!_l@z<)F9o_@ujH34y%e z#ug#QmzIM!=gR#pkO9-A;4sk60jT{CwC>bux+$O9d)|#7_w!x2dy(@OHvey1DTt2sj4pjVn5ceJy#-}fcP z>*1Rzp9+*HeYCr|BDn<uR|#ChXnS#bCIXAxYwxq<$-_saCBk3|Y)rrCD6<_q(Q#bYGSK zC~60EeaJlSdxjt7#y;AS{1s&>Fyq>ey$#8aCp451-IfEZe67;nncP5yc#PJ~{undq zMx&sT%z>_n!V$BapMq_EanZUI?VDV#PS+^OT4}}0RAVR!@7_wPLi6pt>8hFu@?abw zG;Y&lDvj98Is#vqI92!=N)No^>2A;C{L0z}I;XXU#!tC~4IxPxmEIqki)4S19xBO# z&H*hVo%qq<#QA6vW~@KM=@qv;gCy`_^#1`dq%zo} zUuw5S1lv`fESXLn_WSslPR9EV1VwJ5`a9W9M|yS5XKqrXj$HJ2m6D)O zP=}r$x%PVy(?F%7e+V-G8E?{Yt9QZyaAeGftdNXR6f4q@L=_zg*W$6&3q9FW zk2WbQdG+PN;KX|si=B{eMQh{5N%6`M@ib!7THRsVQx>A6_nVOyyr#Lu04K=%9>wm- z+VU|l?FeJW*8RmP$4;V_LmG3iO_$g;T8u_op;srDuvn5OC-!`eqqq`Ti)5>@}s#abJwDj1qj@cV$NANJCX(JZ}Y$o(@;#bm@ZJ3^N2HR6ZP`py-7 zQ07@+h~!Lhz3^iZSp-Awosnxa(rA`1O%)(Sru%c%8HXa+{YOVdl~*U;dsdX!xbL;5 zj`3gX3Fe_ih^}Ve0exsy2#anU8L4}AisqtsPzCgJR=NHX)EY4_UQ$#lxG4$rWe-Dy z;+{-!NP3%0R}`o#Kte_uw%C|knjnjev{E{vC+t?!+`b<+K}?egX6Y2IDaAL`7sfa< z96R)j2n?xQl9q3DfEC1aht}X2xE9jDsvSft$iTP`-$ra*_QLixj~AhgJ09*8|2Bc8 z-d!3BIugV8-^EAt5{1U)`OTxtX(hX?Av`ykGCz#03mBH{t9siQd;z|SZBk&^Wnjlp z5P68zPs0|fZv5#dx8wJ%u8Sn6SjzGY*gZLxyHiQ`1x3m<`L!yy(@Hn4!9(;$`a1jO zx58LN#WMF$g=kamTa9g0kCX{K%r+=r zdF7+lEzzuXj!M;xi^t)bbiZ>B!R&{K1Zhk58M|QIqCfXiNcXW+x9?HxxKQOkm0b^L zIYN&(#nrOK6u(YpbNgSFsd*VyLx)bWU2a#}Z4Za#lQWU9a5|NbalQ~8hn`qYgYql? zOV)lw&%rjweg{)&(Eio&cBgoCvqbCxZNElLMD74+QSJIWK*n2+l%6a0s>3%ujHoGV z3Ot&Sf4EsLTpgS1NCct0C&E*IvU;eRu1m>a`=!k_*uV_owGOp`Ip~elJ-|q7KBht1 zxBSpMv{T@gbd-8k%`5m^l0{QS2!4$m_hHw5juAy(?*T6CaMOK9DTQ~0S` z$SP@Jh=IE_joZaXzN>d2<5Q)=-Du&T(`9DX)ut@tRr_pHi07gqi}ZAab1!v$#IGod zNZcS|~miH5wv%ci^3Xb;N|5I=*p8=qAkF7PTZxvxZ zGtnURBK00;{+Y7uTBTmO(!J5Nv56<0>vPoTBbnFtV1Gxt&4Paf+gauU#1nVhWiH)^ zl9YRV{jZTDwS!>uMXG8#v>er{0!Ho8yQ6WjAi+rI%}_MT<s0>$76m2EvUeV z%d0Pk`lq$eYZO3LfYd8pZkRS+LY9lI>kPD7cTTC`3-;q-g-&xb^=Z|G>#tl#%aFkj zv{m$UWKTf%-b|%)30e{{Z-M;oGLgWtVa&t?* zh}8V}uC89Y@t#8D#|_&5fkek^yK~aE7pphJHg*j#=^;qh{09J=Ujw87qt207`wG?0 zQP0l%%CC#Bm|rub6#sGZKnA^b?2<=f6+O4OKj(pS{bRyCi)1#7<(mF57^cfdv@!G|L-tz4l~l0&k{VC*qGTpl zKLs1H3R=H&hkov`^m?&oS5@R%aki0ku9G({I^w9_JTlNkk%ViwtXu%CLNk^Z5gTpw z#?_c%2_W=m0A1ybz&ATHCG6+?f*DRS(@!u#%Hp`*ma~&-!tR;BUSVXNoBVfz(KEJ+ z55C3Mm8AHkm8L3JkWBqo*>Ox|dN|~y$emzi#{*-vC7-u-41@WDCmm(i4**};V_1c( zF0YL5(VuTKOyvEUb`adQ|Fduk=VFESC{b%Kt}*QJ*7M`Au!~!h zg%g7IKSkwByE|f_&l(8CuLy%&$IwRseuquBCeiL2o)cAwW1E#T#l+}FDZ5G3^Fefv zA3UE?GI!tNmx&D;)og~?%~ZGO(lN3PeBC^}@ncz%ulnQ?(X!H|7Df-ug*I>eM(qKg z!2g-v!eBcZ=PZNjJ=FW#3fkO9UWXL?UVrYwj39V8TD5OiE9rS%_$SNP&c)7=&b^Gg z{#?|*b0hHvnnt&5%b&0Y_s}W-pO;swQ29YWAFF$rzxQG*XaYu}Slk_ekzdrW49 zRfCJK-f_C23a$H4qz#O@j}49M>-qp&P*i(o0C9oq#Y<`-63T8M0g`xKhcNM)Gm?#D zpH()h;dCB=RufbyTdeepEV|XQtD>uY|^`ajRJcSl>}hQIBX|xty(9% z=Ek604WuGQUS>!Fp9t^n^L?sZ0E!Yzy@dHlABF6FnDC&%*kCQ83vGml5%tLL8#bBt z5(wyFlU5GREGDhKCpA2w&BM)vv+c3|c+QT90dqkl`JI*4HPwIFqNSso|DTP7Qq)f9$$nhjT0E#e zi8X@z5oxto+gnDrOlyIRwSSms9$MTfoCp;7E|T!is_)g1gN&E^+_!|k`y71PZ`gY# zZ0Jv|_qCeZHGGI89(JeH{%OHL%CNBP_YG2llg41u)Gu9uKdrn4pBOj%1ja<-Zo9jM z42JO$S}Voe^+Za9hvuo!&teQ&YlrhkTBIxJIvpMyiV>|O?9p4u{`%x52Ea-7U}osm z6;`$q<$I8{o8D48C~Ck*QJmxPUaA2A%R>OYHc^2Tzj@hiXO=qdmB=e@qI?V!N>)$s z+Euj->Q{F7!5HI*f>15L?$OM(aK!XZD}&}`WSSqmrxYI@Q2sI;v~rgm|1Ml!aP(3C z>#nvWZ-#3>^TArky(I;!!B_SX9SE6XZ4E|yM0MnI4}Ti7F9vVhbX@T7axL$7CR7NP zR#a|@Sz|iNSF>Yl+=qN0J@U{Gz}{$mcyvo*_rn`te|K6^V_(E!qp1N5{k1 z(}7exa5B&ap6^b;6x3g4Qk=6{eL+uKJ%@wbAC_;~wE0!hi;gK?T4R)|j-K;Kmdw+Q zSzZI;^e@`K6IO}KZBZ9P2d@5@L))(lJK~UkhwyJZe0QVTwaDL4`~Pp{k<#10CGjm@ z)A#t2sC@bv{BeK<`>^a1|8yIFGRy6qbpu;X*$;Pb@BQMNk84n?GOa^nI)}=5kHmR!64^Tspipy#lTlGGJG9pEERxf&rw?n zXFzOAh{WX`vg0{kJD8FywclIt$C{Uq5a2EAiFu_(>KI6C~Mpt0ZxP9<6` zNgi{H1{AJ$plou1&(Y?yAwR>eQhLX$>1uo>d|U7-*8X9qr>u4y9L$j*JjfyEa3<12 z8o9LD+n#s!_U5pXqLwR#ope;rzVkJ;Kj_{oiNR1-OArT!q!k@iKVIJj3fG_K&TMYS zJ%bW!jW>-Sr=uMRY$^RjH>PEUlP5EkaUN3xW(CmL{fR6GqGZv1W=_&5<4MFdAbN*B zbzRGKc=(j;1Rh9*V z)-c^rjlK8+JG$L=GW!DQzPo6=s>!IdeO|_)VYg|bPg|X}zu?jgjIC&X5-ag4^Q*6S z&Pz8X6x3pa6zFP`5JO!V*_GKE=E)WS&*dPh)ouu^WIh{2*eYnUO-R=zNz}= zT3l-tRyBGZh_2qg+5H<)T{vIq>rPjYW8U>`UXrVHzRc!JC^7LR#zUkDu9)34|Dwu2 zqA{ofW5yReCtN2*v%^L%b(XPX3)p6Jo_~v@UmH;HJK7@+<~*Sgv%JfB!o=UPW%S-( zZucGyNtyLOZv}!Q_-F)rIrg_Lgatp!mD>TtSfV7xm<-JQRglyJt#>HAhVeVC?!_`i zURSK7V-KHb&?SMiFNm!q0$t2- z$X!3WVMI)lqjhsXfR8xK`aIw=BLS$}KeA`c0i;7*Es!wuek@A42v{_y?G zn5l=FUut=*u(Aj)CoYdeanx2p_oP2qlc%yExs)h(RQX8k8w56jRmhgigR9GN!;+}Q z1ouq2|B5SwoG2G~OoC~#lrJf~55nt6u*7J3W+E(qv=>%4~YDIA16D9O}wBG3){{dOPq{ zLlUx$Rk%H1fq{?NwjKidf;y2WR<8LjxmC5ZBUit^`a35MGa9C;r z3YCwSbz{mRfE{p%8tlE(hWyAw`G-gg9uEYv%H~tEcnwx$(5V_{U@>QQ80I<&aTXG* z5BnfIZ)xm%Yai%Yv27N*7pUGmmgQEpmtziX_8%&StzDbm@w^3^=B}dim@@vjppV4CueuHC*fe!mi0A*Ygx(_p~8=0EHnz zv+YTds*uj%wo@JDkK)NF#{RIGRIlS7@eIH3z0$4V0;V|hP8{++ z%?$->c#E=RpJxIdTM#5Q`_O!=RmLBaXR!H|xarjg0H$5<;7t}5qTf1(;4GSh>?$8g z+T8yXEKpy2eXG78=lf^<=!t90zMxzya zSdjfqEBBIw!fD7-%2~bh6jhI{MfW+i5iEO#fZujSPd-txQ<*Q5eJ@;~XWF^PZ=!Yt zmI5=T37T97l*y-H#W`A}1QOT=g-nE(=3B~Q$I&AJ$?C~?G+is znNHl#4F^@oCVGVhQKo~nJjtIPDB?LuX1p`K>{OEkZZLzl$`qqWAa_T+iA9nainsw^8`mg`zn<`#EyWRoE-OJ9Alj1+OA~ zUIJUHavCw43(R*7bM+-kCg)}~>!Hm0600;;d|e2pEG_V&49X5sFWiL`PZwjeqIyWV zCZVmu3m5pNa6ZZmRGWP9J6B?3l*JbV%>B0Ufno=2P1I0tlR7^o`tSZ`L|pF9z~RsS zU6SrCcL#M$ke;^xP0n~pAkJ1t#QK++9_?O%4@_pi-<*3vMSO}6x7OFUU6NFg)%#cjO8tLJE`Vu(L=Ls4F+Q4(+aS?#S0 zbA{#$WuvWY6*imX|BJ0RkB7SN+y8Ba5?LyhC9`Ow~%`{{ioDs6` zWSJC6_I0c?LKuT7+t?@TV64Mf#`gVmUe|ryzw7t7|K;JInYYj9^*)a0alC|8153lQ z;`rc*-_)efIg7VT;njak=d^#y!o~Z5UXF= z+#`icq6By2X`OAnn8>_aTHp0B4(nE-+Fm^}x;HjjG?HJSoa!8{V#0jB~nA<5$^umNW>%Mk37}@+o>{x(w)s{L9hd9`VOUsTgXKdv4#z3o{nsPnRq;jg4fAD zLYby!Rl|jT;V3IaOEttA$c-}_@;FpH`8s2n+S_t9sO#jX8^Qdt!RG;=&(IwiLkeo$ z_PN76*~k~;zbesGx=Z;Iclls?T=mh!S7L$99*j`B#7GHxX2O)6yjeRQG>rVr{|DXj z%K2+gNNt^ez;iOV>(0L?W8+)@>#zgPyXRS7-0A-M74_OjrXM37A7sVTntbUR^i#1r z`E8lFjE$J`DAhosfPr>yn~mb?5W$FOPw3b6#y@I)lesqu3r|?wT(h!CUL$WvUo7I) zX*#0$IJwwVLp5*ak)Sq(oJflIte;3mp7iK=q4k$GIA*oN)~2Fwb}C*TDG-iOo?r-B z&N&mI;%of@3YjQy=N7k0uL!>U+h4rlS3y-)&^P995~&1<_quxH`hv?R(R1V(Fw5Ow zSzkBiDC@R1+nZDQpDIi{p$#?9BAXBVvyWUPfp}C?*i0>gbQXwD-s{4&H>yD<>AR)l zBFReT0AvrD#I0a0&^O8I8)+C^6t%zT z?O!3a?EN|{wv71+?43~qj4xJ1jezlBkanz{`;XB=Hvi$K3JhtB(KGCE%&iRlu|}>P zG#~*(=CTd38sDAsQB!Km-T>-MGU7U?J};bpH+d|-rVP*QnJ<>*SfAYFPCS(Id9%#cRv(_E32u|X1RdygUezIv+|nO}|8M0@8fRrs`!op`v{ z;_mACJDX#k4SIhi!2`i~#}ako!#(m)peSnNo^JV#gYVU88}|B;?mPr%Gr^t z^Gu_0@Wy*brOsgRu}Twe_EZxC{pSe>hvb0(Sy2P}ANo)ogxVX%f{#~;zJ!hSRm9;J zYJyh71Z`otJ_t|;liF1c!++8~;CpRnm|NY}w-Ke~EZo?!qwu*Y%T9xr*Y@ljl_#2L5NDpC<878q^r;#J9Jzccn)xOwP|cV}v^}2v_V~v)I1aXS zA})B>jj2m@x2cHl$9z8M19GvaJ>7%)x!slCvF0fiF-^AA%rtGHfSFYXJShj zXZKkEXkI&KW27V=)^R&LS^IQ{_YW)2G8I#I-3f52A@H!;?C9*sbuaR!TJmaPI1O(3 zDora)G+(I~Zdehg@TPtWepQZr^hGtWPih#f0gL)Ae$c$|<+ABcUD*ZR^z50yTxN%{ zG>nXC66Y_i7u6+qNLX3(^fle84?)B_*@%W6^zP?jMSL=J;97Et=tf~|YJD`$_L$1>v@TE~KHngw06Vn=+YMg`{Ro*U3 z6qr`<9yb-C1Cseqv`*1s-+?fEIvd)zMG-h0`&*j-$9S)<_UCmNyj%?)4-VeTJme2{ znJ~z{&NfezUw;z9W32I>t4=X)C;8^ZLe*1A&`(-r(e`Hj1wno+A!gGf#G8F2i>C|o zFb9~(1io)bv?W|7i-gAj<9Q)$z+2K;SeYoocuS}e_NqVHnw(Q;H{;&}n&zcz!<0Qq zvciuhUC(is1%3G2np$wQ@C3Ip&~v57HTUuYXwOqktlxK!)?08Pkk=&RUL!VPOLoJ9 z2hUGILgEP5EHXN^(bkBxY~r!C()l^b)3k5KdTljr70}El3$;B9GJO+%OAe+d7+?V> zpP#9dCEJaSL_w(zCX$bw{q*-y8V9*HOxvDX>D=8m*fs^HRdyY!(NEiH6gkIfb{fY; zP@w-fxkO`EL7$+_^d>?&4m(cQttfIrd*cTKx_Z9-yWp9(cXNJIMWL)aY9)7OMoQ72 z0~aoLf1F&Mf@@~)cKca8>D$u!bpi6pzmx72y$b96pQ|GM_T&0s z>{j+YUXg^^F~5#PrZ%NT*(;spL*w$9Rzz^R01h-%-+RX9?V2peTr+5JyMv;&+BjV@ z^ve~dR5T`hpudMdSfpJ(yu2cl8Zc)yCdpiD!8>UJ#vcB~=Q&&u%PWlBPg{9Y48-7% z0!X>3Cqu_W9eFI4Q{?KpO8Nd$V!!FP_ocfqF#o51kJ|Fj9!K!JT+XYQ`ODpn6j(BD z##E)ONjuH95s{A|d7b|7C@%NUu?~oLYsu;-V2E({yag2pSL+N=EGt-_w%-?i1iLT> zs7vsHyuduoN1L3RIPibwuDtzrMu%R03_Iaq$R~5jrwL1Rt!YErw*9F1_87)f#e7fG z_hUZJ@;&~85E0mowGE-yj_seXVF((kJ3nKqo}Jz(J1Lp?yFe|-&NdiC^eOQmvXR5R zq}&^%>M-;E*sko=tBFGQxb$W7dM7~NZ!mw6&~!Fb9W9V7-n3+}nhNGkLxwlPqwBwR zRU4Y+N-0%cZ3X=d{bXcIRS3+ceK9Zei6bMF982Ggkva!;$YfHGPE&wf)H7meuGK<0 z*9)(Dy;m`j+64qgKnnE(7k6Xq9eC`{R%Ow#h?pVldudz`$B-;@K7jSlEm#TQ(h9A9 z{du|e4}CfT1gSrO`-)v}R3PFhu}p>CA(?nV$PY|_o|R^%nTiK(B>3eTYVEgwNVoOrq39?O|-&7qpGfvxDAGz*9rDBMB|9&-{ zg!~043;#2Q=k0g=F-Z~J(EzDGXzciyW6lGaLu`J>(ucZ@IG5*P)zq&YEMmfF=?O8S zg?q~ICKp}$!qd|-^W9*ilzICHJe6Ke)Fexexwos+!~=3Q&gwQMw07L!lWEOW{r79N z`~`gYg^Np*@f0ni=1-Y1RQkEF(uea1R#PeSEsw@_N` zBkw{i#OhOY&Xedv{I(WBdY-#>9Mg?qDV=_-WKFuqZ{Fz7d!OqbyLiCTo3FG8=_$^= zXVq_R%y9Q9WLwGc9IYHD`Rc3j_6*KhF6ROj?YF-J*R*u6XZT%-k)dbb!3eZVWYJZP zKGDdBfAMx=o7Z(AywaJoQaJY_Bl9aR&nja9)w^EOTd%9tlow5GwAcQd^Oa8-Upez{ zxh9{S^6cYc{Ds7M`DL4x)RT!IZ%e%o7?fpJs7rX0oAF-XxM#!t%t(SM!IMC!-KdId z)^SadNj<0!yIk3ei?)oM(Z`AQ_@Spv)dMWP1%STnX{$*#jA_meRBw$>x>Eu$i>38D z&8Xpc>IP7zQI?FZI`A2Q-==%&Z%B#g3 zKA_cwLco1b#gC>=)Q{gM5&yYv9ew}%zu2E;@4ch=4Y>X3Z*V5vRDbic#h;T+CQfH) zbLkhr#`Y?E4Wvjj#j>zBwiJ2J8}??z5u1MB9nN>mAZ2=*sqaoA*!F}3&CZz_r9H*( zut9?=+=JQ78^)nSvsUYk4EWS?{NS(l4LV??mNwhZl#;*9^j4ck!YCfj8fsKG`|^s( z@upW8=@vsXscq7Exe%=%$w^UbsXlKWyf+&uP2(%|HOTjtz(Tx~+N{}=bycHtVrW(s zm6n^fN0KG#D_!2D+@-1M^2v2F(3Akun2=mrVI;ePu*VH<0w zvXDgQcUZcaXHx8f-fbU$dg+_<7Iv5_tMrapEH>n7LK}N0s&ij5BxQ{c4#-jGmvWo$ zvxstUGXamR)GS(%PJV{&lzU`~k+(+wS&#*{+zlhHzo%h*ov)>t^jUX#cugh+B53Az z0bBkG)fTaZDE8QvKAUo1JPV@F*S-|d2f-a}E)N~4s;9{&d z)NH3Y0h^S)h&p)Fl1nCMO#m}=a<;1j-cf5HZF5b&-r(KibambEMu3I?*xS-ik~z~8 z%KJ|IXx4eAQF5Y^FPczgD{?a8P=fhBYs-V>f!MmeCC8U1BFT#?5+^T-hT432ks(~zmNYm6(|RSg#?Uu>~)Ehhd*ct&)wUCxA|a^K`i%_QBn z-hEoAQRHq_J?4Veu0S%qgcml!t;^5AZEHK%_ec)Q=>$Z1v4k%FLQ{$MbNsddVXxHh z+ohwU+&q%sG+L;~Z>j;+{ET#g&dRri4-bFs3utsQQs6pztGx`wvCMY)2@qh#9fk8B z4HHin7Bc@8*4|1!`^UfkpXb>uXFGSGsNq3!gePO95;({(xcZ#h6PMR$xlI-7*9kDN zEj#JqoaIM!)*6Mxwr21lf)>bbILfo|RTC`h;Z{L@#AYJg(>u_QMnh=-^-lD)9A@XT zEg@Ill0webF(v<~JdV$7+&Gn0E@vBMAIdNLwz$Z%;JI3liyU2r|ZQ-LL6ZBts zPu11@d2BBu*3n93OxMaLc-u6spkT-mL{fOm3b#?}(xDGKhUYx9PNHi%44DctV`3iz zPb5Qo+#7ONAIBv>ibpSeuDLT&ZCn;?q~KGuU&ARLRhch>2&(WfhPksj*bZI;n$u&O z8OeMAi*KY=c5}n|)56s@jFguDIpgj{%;(_QU*Kho4*|%odQD9YD6oW())NMy+)(3% zUzY`cPPS(p7V!719kWQ&$AARRTzr(9D^SP|icL`o^8DSXQoqiC&jCP6@4z$osXX-O zz8fRL+=thI#B1}ew9ns_oK}iAvQ;UU7|*eT?~G?M#1FE1kI(GvJBeWdyKnb=B~Kyp zd3y(FSv)>7!9YNY;jXQNo@q~=LDhqyu9BZ=LEVjT&&#JIsIXgr*dCAswNCok%<5=u zbnj8}D;^sHRrU&`n)&dFr_k4~zLWF@S!XS$hAYvC0m61PPUgv zY))4PzC~od;Y1$oLYH}%?n9~_FcCtRx3$RkTRtjJ_J2HhxZgH^_bqYWRK;<6g1B(( z_bPYA_i0cWj4-)ki501^F&>C0H9TXvaT&-YNu(NvLhf-RT*pe{T?vKAyND@Xce<7J zCE|9l{ZXvvvF52~(F%}11f&UYy)+0Nyd)St%XU5HVDt3We{eea|KFwWi9)7$dIN4Q zsvC;FBcz=A>vY@V+>TNrkRH+RI53U$714-zM*K!xcE2CIC(>1^Xz-EW_AI@fK*xFW z_3bT3X#;ia5iv$tiYi~DJ0YF&b0uc*bJy{euJCT-P_6~Q=ZlnHHH(B539`_$FH}iR z%qy=3WFN_btD!Ew|z#I)66rzqD>mc9#_pEkPd}6Hn zhuOK`>vgUb>g!uN*ghs4OrG9d6GQmqEY6E)A`^ zAVcCBRE9tN<${BVU6W|JOv}xt?8j;>SEpvel-AN43%eATSdFjHWnj;P@FG18l84L* z4_Z(Ps%%MIY4bjY+}IQDB(pSzH^t2&2;utNov5zccu(tR{ZK60zoe?fvHYoVnw~BY zOdWGtOI~gAkUDg6*ZkTggnzPjTCmFjn;6+Ij}5{umTIll`k`tG5>{E!rQUUAeWeQE z%a(J^uMI75JEhJ6q@YR)OZv;4;-D#);6Bma;_1Lv$I@84Qor#JD$^<5r*$jqx7?c6 z?ys&F5}FUqPp`oD7uvzE0=@vJ1KjX`1&NHKH-acDw!u{BRQe&~o>U;`uCXnB6Amy; zpC2gwx$luKu7dzer#taPq3q&PHe(L71exNI^xAOn2ypl6GZN`%Q__PULYW-&cD?vE zxpckx&h`Z4{%xIe6UYYpFh+jlBT&s>XQyqh&djG*ppLCGF0BX?l)|4E?uuD(pYH(D zTalZKUX?UrS%se?Duute1?wD)M7@z*DAU(RLC3Cm(*3?zv6|dlY-I1S_WbdppR=V^ zyk4mC-EHA2jZfOG8|(COQlN+<{Td4m>7Tq>W^g$f`PiuPjHtt48=S z0{fqM5Z~*W-bM;LH|{~KtrBo4*LD&ZI z7K1l(9>18dWJxmqoB3HLpXNKCcn6!+5!bhPrR2}qI@t(b+446=SIZRjZ+T{VX5+2z z#LGI6;7Qk+RyOBL58sk%A?oQ~MB*OZ9!_D5Kvn++RU5n?2T`*i77zv^^znx3oU>+3 z8~(X22#bcVmg?34PBlGX2H2tg?hAC4x{hs8`7_sS*daBLG}#qX>6kq2Frk1Xf5O&! zpIBgB=%JV!K&zre6z-7;^w)D{=Yg0(^0mRq}qoLo5b6OB0M z&8h@G3id%1psRy{>mnQ4WC2LS?!RUJ2Y0(L^Z%j$5f}gD**G1xsx{!$BDeeOpVYKX zvbPBaf$7@^t2h0O!f!D;UGkTjXfC{$$@4(qx?ZkaKHZ~tFM;hCoegUT!8(=?+(il+ z`qohi3*>g+$2Zb=B-ED>F2d9CEC+m5?oPyk~Rg_Ia8%D@Cbu z-VSm!f}hOS4A-_bQPrAO971sX;0I||5YDGhYyCDxx-O;gm2n3sghve`d7JVy z*C&0E9H~lpferk?JVN|olMh8+I7=P+DJu@g7PO~V=W6{(SJhCw6<9->TR2}#urJ1wT(p0()-$B#Tbpr*bp zaD(KIv^}QJlfHgWO_RU=*d0e+mcboNJMwLeUpZ)=37nIlh~ra1gCvUId{zu?w(th+kjsk zJ|TZ7QUtnGqdb?<+TW0F9!Y_Zy4nPq6VH0Q}EQP+el3l|Tj)*>IgHt?6AQbLSUrjN$QfF%>lq z^PJ?I)WIJj5mvaUl-~vea$7y$wyEt$%ZZTOL7juzK23Nj*7BP%iPNlLoeHh8y1h}B zcZt_dA2W8lSn<}-^^2o6?$u96+Acrxwpk=10u}gKNCO7@Z|1oY9$(b@B%12~{(KSq z%ilQ@?F`E4D$8Of8J=fZ*Z9;z{M@xvZ1vNt{Es^M>`S3#=eDgRWxNhxViTL+m-T(gT1!BJY zHj3^VQ(Ib2f$>B-Ui3zU$z`J}L$BGF5J|EwV){Gu5BYYKJct_3Lk*qojNI9>VlU`p zg#VUgVgAQt`Q6A|mX!u!B}qba^fe>(mX?>IUak*le&Oefi~J1S{o3qgcma%GvnV38 zXWfP;-HX&|vi}e}$+W~+0cK1a)M zC(1FkM-o9UVjjYODWWKLK+<1$L!9#-$a3Bdh&JZ#wM{>4alTPNtr0XBoM(T>H(@^&)?ck{#M{PgcdXK}?Aq~IQ^~w1!0l`YrgfYd-t_=#cMa$lv5V>2 zq!@gO2;mXCa_@uZbhdA|_s4+S0rNZOyvM)8_{#2F>8e*N8VmY(aYMjC86}Vk7e6l= z&VolR+_&e1f&3fag=fWE%vhf*IRS` zR{eFQU9+MS=`VuUL=ov-N0#p@3KMoDOw^xcC6B0MWboIYg(PiTeOmzmnBkG-x7W+% z&58{{r7z2w_s0vB-Tb+G?sFd;xvE9G2-Xb;tMq(7_!4fZu-!f9x;CvJ8hA6xI=Ne( z79N$c=(@0%jvPSDUKe{I)Hkw81%UFtSbUc3Zqov$e{AT-t z+_Kyo;m01ypq~vnR-Yj}_GSdd;>!CbIomC{gGZhMinH55gKL&A`1(ogKWLP^Fz%m= z-hTU;J|MwH^MU?Uh#NL+_1C@TvAIHoGEA&vOYuvai1L6WTR=%o8Q` zU`0356vm9WE6CPydgCvHmWaFZML+P`Nvx~RhHiR?r2rp_T=ht$Eyxy#w_KwY7xloUxb;;yS zRRW3TCqejH(`Qsdk)aW8@n~Ml>9Nh`Ga$3A#P65wBfU#e%_q|6{>pjGh*s?O)=(Nd z2xN4yZ676eduJ#*tfu+X08BRM5q~G@9SQNaJ#?^{yQ6Y)a^^0OP# zyZGVKA}G~bQP@PwhH1O8q@-}bS0J)4aB5_&A%-;MUZ82KS>{^Tfb!hdRKRyt#T=%b zR0I7p>kYGoC65oE?6o{K9#5rM9;Z9&O|PQmrDS)SvhOg1f=fZE(1C9g_0)EAY zL>!o$dOu#ix3ztF$o2Q*13%_c%68>f#9ArJg6OekIpSVhOt3FKSqLbCiwt> zLw`+e)pGv=XTsO`PgkPBr}k+;m}yp&v**fft}}lCs{ei7Z7pw3ZJ>{;_Xx}ANw9D5 zqQh!_q_CC>KYhN2v$p?x5?jv}L)hc{aau9Z>mn^s@pG@$({@R0KU)tXw(q8et$GWl zg2M4%D%RnikM8t~;gHtsj#_8E-@FoJZ9r8rm+5m8s1NKv*ztzj`vz(9NEG3G?8TBJ z=L}H(tcu1$w-T51!iEYaR|bDco=BVb1KkwB>rt=&?w#(U)4`i#^YGc1INeu8n`Og^ z_P6|&^>2~ZDsU265;bjd`us1<>~me!MGw=}q1RtEJ@v&dUd70**=Jk5%)eHskZ-0q zax=VQRBnWR42Z@aNeYAmk1K#eU_JJT-27-@3*s~w2*w#A_DF7($&g=A+XCJ?{0u+vtQg??c@M?ScTN4WCbb@ zoDEG;Ex}bN2xg005$Ht{a0g-8Sk`Mjo+x^QziT-mmqC-9X{t-)Mxs({?{yYP-0OH4 ztG5tc+S9`wUxC~!=q^=GiY)QqLq^%>Tk|Ob(1L2U_2{Sb-ueEZO1cx(UeF)?{r*!6Py>@L=l#Yz6*X`ZHdbOKGx~1MmK}G6?$M{6=JXw4tNmSmE znV>u|V%YQB9|iQHAg#ToB&n8NdwmI=`F6)npcs#JcYCv?wtPSe2rt~#*PZ>%aqvsf z&0=P}VXa{EJM5Nol%?KBef#Axk1b3um~?_+#pdtH6|v6qIFWfiCalsd#=}cgk^SGz z7)c9V8eq4Ky4J9eLaB|IBC1%rh-;6BbD{&G6Av z!u(v)dS8AoBYDHbuNU;Q&n0K5a+5Kk(Qf;=z(X;(N8|<2iGlr zh}wP%o{Bt?JTX1Jdt&&Xw-4KY3y!lG;t67#aa#utraC>JYSe6%0;z;kRpV0VdCij7 z@EQ-0GJk}ePxKR7aV%IPhBr2ltZHiZqn;?YH2y8i4(+C1$#dR%D4LQT>(eXsBDd?* zzXAzsn00@xO}t*xIWEn{nwePIQZHPoAuaNg_I7KCI%K(T0$wY*vmlQ)4OxHW4a;ij^F_9$5)to)ZB^v`uJT{;jez+j)9AkzV*$v&{eTerR;D>Ge0WZH!zcQ+RL5(9CQ?Pe z%E+0 ziyUe=L!o+%oje>q9Jya+%3oTwOPyZ#jNVTtRcJTje;K`)8ZRupAVytcy`o87|KW{^HB!$na6gx?wAU0SZ8jPF7Yt+- zz`dF|fE(RDDwUuEs%eV4Kx?GzrMt)l>I2Pk)+sAuRw^1K9`p#Go9tuoa=+yv|A*rN z(|1^Fh_7(~clF!K%($CG88&Gr#@?A8cg2U9*X?+V+UE9IfH6ATj)%R+`x8|x_KC+L z4^S@^b90u9U6ek<9uwrjVl74D04Cw4n3GD)`H8FRqO`81#WF7G*QA=bJNMgDbOm@2lzE9 z`%72vTRE)1b;moLsUwJ4jePL+EB893j2CqYbq#-b>_B`Xx80y89bl2>qsQxQ_R7n3{ zr`q_I4}>#*AX-)dHy=&wIvze;|D?g6caOibh54b${!~rVY*N!9zc;UKmXuvq;s1w zvUQOPXXCNuyWAGw%YX6g?~~}8Uv7>$1WTrF6Gj}Cb*MetcwRc73YWwG1b~&ob?Z=u zUilB(h}ig(7}M+P#z_to`4>r_>O>zgp zNt;(|u>q|ta^C8DiV!WFzDXFm`8SX2jP6g5=fm|$(qSRgqz~|tB_C2*W z%+2gTfj7Mmsb_y5@{O#qcUF`f0;7zNSMl<|+d@`0)bt?f zjNWwj1I6MYM_bCi@FOW=^s)0Nb3SatY@K{17VVk^F={YU+x7PV_Iw$XcfF1cN!xYd zf6*cl45UwP@B6c)|MY)XVThUr!YbM6oxQj^{o~eMxgY$dKpq?X`F~gg@AD@Mwn2wkhs1SUpi7g9 zMDD>{MRz!y+8E{%e{-04MD*@0zPKK9%S09%zoJdKMUA1kDAU4Qc_=sS`8h+ADrn_L0W9`h0n zL>HP^%-5+kfp6kJ|CkBw_C$+*o;=wfkn;N#D}3o-J(p@v$tIl1<~uHloZI!e^dN^Q zz~WQTR?=RImDQ6S>cK2nJiV=cRWfJz&435VGdI{A&6<1%I}chuH9vkS=KN-MbIPws zrvXEIgQ=h}lmgukTXp{Xx^&t~W4}XSm;IQi8A1j~bc4?`b*Z^s>3DN1CZOLw7f857 z`eFQN$b4cT?f?c8w$_JcJ3OJQ_Axp4if}z{)%3kL2Wkqt&umsGTufZ&qg4(4>*K@q z?K6rV@m$MJbsie$j3dp!kGKQs5}{k1VsuUsJVa#-z?+Z1!sNvTYQ966jUTKkhxyt}O^~g4C3E!d;j^kK=J?d(1i{qq@w88hXNqE``x_+j zJjkiGk)RP5si$M50dB5Scm>y|N2a#076~xP_0gS*1-073Nr<7ygqtg{eLh!!xAEOPy@lW#L>wjsN?0?9) zE8TCXhGV$A1R}qi!{X3vq_8nnLfS**So!(X@yU3wXc6j3Iv(iw6vCAn7dINb28s`> z{hLQyR+%|Rxvu5*K&mzmVPLI+F}c~IOD_10x~}Kqmw$lR>3u5iwBzZthOjaqJAmjAPbrU|o-A@>AXg+IiXdFWfz8Vus z`1Q-mv8OK=WOd|{+zKor)$r-|L*E*L(%JDsuGvrWbp~*6gjkIj^5_WS*b|@`<$7P{ zE~fc?n*4n~CRj~GaAcz6b&z-z#gv!S7f48nui&8u!VK?~DU5KDQR=vp>UfA+U8m5- zgrm`Ih+&*_i{!Ss`Gu>JP4bKqo8yTO#y(`s`%45M-7<<4X;SR28zQA~? zlI=-aSRKXe$yDd_{&bW`R%z48CG|5dSS@9CvlMWSp7_-yweU~3Y>Qj|04k4uRI|y~ zyZQ2`)midykv4x>p+(Y=UQsmVsVlX!zF42qz|tVJR^+Cct7gvHR`XT;FeEG>zZ}`;N?;y)pHSXvBXwDkGCNbyf&LMq$AziUdw^lKI7+%`mhE*7|lH?$&B+ zdX7o$^)}eH)={lST-`N_Z(ee9A4nj*Cbd*ie9xyVXmkg2UcLT{_X|Ny)gV~0;0XCg znVHse(*c}ZxI9V|Bko__uK%7=UDK1@S5gLIPUMJC8I^wgXUNSdqh#zwjV0?qhyz!F#MUqx27D@h!d@>^u ze#bL6VP#Un#P(h2qHO>0I&}caa|g*!7^v;`w(V|IYTX$4po=+dKoGmddZC<=URV{u z>7aMs?E}7Xd_WU}e!kE96zn906Y`0?Wo@>Ir*M`a>{g*J@$6z-u`)y}UVC|IcgksRP;D=FZ%%J@*kHq@N+g+j<>bm{c4X z&GUjB1O#a&^|M8DqO5k)*UA)gONL2~k6S<7D4Ebl%!|;MwL^t5-_vH(+c)&RS}dO8 z7Lq=usSnv#yFyIroWUgGeOG8~Ho;QicDMI~EV15KIvzKEV(*`y47UnPuRi{` zK4*dQvI(%n?OIZcZ(40a%{|t?>b?4CgCn{2EWmBYvGPBNj)!U1yNTEp-*6J{IEnO` zFCs8vy6Sr;!1G5TSSxrpXRpjjfe#%PZI5+MyKtv?@DX`tPtx+yzhX=gynke8n!Aku z=|E5Z9bnsX6#b|B(KDE{?(>aaVZVN2ThxiCB1&vwaDsf=qErgaMM^g-Kl>y%zz{aa z-h_)hqk>}T{KILtqS@HgjdhYJ?`EpRUH9O?#d6RLpjxYk6l3HQmEQ}*_(^HHc7{u6fG=LldqBRM%BCGE7 zJml#*klz$MpYbuFp>JW-^^+`1ctx7R3to_qdHJw$vB%V+iCV5Anz0j^f}PqJFcHCX z#9LBtxSPE35r42zaBBXj?*XZRF9fLZJTW)xG2t;)51%XXQltltn35VQbmRDwKk{VC zpayN@*12`HQM8=BiwJbjyr(ajkO~T)}(63Pg=? zcB`)3hs}*5)k!Kz4^)59mLZ~oL@0m3A6!C`Yy}F5#ja_Z_x~x}Cp8)vKy9mHF!PX{ z-oTs(*2{&ei@R>db?F_}EpchC(YyY|6GI2z77i?aO#v0U<16R|2Q_1egWgnn$H=Jg zxk@yvUNEL`Bzwq#9N^Dp^#QGa>~>&*Bvc)s>W3rv6(y~kE?aC@Qq+&R134A0QlJg% zg_jOOu=Q{fDv1G(T`%yxcg#2G&uBBAa^u(3RRd4_LH}IF){j#=YAn|_;^{14t{&Cg z`@iu13#h~6bToMu?Ypm!=&@0y_0U1b+TQtj3^Zw_HX5Ww+)NM*w|4$p#3;m3e!SOJ zU)DOQUgCKg`3oXJGlWn8B)AQN_ZVhgGc1Vr%Vlb5DM#1?Nu(&xzo@W5t2&XdRfoyZ;GoQdoDF68x#TDQEaFl*KbCs>I!NLP7oZyDGge_EgM>@5}vYHW^wO zxShPnCGUeHc+_GCSAp1n{xXeOk0ERIy?$FM(BP{W6*FJJVB3GI{ej1hE@oMGYEm1} zqIiBQ8}C)?=^Oc&23mSvCO}_%wPa%Uns0SmD_#suRV~@R<0w0kfUnd}syz4M-Z#8! zi76wpM_=n*^S*g;sbkCK{I--KGU?~4TQw^Eg{_;;t|i_wq8N;JeqkGLf}Ec~7h9#ZL(wC5uXtrM~|@E&A8w1ejsEllwU1|A8QZ`hDEV33RV`w69)1-9>)sOsD>BE|E2e?su!Fwl=*8&@Fjyw8sOP~{!`q*~~|HrXk! zn{zGw;ab_;?qyj<7KlC0#}UaYZ=4U$ zI5dVXSp-}@J4zKg62E?K6fZ${6xcuFFa@mo@i43*e9J8%YH>u#ihCH244>eIo~qU9 zpVUO&Hp$%%#9bG)qFYcd58B&SJ;N>6inE`L_3rkb+R8ljW6O9Lc>@V_`Q>vv)1j>B z@zF|@ZsEKByEXbh{JqS4?>`Xc4Iv#?@mXtS`#7!}gne)R)s}7NPGfLuiqwQkcKBU#itK8{0)T_Bnj_iTI%1u$g05vQ1g_rt@-LWt^-|>Od(8xKd$_@J!ZFVYl@0B` zAMkIHGVg2Ne^zk--+3V2pN0Ubm>;;~dg^)6)<&o%ZwB~z*ItdUfRI}pEokwnvly%M zi$s~;-lhZR>)y|W71?_YOz91NC;4Z0yPLj=Mv32PDN2~opN+=26!9>Q=bM+FBTOaB zW?ot?c~0C-Z+nQ>%2G{Z;7ug&8vMeOs~7eTlU`WPn-yE7xhD!%*+dHoCbfSzd&Z=b z7~N!g+k~Ii-~+-vtvmmTqC)#9%MB)qayqR&k25@gZLUrBS+OBq!%iY#K>}a=ok7}B zkC5*khA$e_$Ob*h=(C+agA$&H)h>Lg=F`RW1#{-DJCoJgrHCP#J(kAA`DPC>&rB;H zs9AsmZH6wG=E0KhU-?AJ1HDnS+B2f41{+{17dEBLxSsk_5UI6IiRu;yVyB=bU)1ClVs(Xj-9HD8A z*!_XaQ*6Z&3cA%`Mm_i==s;5@g{1rmH z!{37(zxqsFsOjXWxmVx6Og*0FxsgEDx}6+R&ABbC9f{9~gNsx)@D1lx?E+NRii!hg ziN0=L!YtQpZNf&=q1XM4p)k3Lrm)MPXT?p?p3GcrEiuajU4ahgf7wP16$eJ}*+AuUCC5jh&VI!^*xb1uD zRu6bvwG@%Xm|ql&?rorag)*uC+)dxzrrfdU8erDRhuR*E+aO_w{s!sY{Sv}8tCk}Z zE>en*-4e+hwcmozuMx+6rX(&Y^kEuik)~IWTwNQ*A5jWj_@6GexKsbR`xEzD9=Txg zmWuLj?zinMC%Z};P{_ps3SWKxIrKa_yD-fJRWM|$O?=sGSzgN6(6D4Or8J=CloJXg z2gyC(dreI}d3Cf0={fx!VXNLeQS~pzYPRtDe+jRmAu{{?>-_4xp&riDt2-3slz>=q z^`Fp}J`=U=>2zA3uou^lX0q{00t3M%4vuDdQ?AXohvtDI8 z*%A<=iYaNGdv*h&A5{X+()@{7#0BJQ%mX-mA85HS)2y%#*a-IECWP-|r?+VXSd>nD zou-e5XEfU-+FX@#V_f%f30olS4MeB_U?gQdBL>l zE2KRqceFMamU4sGyCIc4fbS+-G9P5Waj;SkP^?jK#-JANpIN@=3cZR?&iBc5pi1Ds z1`@jWbXwR;>af4}M&&7fzM^{2s;#xtll|-9?ehnOqc!vvuxw|uID+tRc<|g0;f!qD zDKsCLb-!njK-d2#e(_%apBnsGBKpn#1i!0j?h;a{?;omp$x7)Lp|Jd*{s`d_cn>}J zWa!zPrQicn{3**xEALsmQyy-c9K6h%Uhh>yZVn$rI56(AgoIyYyVnM=UqI=m`9%9$ z+m%6?;W?|>5)&{===nG-d_FBq>JDyh{z@D7$A=_?Z}FauPYDJ-`fYgyNlgLXe~M-A zkfVv=sRv0+4gbD2#nF~f(@!?mu}Y3XyRKN|hc`t*NeiuhtcU(F1Mh^sTLy1?jv22Z zYpijJCARU}BdHEaLC8)7-S0o~>q`SQQk169RqtDS23oLxZZCNjqE(p_P+P4VXpuHm zR;_NS>kMC6-ZA^HfO)W5hwUNDQ`M=|G(7`+PNd!I0D~^YfAx9_h<@|z)zDIr_S6!1 zK1n&&)PzRD`fGEEeRMo=IeM+8r&gw%?`VEEKE@DitmVuR$4M{?Eiuj(0~S1So>Edy z@mI@<^KY1wtyp1ezHzP*Pr6m zQ(L(7fQ>3zU*szLKbfAWL}&tLX{4&Lx9N!Xjiie_BXnYqGFi4I!LRZ2w`uYdl@%nN z=0lVmACLEBWBg1JP=^RE*+zQK*;i%Gzj)h{=yTd~lQ~q4_%tk19PKOQfHI$%U)EO^ zE3Yh%?ex!XUc7v%o>J`}^vvxtxagE??YZ0;!KHT0Cl#TvWb2_tAa}$5{G1>Pb ziL7O^M-l^< z`>p)3^SrUHteBkN>$s{%y<){<*raV6HC3qEgPLAP2+TDG%f2@+8I zq$@FwBllb9z#q_a-6!R7rSi+ma5=}@R7!_dEIqS1IfjzetKkqt=4a7fOBs=((SVUO zPxDrKjI0?Rjw$={1|bmOm9O(y0S}GyJaQAxjMUYvP(plV@0X1gBcw+nwrzO3b((z5 z_h(H;eB*6u(2WK1AbeH8!>X(rH0-)H$-Hs>Wc-8YKqw*Y%r!dDg{(RJZOD5BR{h)l zak;+;8~o5W8?T3d>cvqd8|8rd5aRW7lTIXD0 zIGGhcR`#>8%o{sh$KUYWXI%&}AW8GXNdBLOufLqUe?3nB4!Z*X#>b#l;;WcxL!+*M znCm-ACEalxJh%v2?&1Slb*Y)5NSlNg>${u!U-VdQ-u)4i3>_7SK*ElVHz(s*oP&)> zOit>ckzjm$1cT5#5AhAM_-@la)!ALVT|}Ur=U0N~i-;ti_E$OjUT;lL1yXPAE#9f& zO>AP>;G2pSV-!!(kITAfN1Y|f)FP^QAURF3%bbO*sww4Qct48q9ZV{4I_`6tYAxMe z?>o+Z1f`wzPA+@P><>g4auiCmHK0-y0mZw^&9stoBdf~r_y;L=d&=!oha;g-{hS9H zc}JQCzV0SD@|P$_&O)WkDV&umZL}W$29J7W^)T)rTa=fXJ7Y?@~`%ucKKmW{p@S*TeHF> zoTi6iNgKs)mM0)|l%{vhJj?Yk5_!S!2eV*1HA9U8>`pIRwjw9(iS}v`p{rfk(bo^M z(lmF_A%<`&j!|!fPKNn6QVY!s+-))1a5nH9&TB-xu4QS~zNWJ7@16cs?80XQ`m8QY zpc#QDafIc>p@PNh7MO+$bn-YPaIDJy5zEiwH>r6N`I}bq6>ui=H(RdBuU-fAhE6l3 zeM$(VpLXY48;#*mbO`~>caJu$Z14SboKy1jhCt_H(pF;Vy3&sIXL=}2fZ|)&p;_Ny zR=qxqHJ4V0fk!Lh9fvfL?XvCq_jh$~0-TAnvRUkomIiiA>s6zyVhd`9SrMC>I%Al1 z#wDAY&Qp*HB9q;sSw8dK+eorrplBFg@}^nV)zb0ORmM&YVt%b<+F7TS@v@WpYL3zYs>)J7*c0O*mGvPXE$ zX5I-?S-knl|A2zbd`l)EKh{58tvOne7+`pUJ^xK$INxgi_3w%`=KoUfxi35K=97BM zcz;%jsFKC|sYcq3B}}xbL@#8~JRhUDsWlWk#+~!lE5Q%_bJ6MExg+*es_b1lnhD4l zn-|*n{l>FQv+MumoA~oiW{c9RTTi0Ne&Z(=p!wVJ@d9`PV7J^=GW{kz6R6K8Y!+r1MOmoTg00S< zzd)6)30)k@9@7Q;8WojnKcV`_u?1wM2BT>a6H2Bnc%O@>vhi-5LDr1d#g^lTT~usz zbf2}-70%O)+M`w7O%|~5$6G%Nl`5Y0K2c}f)PK&d$kh5vV(0)MzdM@PFs@eepp5^Z z(g&Vfe_vQzjZhi#Y-ocr|H?b`;V@bt){MJGci9MWUu(Rb)BX2n5=}np#WZ z4^PFtGJP85E)GPq4_q+}3~yaz!&y(W8;ie3xH!bracN6ZyXioQ`itU@IWer~3{{#7{;( z_ygHmLh@Nk85l=A2)v9MqYTT@HFS)jetwCmB(Mc9`BQ6e=`rs(xno%FFI1;hvO&K~ z+sjeF7Q?|6p#r0GKTkU%sO1eS)N^!O-Npla9w3)__wjBXo`Xk?02o{VaQjXHE}6nh zt!C9!g@H3XpQ&b)_Kz12}4X*b-8^1y5fgo4@jU1%OH2 z1j-07mjEzN3AW)@mt4G=5H1>ME^rzEj4;3b=SHK(GB7cDWK&eH#nbA|iAi z*sH_BRX^{r?4dln4(Xo0pArZr?RYjpu&MRwr6jIaX7aL&i?^wnFP`q4ZTl@o&Yvep z9*6(4&RK*P{~aaB{%1y|2ak+u|FhRKN8EP8Kld{t((x6#Ceu2Yg1oD8Nid zNfX6Kc~>U_BEoE;2H$!PFHb18-##s&QKa*_cr4rGBm$R2r1PfR2wbe7a<%gixri$j z>~=*p(ZG(%&2L@+x^n+Q%q&mk-Bc@nkQmouCW&5C;=i3DKO{b7F!?;;x2haKuXj6O z<K>pOB^4>@~%eBeIa!K4JEYCH|>Bb!C_s!Wif_>h^i_ z_5J%1%(J!eAg|G;casYcGsHBkiFv|g?@r`ky?-&95;D4j7bsq)j@t_fZzw z#7z_ZP8Pogd(F3PP2<`My$*f%Ff0qY&-VBKRoI1E{i`|!?6gWJO8;`BOh^zdB#+C!Dgbu6Hw+1X z8NJ`Mh!aNtGnU?F{!gB=u*W>_`Z`BX{&h60L;-gEP1WEamhJXxXq6nKmK1V5;CE9$aY(SK`94=$ayM?FU7%CD$%eUzx~a^4o@ z%a~X%p+i4Juu;oEABI@te>EK<=SBj&IvIGKAWtdZhWlec&qS)5Y6=;+C*bC{19!?Q z0T7EGdhy0#!!xf@`wB#xAk@)o5p#u8%)67qFV^fObn!Ya^s(QIHZyV3Q=dn(ZK+T> zEAQBIJ2fAEqSGm|{l*>y+qKelx@5u7RrPNR${VAL|2>aB3qH;|Z#D9e9M$#j0%DPu z4^Ix8<6|;_%c$bel&xBT;C0HTerK8RBsGbKwBUAvb;CqlF)5uuL9bqg46L*fGdjg& zKhjB{_*SaFg^A`;^?3NiyjJ3yf(9(xo7|p$)6-TNpEEE&)G$nGE}|cv zkGDSJTfRY8uj!(-X^-GBl9sMxsjZ=!(&|2j0l?a`F%a22a z%nd%d>Ub4$6$>I4zFBfLeIgFXmdO;QFlUA7MSl@@5ohXkIq6wl$(wnfOY=wGhwQh( zg@B#St84l(HQGP3JKT$jH|vDAo2dWT46N(nlg-M83>5Uw_SYH2+ouZ!p4goErLP?- z>G9Q7pQ{K|FC>r8-RB`J_LPp^9hXR)o+~FU2O+5EZ3y0nk$RzaXqJfNQ(~n5D0ceu zE4`M+^bKd@ng+ex9c%2+v`mE8%4K|iTm)vZ93hS>tO`G13<2|eY9CHbNH}J1FPo?- zd3QejFNmm(>AxP-E%g6&dHCzX*LPIoIpsx0OD}YaX9nJQ0%&wTS{k7HoBL-eQOnwI zo?B>!t{;(1PdlSwDyZ!;C0L}V06E*MxSjhrJB%{1U~(;Q-}cTpDJq9hB)I`3-$Q9w zK)?Q_aVBa6U!K0zlEOR>D4$NXuRmRMOuuk#0&ro2(l4AGkHh22?dDKGLJVlGU)f1> zR4yOrb^I%yT5O)!bsvn4y$Kz1iV72rtUCuPjRwja0W-ID?CCmp0Scf^9=7E5e}5BP zZIjTlCM}3^p|{d$_D*-U0eO4X3(=vAs$9PWm*1;--yz+#P2+YoP=-ur^%Cn!+KTU> zbHQijR*TAHM=L;H`#$!5O=7Ji#?mu!BCV&?;z!1H>Q5@POx zR`s_lsRB9@>SFe9*@oxrXHC2!Kf!a{;VQX<#&IZ*uU;)f)(e`jIwdCruBkm5@N2lb zJuH}{f5>vNjm;5BhA?i$IEW!84&9pJPSdy2jf#H67T<>m+=M{QX5t-(D-IvyO=~RX zm>*5svf?%img-rY?9e0YZ8o}=;$BlLQoc=oQ&s3!=oBokFMKT`CABotN-IU{G+In4 zl=D!nI4WwAq{ohJa7rY6-M1SaxTxgLt=k=a+xIeh@oPVL)Y)}2X6>dIGQqYFVR35BXFkwm+1CU!LPYH;3ZxwHqvHtG^3NCAf^7X*a0@{PO#R7d z0PZLhteSg1?sxtc9<8&V|F7fDvEax5&3I%5Mu)Y+sH6RMY;f=qJW{v4Qb{%P%9hF} zRPqD@bKVcQGB&o`A|mv<>`?S;V{i7YL+Kyg3qdHauM9g{2GRq3rN6JpOg?2Yb~;u) zLd!WBKL=v8fXPF2t=oEgyRFvbQv&%trMR`1q>W!d6BhsCnSGsq*uieN=P=JH=d z-HJ#%Bem)G+nCb;6^W@#(zR>)OkV9pI%j|d_Ch?l=BTpB6i`D1qEEst1Qzn9)Hrfp z`?Ylgo{8E{LZ$?K>fi8+i#4IKgbcWaJ&urF6#`tXZ|^VmwgDePfK8g1!n_H>x?eb! zt;|*L>@SK7gw~W-37K?;<8n^99gObF4hMO{IrKzUJv=34`Hb^C9JaH&rArPHWD zWY2xMp+IYH8FJC#dq(ZH{2E_!9}}k6>Bjnz_MaxR2o=AqKaD^1LN*gyR@s|Gz(SF; zn_aRh1*v*b_BhRg%>8Jelug_mfHq3~b_<2s=N`w)61bD5ZxTQAqAuGU`=35$+GcF3 zscOSzTWPU-_&iU8BY>9A&PPxb3_E?;4sac}6;Q3)WH0-PyF#Z9@!uSb|N1>{t0@1Y zPW@%oe*B+x>~im(>ZxkSsYOB5ugKQ$^|K#FPJYIj?HNq@!zU|uAql4T1K^KW|9}9+ zGc;O@`}127r-c*sCSq-rA$790^D9ih5@)9HAtQ0I=fgGs%>iiIjf{m;%CX?FA+UH^ zn?^0d3E3~tl8{jQC8pIkn0jDV{7y5oXb_%!qHYz&g?eO_H;t1;lxEu+C7p_=1o77E zT(cm)+xDQ-_?+se2ZE+%#$&Xbwt`E!V~DF^NFO$Cnvjr}sE_tSEX@JYjK#?FrN&daQEq^@wn+h!tbNT{nx+c)L8xC*L# zi8AIoc(>m4GKN_!8EAN5UmeJ>=NtEt$G?oZx6Lv>dH4!fRz~N=zZP5A3rAD7j4>t7 z|FDwUajXQH)_qP}YReqp?=nveus?LQow1kiD?YwD+?O#u_oX*&IIJURv*}v@n{EfS z=9o6!{{`O<(I{|(UC8y}qzJ(PG8iTSA=mCifB zQj+p)yv?uV1*{nx)}Z^K_v`+xJ43wZ;<)*9;z=}g;@S4!tl*V@kwE{JkpCwu_@lr3 zw<2gw6<0KB$}is;jBrgZsH88uXEk>$DKxYjAW>^+of1Kc}P^ zBwv7Ox0)F^ygE4SAZa`oqj!-j^El&?`-?8cIDnz;A(E%ta+I?mN`nUny^I9-ceOZh z1)QabSEsm5pG$A5>HsVf?8oVAeJa>%3XMS0%-UtXmEH;xS@q93>JbX%RCeL=_w;k* zXlRgmP>3f}3P{ne6OH2gzOpbqk}KDv_LW^-p#6bmx|!Y=pExTIE=Rj!0$(_*k*csu z_s`H(a!GQaWen&Omw&QzWx4T_(iYjQq^s=#^ubuiNeR7}?^t!ZfIs*ke$qWR$Sz?x zCWyqc`Dk30yzQWHtOjFFy>oh|;=tfK5uU_aHR$D0W=?@vsth%}7tz%inyCFAWA(}l zf`7dQm2I{eSe||r*H#sgB`JRL6SoHR#y8avI$4SdEI264H(AU9BRfrFaJJIj1oP#^ z)ikxror?_wqQVx3n`~7ZPO?#Ncz(^5m}H_M)xjL-KiBwd70Fm{EHO-AcT|$1@w40* zn909D8Z*vh&skgd#r(OQEw0qZuNh|y_k zi4(YfY_?gFQ5$t+nne2)SHk`P)#vhRBwt1=kRs23 zbT)02*~9CjbtVxc2UAI?+&f#oS{s*WWb@Q{Rx}oDI6YfWklOZ(U+5s~hz>cn!R&?2 zTPq&!Rk;unlA|$f_JtH<(d$V;F?YK~)7YO6w~=(tb`h6U`Fs z{C71^YB;XAS^qC;z>id>|GIDqD?2CLC{oYaw`jEb6-zDEL#YaQZ(_j5vg<_!*9_VE zuGi;HS(BBInO?A!PuOKSBB%ML(4hb~8q&^uDRrru8ysBA_VMTTGa5B~Dw`h_3aRj;%)rj7bH{xxxK{JHk($^OodYyP-le-58PADG@i;?|K- z8HiFj9qs+HXVh@FU4TfrtU&^TDU4Ah;7`eBllW)#$z`nk9-K!u%XsK)lf;XK!M@Mg*CSi*LQlQwcfqVrw+v^ zeO~c3ufsYdhC*79)K z*U3vCs#Yx#ie%$%i~VTN6c`O^Le*t3qxeRkM31T)v#H5DohCxH+i z)v@yLw%W93e^H*Xf3tky6aP$`J@<8w+PLnowG*CXZoeubx~Y}{li#nE-DkG1w*md~ z?LKf8;&wzboC6v$6BAOu8CBf)E^c7<@St=7i|F^ZNvUYIfcUfPjLW2plhR2#xB?&X zuUluJ^m*V0_(gF9AL@vkkYxG^FXzeJoC~5zj=X|Ut?7HZZi|I4;jzDiJ&auvV%4zi zJCv;TZ2cA*IqRf5D3Thpra9R3Twh;?*NF01MCu%{n%b-*W&j$->=S;&M#WcCfBYkw z;^>XY|3(6V?OHLH0|nokw~|L0!Sn4a}~n^zXXBQ@v-Hr z5Om&dgea!@)U^j@i|N?x+9_M>%H!5)M*NO)AL4roq6t3V} zyPAx@K5lM$kh&DskcLJgBT!@M&%NcB-J_Nc{Ca+)ET;ZV@j*#^$cvUfyH@dt7}fIu zPk?9sXE#bt_P-7xf5~#0r?wdzduF&oDD}Z@wbu3&?E@Cii(w}}Rry9eYxlMl0p&W& zX`%h)Xogu?vrqZr(o##>?+guez!^_hJ43^T@O;{iXoaO?92w$zeJ)8!DNgfk6n?p7 zGV@QNA#mJqDi`VZh}=uWyzf|BMF2oTnV#IlXDWiYX!Bg!;w2!STqkUtnz=3IS)V!^1d*M_zIWmP= zI^G4}{d_@;Bue84b$D&*e2H%a3E(oViFy-Uz82cgoC}je?+7$wzC`8)(SGY+?cCDJ z8a#2U@1WN-La5Zd_Rvv-4s7dfdtJ!wEpQNlqy>5A2C7CFSeLjPynt%^i}PQAb(@FukQLio+Uk$HvP0HP{N0$Wfjv@&+vnAYN}cjb0mXtCcZoJ%uSvP8m`ex zgHMNjnlMLt1&SX^6ymE!1p*B0H`@hKUX6?7h-&gobcTizQ*AU?G`a!%-GPu0eRy(y zRDbcW%{PMS{|6Oh=nd{V$3;h-=buGGqj%0m`e$^m>9Gc%DHhyLCTw_hV|4+L(>Z-v z2XOLu^Q`BZwoDwhwytvR0*DfPeRph!*vrDPTjnT6+2XaKU~UidSis02j0(GK zrHq%yYYsV^jI!HkBRBH%b%NUCKG46kdrivI75CYJAG%JECB&kTRDdDlz45@j2{d^S zPAa?Q9(GyEZpa!m0%G>(d=ipB%+^2?9+?71IF$h_gy~fq&Y@Gr^4>t&U#sY|o+k)P z3g>wg-xuZh0HI<9vRQa*7eyLgG9}<`@1qbrGu7$ob?g(&77wxrrHRP~cenfAr#tH?yd!Wg!LjV;Fk4^F zR9FV$qvl7SbnmL4D^&qHIYWWtn}i4h=JqCrj;vBtJ<)mwd%BqBI$o$?6wCp~rp~!l zDC7541e!!^2;nIIC~ejQn@5C!5Y(CVerS13YTdrd7sRWrgyd7e`EvV9?2D&T1KI^#ykMJ`5@bgO|ozAXQ=$K0W+h{IR8kU)KUPPJ9vaqobsp@?1>EsIZ9L#k(#`i~4E1d% z_s<*jqb%`IP4ICb6!1All0`4q`Z}0F(x)4xxY&9ZR2wYFr^!J(H*la_+pQ2Dcb*^A z7`lKtc+tEvog~w)qNR+eJpGzd;pIDmC0El-)C@U=2hi9I{h-W@$O0gsa8jyVUnrlF zEZJNLeh(Ko)kgMt7{#?n4S;$AeKoTn;YF*LsD`#9MFuT1r;@7)#rSG=x_tdeYakC~rWm*1U{R#rY-zv_hH>@7=E6=gAjEp%BMrEsbt6nm zRDW_oY@H9+(`BB_G|NY6Pr@s0euYU)m7KB+BHOgQ+P88S=u8mlE?pd2BIn^G`qqnm z7XUR?aV2*TQ9#tkSEwGJ^{Td4mHz8t@k5^W|1Lp+i_iVK-H#wa{6R4%nK zK!q=#04C$~WoeB7YqdfIPhjgsW4zcY?Bn5H=cS63x3@Ch6F!1js*RFzb`JjB&{Sl? zxI633mmFj{2wx3laMb+Gl>X>6184w$dIfRIvM@(rF>9#(`dN15I}+k)IVA>GGV1l+ zVOV10TupGa=(`ut>u0;J6USaNmAd5OdU{VSyZpBxCgDYLlR}$r1-@FRo($6kYra~U_1koA=1IM9S2a#g3IIUl{ZweA zm{Hzo@xzPvHTMU@VIzrbX=;KO?w(q`?E>HJqtT{op~eDBnk%v&0-EU3b-A@jw6jLZ5Xx+^U2;d6WpBy zsYO#Hgd0zvm!SF~T!3ZxMy|i;$xy2i#={;6(w_JzuOG2Q89AXqsiEi3b1*ZSgZ;XJ z^lReAXmj+w$PWN~jj?5Xmq%s0KJgwCQ{$fB+wpjsrU?iv=eYQ-SwmC?kGgBkck%FR zuPiFAT+pLGcx0C5;zB0P@*d zo*RYyj33qUj{yTzz2}0Y#7DutTwQFA`8Jb(mNY<Xzl$%W`O>z z^GMq2^zp-+khQIeQUgI7_&f`Fq=$L}FnSipEJ5e_|Dk~ZNLbR#|Lug}AsU^33O*10OVLYcMn|ms zB2@Z8KQRG6b+F6q(k5GsEt)?|W-SR`5Vf4Zci^ueo1-jW#?_sV64>%er)o%1$s9pI$aIH|jZU zs6o+hJ!B5$A~NAtoys`49r1qt!Eh^aLb}SMKPPCJ4cl~_;-avm=-NNMq+SX^gm`ZT z3T_)R?3Yx1^ohJrK**~+ZYN|xG4%(h4Ur#Cd#YvV*JV!GOni9`#>(bkG)ZmeCgEm~ zd33*rJX3GY(=FewtIME_QGih0nz&L?>N6G&SjO`z&O$Ras-4zP21Ea%{L9=mX5Iw& zO7Lrmey?S_jcsS6^zRb<)`AVW$ugx3X&BX0X&#ce)>jpFsJyGP>WxH*MP*&##k5t0 z@0mL+mYtQhLC28X0*&iu<4T>_o5zm^f|tz&uEr3tg*l`9vYt=cqVUbs{?#_~9-|0Z z)#gPZ9Co^0b4(Mte)FFaB2s(Ybu^iyV)t*U^AP}yh${QLPV0&|?wqgs8#!6def9tA zm}UKc7#(-QjaL=qxjrmjh_VRyh@d&xyAp4kYFZFYG0nmVfP!;J`KI4{&R{Q+OI#1w zvs)*kC)%$?!SC#K5RbxXogeCJF<>T&4XGrVy#1@aAbIP_%%Zkhu9)2cvx4I5p6Vu{ zseaqV5lPO*4d9j_^DIK-;3osQFXB*$igC!UmDu)prJO`Ag)M|-yfB~(a&$Ku(^jUX zDpDgXst9R~5|c^(WXHU>B}BlU#@(|%jc<1=g?w+cLTw5n+D=1quyv7zYFvT&i|+e}h|u+z5Hw%C60 z{>{P5dVj)>z+T&p+KSD_HHp^OZEHHiIs<02o>(7AfZGwCp4Gu(?!i^NS&_Ch50o81Xg9eRYhnU@QFd3gZskrJmClx#?ob^=u2BU-%xYF zVT;I=TeV(x4vp4suX=V8_~vaG@vu`s-b~8URb0IZtt}9i^G3PLD79Mg3@C9VT7Xsx z&;G*gprcuTXND--f6g7pug-M7{@XkS{7}6J&^PJ?O-i_9n9(D9Yxh@ME2)@!)S@22 z**E&^x{!W~W;?Gr^6SLi_$24gU0trX9RlV(0A(_AQ==ti%x_KC9oO=ZQzg4Mmtdzr z*o9LnWzIv?Bv5Y@`l}kVGwn{MUI+|>Tq0 zC1bfFiQjT2y_@P(dS`6od5#>5ZO5cY@AA-bJOfB&$5$Y_5ZSSu}QY*gRs$o!#1{v#o}Kx49;s{M@YN-9CX)7&W9SF*xlt zV_k?K556V5E++`H$aLb>qJo8)Sd&DzrS&cVl4}1xI?zBUMu3 z??JxS+*pGL7GjUqG-&WtP7>GxT$yb3`BP}KnnHre>NDEFKS#`Sl#O(L^m);L z+>49ST8{Y2`3M!)znVqOM<*oZD2kC9RIBw2r1g$gPAL&(@o|2!=r30}n#)~WmY?YH zis(SvBJ~18Xdg7cr~S}BZ*m8Ex%Ow{ppRv_A$s*8xjj>r0d17#s&Uuzw9m@rKT8?F ztRZ9rpbIA&Ujt-#v>et2ur~$Yh9&tTObg{=iVhmbvZ3cCzXSuzJ_ zvam3ndHSUp>>msCFmWuJy58CIR}7Z9>N zCaQ&1>#S@7yQ%M}%F-czz@^?`L2auoEjwyk~u9 zvj-xCgkvn}Hz5c651JdGCei)3?)M6gXE;;j_7b2vCBKbo%^%!lo^JgG{65vri ztkH(~GIDrelYs`RdhC&^4$)h|NassoCOw~#Y!t4YML*FpMO>Fm3LEAYu=s3Z^M@2J zVasFE-FfjqtUZT+#6~)kaKnnWDlo_atK--F?+Kjo_q)RVOCJ5Pdl7gU@9-$Ri&j!l ztY~`UWmH{1B{0xgpQi9%n;=b;U!4LU9}y$~O;3LvSW{EK%vbL(`{Bmnkw-#?5;pSf zi1ZYPzc^ptUk^|@YHzf?QEq~6>&{tCbISC(ew?KcVzBFjo^myL$hczSGjqpAxZr`8 zcnaES&EqXuuNOlX7|@OnUHKEF6fL2Jp9JGd8Jy9(YcjmP%D2rzkIZV=ulBo_C~4iN z`8yHb+jc_o3*+K z6q`Wjdru@&dnN9;l+=Dfyq!0l_q7~~RQ=YXyk?Bb{~cUbDuIdR_>!6jaIxVo9a<>` zb15}h0WiTW{xZ9dn0F#-QG!@x)GRAsq6`3No_^7>UiJ2dbY;UqEJDjGQzt0~t@2@E zojcU<&KmsFjdxy;YeFwO3$Hfj72XWUq)d&EtinoxYH;@D@|gpnU;PtpJ2gj9CLP26 zldb{!Hiy;MUF{*ldO-vI%EqM8a=G=_H%=S-I{%}h)31oBk-uG)8K*##q(Lz8GGUR zI8YGqpKTU5$6rh2g`XV%IcB`U_u*k-CpT2jfApfxCWAl>ZS&WP#D_uWCmHP#)*@Yf z&|BW^m_L>;RO4h~RXXmV>A1jsotOI&#Zf%~GHyc~=O_qgU;wgtTv=gAUePFY&`&zkTal} z#G0=Ke24Vx%YhZS0Xwzsd|tuI!SN*$vcr&LO#$ehv^_udHXJwWspzGnrT{`-fbEfO zG&~u5;Rt@AC;il|G=#(9+n7c(#xTh!$Q)v$nz^-ceRg#p+*${itkIJO9KVAIKLlfL zi7Me;xAv#%Fol^kk>;>ME|enxQI^qfmYO^V6iAKh@v+=2g)L%a=X{^2Wq*NLbZ0yMha+ctv3-cHYPi29%$O7X}|ToaAuhX2okV z8wbDii;@<--7a$gDCywb5yq33! z!8zJuEQZsoCmO7PlYyqxE${sri<5S(O8T4m%$&>t?>Fs0NvyWjm0VyD5^oT> zXdBFPD=4p$r{}MkVaer&tf=re3X?`X*1(+vj6bs2&?u=bm&EI^{gqoq@O;9mGf!J; zOl~-0t~6R@2Rqcl)|Y_<77;ydU>m-1J?#*B{Gv%M4%PIvV{A|aZ82Rl_1a&+#I?d# zPj;4u*FpWXsnkV0bd;1K0vU5XMsoSnJlSeYe=(OPt^DfR^sRws7=JnqMo#>*_WPbb zwEDf&U3$N5*Ck6V@$He9J?I!-l6`OzJddwe+5sHUA5wyA7e}1nh@x5W;jw})lN8Xzz0j!-w4Ns%|h z(qfZ}lwXwd3J)<$NjTqsRU_~sj5Uq*mcPxi(Kwnu!wLvgN5zO0XtfrjX@g*tv> z?a>=cMd=_n^ZW_?r*Kk?hU>#V{9<;XA!(&+dVZZd5V}I(?wpA-@vFN1rkL1L99C59 z0;I%>f#3dq4Vk_^E=O$l$Z7M=OB6ka{7CDC%7~Wa7Ne{~=B=z2j3U={^ROJO%{v;Ns^=8%T8;;&UQ#22sX2z|t#D{tplIcW5G5L(Xo}@j6;WXr33Hf+? zNY7IWXXk)uc8rsEiuu)7;zl{93Q@WtSp&}SWlEJvnLIPF7ozqNpek_ zSRPA0dkTK}dqdq#pP>s{8+7`Ujj^eBhMzKlnrc4fB#j~>M+B}qI&VUH_j18-pN`{t zk>1jr>-^1z-LWSfW-MThmnMxX=%%Z`OYh%Cr(qNBF|m0qx8|LfKbl?(8&Yr`I1DgY zy9ePx*u5Ed?ea58&U(lDXSh|Vlyu`kYndLtWI+)I9l{$T;WZ6erQv8PlK7Mep|Vt} zr38x$t|Kn&Mw&BqL)Lj1ga%QxYb3MwgjW5iEYCurm@|WK=hcp7ApDgyOh+Gq>4;#>}~6pM4aSw`igUqF^Pe!#VMn9|V3G2S7l`<;wV@s7(kE1K%2)_`aL z99(+*?9FfERXzAh9%I|BvW0R+;UL7&hGUF@I5_5_*PV*XLi=HXyd`o$qimv@BlS_j z3zKn=t1T36dWG}#r>&S0BHABcG@9T>%C|DSluXGaqsfJQd{Fgz>W#4MFrHPayCm%WhVvg*Cd;;iq;e+ z2k;CJsd!@dE%lby$8)%bg?SI^cK%4bn8QEa-tBch+R*x8@;s>&WM4mBs&Z@1DGj`R ztLZkCj)sbYKqFDvzIrW>%wbx>?y!l%2=|jdX|3rsUFzlG!k$K2e5((GB`Ucq{E!RQ za1yqUzl&)7=WXP03D!NL`LDMW@ZG_BQI-YU=_|CQ!i^`pNi(}MeNrY6Z*!yPSQP)~ z-F`%%ruczXNQgYV%6i>Oc9cB90^t^TDE*34zgjCgALvuWQp}CU{LUY+P$@x6YbbPw zcBBp;yHA91*n^g&p~Cp!=c{*6$kum=_vhVR=LElmmKD%q>Ij#dr# zfD#gdkugZ*`fUaf95U@|3iGGmqkrW4e8}1Nno{Bt3~Fh|KxXalBii?klM?{$ajhw$ z{p(*lnHE^n6cyIwj>L}n^!3(h_a5HMtEEH0vF~e!6{L;ClSId}?V0{qPNqBGtypkV zdPEP-*(Y=Mlj7Q0Qb?72&WexmQSNiPf-qk6XZb=}>hTT_p4Wd3RUyV_h_Pxv&rXnzf2?-QJ<_Ve1Z2N&qMjdQ!Xh5K(dI2dCWar zb;N!qyugJ_z!Z71@Jx{wmhLHP#xl737aiO~-?~-@?zD4t@}OmE*5o8OH)WTqMMZwx zxAGINIT4kQxOJyz+;WY>Yk67N_{?BkvSzeGuzpCLL9ewkv{J7p-{H-36Ud9kg?8)J z7o~{qx|uD7-@5@SV0I=Ac7nsU@8%<uUWi4ZLIjvtv$Cht7y^dkc_cBcN)H#=A3U&DA? zpeH=@J}?1}0x{0}OgzS%ay>u2#%_$xd}~(r9_AfYjjzK`mTfHIBX3Gv4$d@H zd}ZS~|NL3SlmL)RwnBb>w&TAw5s|!+S&JsTX7zQt$+(d_Mbozk|K8fc#mGC$JJ#qI zsk?(KN13tcyhEQpf7I>Baoby|Av#3oMdQZcFM7txja{umjUZ>N)5z+RRODTFD|NfT z9cd*~Nt91o1Go#H;zjI#Gt$?bv zysX;{H*KxuqaPL&1RqQ~#q3O%ARrvpAtN93ib3=K?HC!!TWwqlTMMQf+OQd(|)|4Q8v zgPDAYBA7g@C>{X4l;tIq{;6j^>tw0_fW5}{Dwk0C)^7cG)0NiVa;}8Mf*r)~`>msp zo?D8PSe+I*Ws}{GKjRoyrQ}iGA=ehL^WdnV->zT?uqpI+e z2FtF3dSV?|QFeOV7P2l*_=-$QU78HcB2rGo|i~~ew;KtZyF}9uUUgO zsZxKeagbJo@y-p>tPBU)BGC+Xk

iyCk?n7y4|U6#(}G6XDtMHDI84$E{^1VfHRr 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 A!~g&Q literal 0 HcmV?d00001 diff --git a/client/src/assets/image/banksprite.png b/client/src/assets/image/banksprite.png new file mode 100644 index 0000000000000000000000000000000000000000..6c68af62a16d0ef45dbc6c1aac3248776c0abf06 GIT binary patch literal 48163 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 alert(name), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/BankSelect/BankSelect.style.ts b/client/src/components/Design/components/BankSelect/BankSelect.style.ts new file mode 100644 index 000000000..5c42e3909 --- /dev/null +++ b/client/src/components/Design/components/BankSelect/BankSelect.style.ts @@ -0,0 +1,31 @@ +import {css} from '@emotion/react'; + +import ImageSprite from '@assets/image/banksprite.png'; + +export const iconStyle = (position: string) => + css({ + width: '80px', + height: '80px', + background: `url(${ImageSprite}) ${position}`, + }); + +export const bankSelectStyle = css({ + display: 'grid', + gridTemplateColumns: 'repeat(3, 1fr)', + gridRowGap: '1rem', + gridColumnGap: '2rem', + placeItems: 'center', + + height: '100%', + + '@media (min-width: 450px)': { + gridTemplateColumns: 'repeat(4, 1fr)', + }, + + overflowY: 'scroll', + scrollbarWidth: 'none', + + '&::-webkit-scrollbar': { + display: 'none', + }, +}); diff --git a/client/src/components/Design/components/BankSelect/BankSelect.tsx b/client/src/components/Design/components/BankSelect/BankSelect.tsx new file mode 100644 index 000000000..5fdc6f2df --- /dev/null +++ b/client/src/components/Design/components/BankSelect/BankSelect.tsx @@ -0,0 +1,30 @@ +/** @jsxImportSource @emotion/react */ +import BANKS from '@constants/bank'; + +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {bankSelectStyle, iconStyle} from './BankSelect.style'; + +type BankSelectProps = { + onSelect: (name: string) => void; +}; + +const BankSelect = ({onSelect}: BankSelectProps) => { + return ( +

+ ); +}; + +export default BankSelect; diff --git a/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx b/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx new file mode 100644 index 000000000..87d597212 --- /dev/null +++ b/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx @@ -0,0 +1,24 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import BankSendButton from './BankSendButton'; + +const meta = { + title: 'Components/BankSendButton', + component: BankSendButton, + tags: ['autodocs'], + parameters: { + // layout: 'centered', + }, + argTypes: {}, + args: { + clipboardText: '토스뱅크 010100-10-123123', + onBankButtonClick: () => console.log('안녕'), + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts b/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts new file mode 100644 index 000000000..584fafde0 --- /dev/null +++ b/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts @@ -0,0 +1,12 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@components/Design/theme/theme.type'; + +export const bankButtonStyle = (theme: Theme) => + css({ + padding: '0.125rem 0.34375rem', + + backgroundColor: theme.colors.tertiary, + + borderRadius: '0.5rem', + }); diff --git a/client/src/components/Design/components/BankSendButton/BankSendButton.tsx b/client/src/components/Design/components/BankSendButton/BankSendButton.tsx new file mode 100644 index 000000000..cd2a48cd2 --- /dev/null +++ b/client/src/components/Design/components/BankSendButton/BankSendButton.tsx @@ -0,0 +1,33 @@ +/** @jsxImportSource @emotion/react */ +import CopyToClipboard from 'react-copy-to-clipboard'; + +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Icon from '../Icon/Icon'; +import Text from '../Text/Text'; +import Flex from '../Flex/Flex'; + +import {bankButtonStyle} from './BankSendButton.style'; + +type BankSendButtonProps = React.HTMLAttributes & { + clipboardText: string; + onBankButtonClick: () => void; +}; + +const BankSendButton = ({clipboardText, onBankButtonClick, ...buttonProps}: BankSendButtonProps) => { + const {theme} = useTheme(); + return ( + + + + ); +}; + +export default BankSendButton; diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx index 6d6bd339b..efade71d5 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx @@ -14,10 +14,10 @@ const meta = { }, args: { expenseList: [ - {name: '소하', price: 2000}, - {name: '토다리', price: 2000}, - {name: '웨디', price: 1080}, - {name: '쿠키', price: 3020}, + {name: '소하', price: 2000, clipboardText: '토스은행 2000원', onBankButtonClick: () => console.log('소하')}, + {name: '토다리', price: 2000, clipboardText: '토스은행 2000원', onBankButtonClick: () => console.log('토다리')}, + {name: '웨디', price: 1080, clipboardText: '토스은행 1080원', onBankButtonClick: () => console.log('웨디')}, + {name: '쿠키', price: 3020, clipboardText: '토스은행 3020원', onBankButtonClick: () => console.log('쿠키')}, ], }, } satisfies Meta; diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.style.ts b/client/src/components/Design/components/ExpenseList/ExpenseList.style.ts index 8dbd227aa..f24e4914a 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.style.ts +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.style.ts @@ -2,28 +2,11 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; -export const expenseItemStyle = () => - css({ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - width: '100%', - height: '2.5rem', - padding: '0.5rem 1rem', - }); - -export const expenseItemLeftStyle = () => - css({ - display: 'flex', - alignItems: 'center', - gap: '1rem', - }); - export const expenseListStyle = (theme: Theme) => css({ width: '100%', backgroundColor: theme.colors.white, - padding: '0.5rem 0', + padding: '0.5rem 1rem', borderRadius: '1rem', height: '100%', }); diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx index 74d06c86b..67d293111 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx @@ -1,24 +1,35 @@ /** @jsxImportSource @emotion/react */ import Text from '@HDcomponents/Text/Text'; -import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; +import isMobileDevice from '@utils/isMobileDevice'; + +import BankSendButton from '../BankSendButton/BankSendButton'; +import Icon from '../Icon/Icon'; +import IconButton from '../IconButton/IconButton'; +import Flex from '../Flex/Flex'; + import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; -import {expenseItemStyle, expenseListStyle, expenseItemLeftStyle} from './ExpenseList.style'; +import {expenseListStyle} from './ExpenseList.style'; // TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 // TODO: (@todari) : 추후 클릭 시 상호작용이 생기면 iconButton으로 변경할 수 있음 -function ExpenseItem({name, price, ...buttonProps}: ExpenseItemProps) { - const {theme} = useTheme(); +function ExpenseItem({name, price, onBankButtonClick, clipboardText, ...divProps}: ExpenseItemProps) { return ( - + {isMobileDevice() ? ( + + ) : ( + + + + )} + + ); } @@ -26,8 +37,8 @@ function ExpenseList({expenseList = []}: ExpenseListProps) { const {theme} = useTheme(); return (
- {expenseList.map(({name, price}, index: number) => ( - + {expenseList.map((expense, index: number) => ( + ))}
); diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts index 939cd2f68..3987688a3 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts @@ -1,9 +1,11 @@ export interface ExpenseItemCustomProps { name: string; price: number; + onBankButtonClick: () => void; + clipboardText: string; } -export type ExpenseItemProps = React.ComponentProps<'button'> & ExpenseItemCustomProps; +export type ExpenseItemProps = React.ComponentProps<'div'> & ExpenseItemCustomProps; export type ExpenseListProps = { expenseList: ExpenseItemProps[]; diff --git a/client/src/components/Design/components/Icon/Icon.style.ts b/client/src/components/Design/components/Icon/Icon.style.ts index 6380f6dc1..14cdf4e12 100644 --- a/client/src/components/Design/components/Icon/Icon.style.ts +++ b/client/src/components/Design/components/Icon/Icon.style.ts @@ -13,6 +13,7 @@ const ICON_DEFAULT_COLOR: Record = { confirm: 'complete', error: 'warn', trash: 'white', + toss: 'white', meatballs: 'black', }; diff --git a/client/src/components/Design/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx index 307950976..bcfe405fc 100644 --- a/client/src/components/Design/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -1,5 +1,6 @@ /** @jsxImportSource @emotion/react */ +import Toss from '@assets/image/Toss_Symbol_Primary.png'; import InputDelete from '@assets/image/inputDelete.svg'; import Buljusa from '@assets/image/buljusa.svg'; import Error from '@assets/image/error.svg'; @@ -21,6 +22,7 @@ const ICON = { error: , confirm: , trash: , + toss: toss icon, meatballs: , }; diff --git a/client/src/components/Design/components/Icon/Icon.type.ts b/client/src/components/Design/components/Icon/Icon.type.ts index 7cb7542b0..07e52f16c 100644 --- a/client/src/components/Design/components/Icon/Icon.type.ts +++ b/client/src/components/Design/components/Icon/Icon.type.ts @@ -1,4 +1,3 @@ -import {Meatballs} from '@assets/image/meatballs.svg'; import {Theme} from '@theme/theme.type'; import {ColorKeys} from '@token/colors'; @@ -10,7 +9,9 @@ export type IconType = | 'error' | 'confirm' | 'trash' + | 'toss' | 'meatballs'; + export type IconColor = ColorKeys; export interface IconStyleProps { diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx index d6a9d2094..9c5af6e8f 100644 --- a/client/src/components/Design/index.tsx +++ b/client/src/components/Design/index.tsx @@ -1,6 +1,7 @@ import {MainLayout} from './layouts/MainLayout'; import {ContentLayout} from './layouts/ContentLayout'; import {HDesignProvider, useTheme} from './theme/HDesignProvider'; +import BankSelect from './components/BankSelect/BankSelect'; import BottomSheet from './components/BottomSheet/BottomSheet'; import Button from './components/Button/Button'; import DragHandleItem from './components/DragHandleItem/DragHandleItem'; @@ -26,6 +27,7 @@ import Back from './components/TopNav/Back'; import TopNav from './components/TopNav/TopNav'; export { + BankSelect, BottomSheet, Button, DragHandleItem, diff --git a/client/src/components/Modal/BankSelectModal/BankSelectModal.style.ts b/client/src/components/Modal/BankSelectModal/BankSelectModal.style.ts new file mode 100644 index 000000000..cec3609de --- /dev/null +++ b/client/src/components/Modal/BankSelectModal/BankSelectModal.style.ts @@ -0,0 +1,28 @@ +import {css} from '@emotion/react'; + +export const bottomSheetStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '1.5rem', + width: '100%', + height: '100%', + padding: '0 1rem', +}); + +export const bottomSheetHeaderStyle = css({ + display: 'flex', + justifyContent: 'space-between', + alignContent: 'center', + + width: '100%', + padding: '0 0.5rem', +}); + +export const inputContainerStyle = css({ + display: 'flex', + height: '100%', + flexDirection: 'column', + gap: '1.5rem', + overflow: 'auto', + paddingBottom: '4rem', +}); diff --git a/client/src/components/Modal/BankSelectModal/BankSelectModal.tsx b/client/src/components/Modal/BankSelectModal/BankSelectModal.tsx new file mode 100644 index 000000000..02082fd75 --- /dev/null +++ b/client/src/components/Modal/BankSelectModal/BankSelectModal.tsx @@ -0,0 +1,31 @@ +import {BankSelect, BottomSheet, Text} from '@HDesign/index'; + +import {bottomSheetHeaderStyle, bottomSheetStyle, inputContainerStyle} from './BankSelectModal.style'; + +type BankSelectProps = { + isBottomSheetOpened: boolean; + setIsBottomSheetOpened: React.Dispatch>; + selectBank: (name: string) => void; +}; + +const BankSelectModal = ({isBottomSheetOpened, setIsBottomSheetOpened, selectBank}: BankSelectProps) => { + const selectBankAndClose = (name: string) => { + selectBank(name); + setIsBottomSheetOpened(false); + }; + + return ( + setIsBottomSheetOpened(false)}> +
+

+ 은행을 선택해주세요 +

+
+ +
+
+
+ ); +}; + +export default BankSelectModal; diff --git a/client/src/components/Reports/Reports.tsx b/client/src/components/Reports/Reports.tsx index 9215831d7..028c55d17 100644 --- a/client/src/components/Reports/Reports.tsx +++ b/client/src/components/Reports/Reports.tsx @@ -12,12 +12,23 @@ const Reports = () => { setName(target.value); }; + const onBankButtonClick = () => { + const url = 'supertoss://'; + window.location.href = url; + }; + + const expenseListProp = matchedReports.map(member => ({ + ...member, + clipboardText: `계좌번호 받아와야 함 ${member.price}원`, + onBankButtonClick, + })); + return ( {reports.length > 0 ? ( <> - {matchedReports.length !== 0 && } + {matchedReports.length !== 0 && } ) : ( diff --git a/client/src/constants/bank.ts b/client/src/constants/bank.ts new file mode 100644 index 000000000..b730adb44 --- /dev/null +++ b/client/src/constants/bank.ts @@ -0,0 +1,32 @@ +type Bank = { + name: string; + iconPosition: string; +}; + +const BANKS: Bank[] = [ + {name: '우리은행', iconPosition: '-10px -10px'}, + {name: '제일은행', iconPosition: '-110px -10px'}, + {name: '신한은행', iconPosition: '-10px -110px'}, + {name: 'KB국민은행', iconPosition: '-110px -110px'}, + {name: '하나은행', iconPosition: '-210px -10px'}, + {name: '시티은행', iconPosition: '-210px -110px'}, + {name: 'IM뱅크', iconPosition: '-10px -210px'}, + {name: '부산은행', iconPosition: '-110px -210px'}, + {name: '경남은행', iconPosition: '-210px -210px'}, + {name: '광주은행', iconPosition: '-310px -10px'}, + {name: '전북은행', iconPosition: '-310px -110px'}, + {name: '제주은행', iconPosition: '-310px -210px'}, + {name: '기업은행', iconPosition: '-10px -310px'}, + {name: '산업은행', iconPosition: '-110px -310px'}, + {name: '수협은행', iconPosition: '-210px -310px'}, + {name: '농협은행', iconPosition: '-310px -310px'}, + {name: '새마을금고', iconPosition: '-410px -10px'}, + {name: '우체국은행', iconPosition: '-410px -110px'}, + {name: '신협은행', iconPosition: '-410px -210px'}, + {name: 'SBI저축', iconPosition: '-410px -310px'}, + {name: '카카오뱅크', iconPosition: '-10px -410px'}, + {name: '토스뱅크', iconPosition: '-110px -410px'}, + {name: '케이뱅크', iconPosition: '-210px -410px'}, +]; + +export default BANKS; diff --git a/client/src/global.d.ts b/client/src/global.d.ts index ddc00fc99..63226360f 100644 --- a/client/src/global.d.ts +++ b/client/src/global.d.ts @@ -1,4 +1,5 @@ declare module '*.svg'; +declare module '*.png'; declare namespace NodeJS { interface ProcessEnv { diff --git a/client/src/hooks/useAccount.ts b/client/src/hooks/useAccount.ts new file mode 100644 index 000000000..265ca04b5 --- /dev/null +++ b/client/src/hooks/useAccount.ts @@ -0,0 +1,34 @@ +import {useEffect, useState} from 'react'; + +const useAccount = () => { + const [bank, setBank] = useState(''); + const [account, setAccount] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + + const selectBank = (name: string) => { + setBank(name); + }; + + const handleAccount = (event: React.ChangeEvent) => { + setAccount(event.target.value); + }; + + const enrollAccount = () => { + console.log('bank', bank, 'account', account); + }; + + useEffect(() => { + setCanSubmit(bank !== '' && account !== ''); + }, [bank, account]); + + return { + bank, + account, + canSubmit, + selectBank, + handleAccount, + enrollAccount, + }; +}; + +export default useAccount; diff --git a/client/src/mocks/handlers/eventHandlers.ts b/client/src/mocks/handlers/eventHandlers.ts index 81560e4ed..23fefaa47 100644 --- a/client/src/mocks/handlers/eventHandlers.ts +++ b/client/src/mocks/handlers/eventHandlers.ts @@ -1,6 +1,6 @@ -import {http, HttpResponse} from 'msw'; +import type {EventId} from 'types/serviceType'; -import {Event, EventId} from 'types/serviceType'; +import {http, HttpResponse} from 'msw'; import {USER_API_PREFIX} from '@apis/endpointPrefix'; diff --git a/client/src/mocks/svgMock.ts b/client/src/mocks/imageFileMock.ts similarity index 55% rename from client/src/mocks/svgMock.ts rename to client/src/mocks/imageFileMock.ts index 371bb44e1..b59aedd2d 100644 --- a/client/src/mocks/svgMock.ts +++ b/client/src/mocks/imageFileMock.ts @@ -1,7 +1,7 @@ module.exports = { process() { return { - code: 'module.exports = "svg-mock";', + code: 'module.exports = "imageFileMock";', }; }, }; diff --git a/client/src/pages/Account/Account.tsx b/client/src/pages/Account/Account.tsx new file mode 100644 index 000000000..d3d45e410 --- /dev/null +++ b/client/src/pages/Account/Account.tsx @@ -0,0 +1,52 @@ +import {useState} from 'react'; + +import BankSelectModal from '@components/Modal/BankSelectModal/BankSelectModal'; + +import useAccount from '@hooks/useAccount'; + +import {Back, Button, LabelInput, MainLayout, Title, TopNav} from '@components/Design'; + +const Account = () => { + const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); + const {bank, account, canSubmit, selectBank, handleAccount, enrollAccount} = useAccount(); + + return ( + + + + + {/* */} + <fieldset> + <LabelInput + labelText="은행" + placeholder="은행을 선택해주세요" + value={bank} + errorText={null} + autoFocus={false} + readOnly + onClick={() => setIsBottomSheetOpen(true)} + /> + <LabelInput + labelText="계좌번호" + placeholder="030302-04-191806" + errorText={null} + value={account} + onChange={handleAccount} + autoFocus={false} + /> + {isBottomSheetOpen && ( + <BankSelectModal + isBottomSheetOpened={isBottomSheetOpen} + setIsBottomSheetOpened={setIsBottomSheetOpen} + selectBank={selectBank} + /> + )} + </fieldset> + <Button disabled={!canSubmit} onClick={enrollAccount}> + 확인 + </Button> + </MainLayout> + ); +}; + +export default Account; diff --git a/client/src/router.tsx b/client/src/router.tsx index 0cfe364e4..e1592bd2e 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -4,6 +4,7 @@ import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; +import Account from '@pages/Account/Account'; import AddBillFunnel from '@pages/BillPage/AddBillFunnel'; import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; @@ -19,6 +20,10 @@ const router = createBrowserRouter([ path: '', element: <App />, children: [ + { + path: 'cookie', + element: <Account />, + }, { index: true, path: ROUTER_URLS.main, diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs index 8b34ef1c4..90879f2f9 100644 --- a/client/webpack.common.mjs +++ b/client/webpack.common.mjs @@ -46,6 +46,10 @@ export default { }, ], }, + { + test: /\.png$/i, + loader: 'file-loader', + }, ], }, plugins: [ From 89ef7a010244b53f236bf1bcbecc50053a45e43d Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:14:31 +0900 Subject: [PATCH 232/273] =?UTF-8?q?feat:=20=EB=84=A4=ED=8A=B8=EC=9B=8C?= =?UTF-8?q?=ED=81=AC=20=EC=83=81=ED=83=9C=EA=B0=80=20=EC=98=A4=ED=94=84?= =?UTF-8?q?=EB=9D=BC=EC=9D=B8=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20=ED=86=A0?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A1=9C=20=EC=95=88=EB=82=B4=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=20(#568)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 네트워크가 오프라인 상태가 되었을 때 토스트로 오프라인 상태임을 알리는 컴포넌트 구현 * feat: 외부에서 토스트를 닫기 위한 함수를 ToastProvider에서 return에 추가 * rename: NetworkCatcher -> NetworkStateCatcher로 직관적인 이름으로 변경 * feat: 네트워크 상태를 감지하기 위한 컴포넌트를 App에서 호출 --- client/src/App.tsx | 3 ++ client/src/hooks/useToast/ToastProvider.tsx | 3 +- client/src/utils/NetworkStateCatcher.tsx | 42 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 client/src/utils/NetworkStateCatcher.tsx diff --git a/client/src/App.tsx b/client/src/App.tsx index 4535c6b8a..006a6af4f 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -9,6 +9,8 @@ import KakaoInitializer from '@components/KakaoInitializer/KakaoInitializer'; import {HDesignProvider} from '@HDesign/index'; +import NetworkStateCatcher from '@utils/NetworkStateCatcher'; + import {GlobalStyle} from './GlobalStyle'; import UnhandledErrorBoundary from './UnhandledErrorBoundary'; @@ -21,6 +23,7 @@ const App: React.FC = () => { <ErrorCatcher> <QueryClientBoundary> <ReactQueryDevtools initialIsOpen={false} /> + <NetworkStateCatcher /> <KakaoInitializer> <Outlet /> </KakaoInitializer> diff --git a/client/src/hooks/useToast/ToastProvider.tsx b/client/src/hooks/useToast/ToastProvider.tsx index be0d2ea15..60f16f186 100644 --- a/client/src/hooks/useToast/ToastProvider.tsx +++ b/client/src/hooks/useToast/ToastProvider.tsx @@ -10,6 +10,7 @@ const DEFAULT_TIME = 3000; interface ToastContextProps { showToast: (args: ShowToast) => void; + closeToast: () => void; } type ShowToast = ToastProps & { @@ -39,7 +40,7 @@ export const ToastProvider = ({children}: React.PropsWithChildren) => { }, [currentToast]); return ( - <ToastContext.Provider value={{showToast}}> + <ToastContext.Provider value={{showToast, closeToast}}> {currentToast && <Toast onClose={closeToast} {...currentToast} />} {children} </ToastContext.Provider> diff --git a/client/src/utils/NetworkStateCatcher.tsx b/client/src/utils/NetworkStateCatcher.tsx new file mode 100644 index 000000000..8faadfee0 --- /dev/null +++ b/client/src/utils/NetworkStateCatcher.tsx @@ -0,0 +1,42 @@ +import {useEffect} from 'react'; + +import {useToast} from '@hooks/useToast/useToast'; + +const NetworkStateCatcher = () => { + const {showToast, closeToast} = useToast(); + + const handleNetworkOnline = () => { + closeToast(); + }; + + const handleNetworkOffline = () => { + // TODO: (@weadie) 토스트 높이는 z-index 이슈가 해결되면 반영할 예정입니다. + showToast({ + message: '네트워크 연결 상태를 확인해주세요.', + isAlwaysOn: true, + type: 'error', + position: 'bottom', + bottom: '6rem', + }); + }; + + const addNetworkStateEventListener = () => { + window.addEventListener('online', handleNetworkOnline); + window.addEventListener('offline', handleNetworkOffline); + }; + + const removeNetworkStateEventListener = () => { + window.removeEventListener('online', handleNetworkOnline); + window.removeEventListener('offline', handleNetworkOffline); + }; + + useEffect(() => { + addNetworkStateEventListener(); + + return removeNetworkStateEventListener; + }, []); + + return null; +}; + +export default NetworkStateCatcher; From 1ab3c0dde669193127d882b96b7c4e9b38f65074 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:17:56 +0900 Subject: [PATCH 233/273] =?UTF-8?q?feat:=20=EC=9E=85=EA=B8=88=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EB=A5=BC=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20DepositToggle=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20(#555)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: DepositToggle 퍼블리싱 * feat: isDeposit에 따라 toggle 스타일 변경하기 * design: DepositToggle의 storybook 추가 * design: DepositToggle의 세로 중앙 정렬이 안되는 문제 해결 * design: toggle 흰 배경색상 transition 주기 * fix: DepositToggle animation 추가 * refactor: 사용하지 않은 코드 삭제 및 styleProps 구조 변경 * refactor: Text 컴포넌트의 class를 deposit-text로 통일시켜, p 태그에 스타일 사용으로 인한 부작용 방지 * refactor: WithTheme을 사용하여 스토리북 에러 해결을 간편하게 변경 * refactor: 스토리북에서 DepositToggle을 클릭시 focus가 변경되도록 수정 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- .../DepositToggle/DepositToggle.stories.tsx | 51 +++++++++++++++++++ .../DepositToggle/DepositToggle.style.ts | 37 ++++++++++++++ .../DepositToggle/DepositToggle.tsx | 24 +++++++++ .../DepositToggle/DepositToggle.type.ts | 12 +++++ .../Design/components/Text/Text.style.ts | 2 + 5 files changed, 126 insertions(+) create mode 100644 client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx create mode 100644 client/src/components/Design/components/DepositToggle/DepositToggle.style.ts create mode 100644 client/src/components/Design/components/DepositToggle/DepositToggle.tsx create mode 100644 client/src/components/Design/components/DepositToggle/DepositToggle.type.ts diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx b/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx new file mode 100644 index 000000000..a86532eca --- /dev/null +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx @@ -0,0 +1,51 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import {useEffect, useState} from 'react'; + +import {DepositToggle} from './DepositToggle'; + +const meta = { + title: 'Components/DepositToggle', + component: DepositToggle, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + isDeposit: { + description: '', + control: {type: 'boolean'}, + }, + onToggle: { + description: '', + control: {type: 'select'}, + options: [undefined, () => alert('change toggle')], + }, + }, +} satisfies Meta<typeof DepositToggle>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + args: { + isDeposit: false, + onToggle: () => {}, + }, + render: ({isDeposit, onToggle, ...args}) => { + const [isDepositState, setIsDepositState] = useState(isDeposit); + + useEffect(() => { + setIsDepositState(isDeposit); + }, [isDeposit]); + + const handleToggle = () => { + setIsDepositState(!isDepositState); + onToggle(); + }; + + return <DepositToggle {...args} isDeposit={isDepositState} onToggle={handleToggle} />; + }, +}; diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts b/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts new file mode 100644 index 000000000..a5ebce425 --- /dev/null +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts @@ -0,0 +1,37 @@ +import {css} from '@emotion/react'; + +import {WithTheme} from '@components/Design/type/withTheme'; + +import {DepositToggleStyleProps} from './DepositToggle.type'; + +export const depositToggleStyle = ({theme, isDeposit}: WithTheme<DepositToggleStyleProps>) => + css({ + display: `flex`, + flexDirection: 'column', + padding: '0.25rem', + borderRadius: '0.75rem', + backgroundColor: theme.colors.tertiary, + cursor: 'pointer', + width: '4rem', + + '.deposit-text': { + display: 'flex', + justifyContent: 'center', + borderRadius: '0.5rem', + padding: ' 0.125rem 0 0 0', + zIndex: '10', + }, + + '.toggle-background': { + position: 'fixed', + width: '56px', + height: '20px', + borderRadius: '0.5rem', + backgroundColor: theme.colors.white, + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + + transform: !isDeposit ? 'translateY(1.25rem)' : '', + }, + }); diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.tsx b/client/src/components/Design/components/DepositToggle/DepositToggle.tsx new file mode 100644 index 000000000..a5fb4f30e --- /dev/null +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.tsx @@ -0,0 +1,24 @@ +/** @jsxImportSource @emotion/react */ + +import {useTheme} from '@theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {DepositToggleProps} from './DepositToggle.type'; +import {depositToggleStyle} from './DepositToggle.style'; + +export const DepositToggle: React.FC<DepositToggleProps> = ({isDeposit = false, onToggle}: DepositToggleProps) => { + const {theme} = useTheme(); + + return ( + <div css={depositToggleStyle({theme, isDeposit})} onClick={onToggle} role="button"> + <div className={'toggle-background'} content="" /> + <Text size="caption" textColor={isDeposit ? `onTertiary` : 'gray'} className="deposit-text"> + 입금 완료 + </Text> + <Text size="caption" textColor={isDeposit ? `gray` : 'error'} className="deposit-text"> + 미입금 + </Text> + </div> + ); +}; diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.type.ts b/client/src/components/Design/components/DepositToggle/DepositToggle.type.ts new file mode 100644 index 000000000..15f19d01f --- /dev/null +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.type.ts @@ -0,0 +1,12 @@ +export interface DepositToggleStyleProps { + isDeposit: boolean; +} + +export interface DepositToggleCustomProps { + isDeposit: boolean; + onToggle: () => void; +} + +export type DepositToggleOptionProps = DepositToggleStyleProps & DepositToggleCustomProps; + +export type DepositToggleProps = React.ComponentProps<'div'> & DepositToggleOptionProps; diff --git a/client/src/components/Design/components/Text/Text.style.ts b/client/src/components/Design/components/Text/Text.style.ts index 650260e62..858d136af 100644 --- a/client/src/components/Design/components/Text/Text.style.ts +++ b/client/src/components/Design/components/Text/Text.style.ts @@ -23,6 +23,8 @@ export const getSizeStyling = ({size, textColor, theme}: Required<TextStyleProps const baseStyle = css({ whiteSpace: 'pre-line', + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', }); return [style[size], colorStyle, baseStyle]; From 5e9555ec4783ae4ef3df78522939870e45c61ebc Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:28:04 +0900 Subject: [PATCH 234/273] =?UTF-8?q?feat:=20=EC=B0=B8=EC=97=AC=EC=9E=90=20?= =?UTF-8?q?=EC=9E=85=EA=B8=88=20=EC=83=81=ED=83=9C,=20=EC=B0=B8=EC=97=AC?= =?UTF-8?q?=EC=9E=90=20=EC=9D=B4=EB=A6=84=20Chip=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84=20(#570)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Icon 컴포넌트에 check, x 추가 * feat: 참여자의 입금 상태를 관리하는 DepositCheck 컴포넌트 기능 구현 * test: DepositCheck 스토리북 생성 * refactor: isCheck props를 isDeposited로 api 이름과 동일하게 변경 * fix: icon defalut color 누락된 부분 추가 --------- Co-authored-by: jinho_kim98 <rlawlsgh1227@gmail.com> --- client/src/assets/image/check.svg | 3 +++ client/src/assets/image/x.svg | 3 +++ .../DepositCheck/DepositCheck.stories.tsx | 27 +++++++++++++++++++ .../DepositCheck/DepositCheck.style.ts | 21 +++++++++++++++ .../components/DepositCheck/DepositCheck.tsx | 21 +++++++++++++++ .../DepositCheck/DepositCheck.type.ts | 11 ++++++++ .../Design/components/Icon/Icon.stories.tsx | 2 +- .../Design/components/Icon/Icon.style.ts | 3 ++- .../Design/components/Icon/Icon.tsx | 4 +++ .../Design/components/Icon/Icon.type.ts | 2 ++ 10 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 client/src/assets/image/check.svg create mode 100644 client/src/assets/image/x.svg create mode 100644 client/src/components/Design/components/DepositCheck/DepositCheck.stories.tsx create mode 100644 client/src/components/Design/components/DepositCheck/DepositCheck.style.ts create mode 100644 client/src/components/Design/components/DepositCheck/DepositCheck.tsx create mode 100644 client/src/components/Design/components/DepositCheck/DepositCheck.type.ts diff --git a/client/src/assets/image/check.svg b/client/src/assets/image/check.svg new file mode 100644 index 000000000..66ed75336 --- /dev/null +++ b/client/src/assets/image/check.svg @@ -0,0 +1,3 @@ +<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M10 3L4.5 8.5L2 6" stroke="#B575FF" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/client/src/assets/image/x.svg b/client/src/assets/image/x.svg new file mode 100644 index 000000000..c3622bab5 --- /dev/null +++ b/client/src/assets/image/x.svg @@ -0,0 +1,3 @@ +<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M9 3L3 9M3 3L9 9" stroke="#B2B1B6" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/client/src/components/Design/components/DepositCheck/DepositCheck.stories.tsx b/client/src/components/Design/components/DepositCheck/DepositCheck.stories.tsx new file mode 100644 index 000000000..7cfd25aea --- /dev/null +++ b/client/src/components/Design/components/DepositCheck/DepositCheck.stories.tsx @@ -0,0 +1,27 @@ +import type {Meta, StoryObj} from '@storybook/react'; + +import DepositCheck from '@HDcomponents/DepositCheck/DepositCheck'; + +const meta = { + title: 'Components/DepositCheck', + component: DepositCheck, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + isDeposited: { + description: '', + control: {type: 'boolean'}, + }, + }, + args: { + isDeposited: false, + }, +} satisfies Meta<typeof DepositCheck>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/DepositCheck/DepositCheck.style.ts b/client/src/components/Design/components/DepositCheck/DepositCheck.style.ts new file mode 100644 index 000000000..22f1f52a9 --- /dev/null +++ b/client/src/components/Design/components/DepositCheck/DepositCheck.style.ts @@ -0,0 +1,21 @@ +import {css} from '@emotion/react'; + +import {WithTheme} from '@components/Design/type/withTheme'; + +import {DepositCheckStyleProps} from './DepositCheck.type'; + +export const DepositCheckStyle = ({theme, isDeposited}: WithTheme<DepositCheckStyleProps>) => + css({ + display: 'flex', + alignItems: 'center', + gap: '0.125rem', + border: `1px solid ${isDeposited ? theme.colors.primary : theme.colors.gray}`, + borderRadius: '0.5rem', + padding: '0.25rem 0.375rem', + height: '1.25rem', + + '.deposit-check-text': { + color: isDeposited ? theme.colors.primary : theme.colors.gray, + paddingTop: '0.0625rem', + }, + }); diff --git a/client/src/components/Design/components/DepositCheck/DepositCheck.tsx b/client/src/components/Design/components/DepositCheck/DepositCheck.tsx new file mode 100644 index 000000000..10b21aabc --- /dev/null +++ b/client/src/components/Design/components/DepositCheck/DepositCheck.tsx @@ -0,0 +1,21 @@ +/** @jsxImportSource @emotion/react */ +import {useTheme} from '@components/Design'; + +import Icon from '../Icon/Icon'; +import Text from '../Text/Text'; + +import {DepositCheckStyle} from './DepositCheck.style'; +import {DepositCheckProps} from './DepositCheck.type'; + +const DepositCheck: React.FC<DepositCheckProps> = ({isDeposited = false}: DepositCheckProps) => { + const {theme} = useTheme(); + return ( + <div css={DepositCheckStyle({theme, isDeposited})}> + <Text size="tiny" className="deposit-check-text"> + 입금 + </Text> + <Icon iconType={isDeposited ? 'check' : 'x'}></Icon> + </div> + ); +}; +export default DepositCheck; diff --git a/client/src/components/Design/components/DepositCheck/DepositCheck.type.ts b/client/src/components/Design/components/DepositCheck/DepositCheck.type.ts new file mode 100644 index 000000000..fdb308170 --- /dev/null +++ b/client/src/components/Design/components/DepositCheck/DepositCheck.type.ts @@ -0,0 +1,11 @@ +export interface DepositCheckStyleProps { + isDeposited: boolean; +} + +export interface DepositCheckCustomProps { + isDeposited: boolean; +} + +export type DepositCheckOptionProps = DepositCheckStyleProps & DepositCheckCustomProps; + +export type DepositCheckProps = React.ComponentProps<'div'> & DepositCheckOptionProps; diff --git a/client/src/components/Design/components/Icon/Icon.stories.tsx b/client/src/components/Design/components/Icon/Icon.stories.tsx index ee111a2f9..c3763b12d 100644 --- a/client/src/components/Design/components/Icon/Icon.stories.tsx +++ b/client/src/components/Design/components/Icon/Icon.stories.tsx @@ -13,7 +13,7 @@ const meta = { iconType: { description: '', control: {type: 'select'}, - options: ['inputDelete', 'buljusa', 'rightChevron', 'search', 'confirm', 'error', 'trash'], + options: ['inputDelete', 'buljusa', 'rightChevron', 'search', 'confirm', 'error', 'trash', 'check', 'x'], }, }, args: { diff --git a/client/src/components/Design/components/Icon/Icon.style.ts b/client/src/components/Design/components/Icon/Icon.style.ts index 14cdf4e12..8d4d68145 100644 --- a/client/src/components/Design/components/Icon/Icon.style.ts +++ b/client/src/components/Design/components/Icon/Icon.style.ts @@ -1,6 +1,5 @@ import {css} from '@emotion/react'; -import {Theme} from '@theme/theme.type'; import {ColorKeys} from '@token/colors'; import {IconColor, IconStylePropsWithTheme, IconType} from './Icon.type'; @@ -13,6 +12,8 @@ const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { confirm: 'complete', error: 'warn', trash: 'white', + check: 'primary', + x: 'gray', toss: 'white', meatballs: 'black', }; diff --git a/client/src/components/Design/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx index bcfe405fc..c900c289c 100644 --- a/client/src/components/Design/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -8,6 +8,8 @@ import Confirm from '@assets/image/confirm.svg'; import Trash from '@assets/image/trash.svg'; import Search from '@assets/image/search.svg'; import RightChevron from '@assets/image/rightChevron.svg'; +import Check from '@assets/image/check.svg'; +import X from '@assets/image/x.svg'; import Meatballs from '@assets/image/meatballs.svg'; import {IconProps} from '@HDcomponents/Icon/Icon.type'; import {useTheme} from '@theme/HDesignProvider'; @@ -22,6 +24,8 @@ const ICON = { error: <Error />, confirm: <Confirm />, trash: <Trash />, + check: <Check />, + x: <X />, toss: <img src={Toss} width="24" height="24" alt="toss icon" />, meatballs: <Meatballs />, }; diff --git a/client/src/components/Design/components/Icon/Icon.type.ts b/client/src/components/Design/components/Icon/Icon.type.ts index 07e52f16c..1b058c76f 100644 --- a/client/src/components/Design/components/Icon/Icon.type.ts +++ b/client/src/components/Design/components/Icon/Icon.type.ts @@ -9,6 +9,8 @@ export type IconType = | 'error' | 'confirm' | 'trash' + | 'check' + | 'x' | 'toss' | 'meatballs'; From 2b64fb0b4418658fdf4f2139a8289c9ebff08827 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:29:05 +0900 Subject: [PATCH 235/273] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EC=8B=9C=20=EC=A7=80=EC=97=AD=EC=A0=81=EC=9D=B8=20?= =?UTF-8?q?error=20boundary=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EB=B0=A9=EC=8B=9D=20=EA=B0=9C=EC=84=A0=20?= =?UTF-8?q?(#567)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * rename: FetchError -> RequestError로 이름 변경 * feat: 에러의 타입이 RequestError 인지 확인하는 유틸 함수 구현 * refactor: 에러 객체를 불필요하게 object로 변환하는 과정 제거 * feat: 에러 처리 전략이 에러 바운더리일 경우 updateAppError로직을 수행하지 않도록 하고, throwOnError 옵션을 킴 * feat: GET 메서드에서 발생한 에러와 에러 처리 전략 정보 전달을 위한 RequestGetError 클래스 구현 * refactor: errorInfo라는 에러를 객체로 바꾼 자료형을 사용하지 않도록 개선 * feat: 기본 제공되는 RequestInit을 최대한 활용하도록 타입 수정과 직관적인 이름으로 개선 * feat: GET request인 경우 에러 처리 전략을 넘겨받도록 함 * refactor: 내부에 있는 로직과 맞지 않는 함수명에서 로직과 함수명이 모두 직관적으로 일치하도록 수정 * feat: 메서드 타입에 따라 해당하는 에러 인스턴스를 반환하는 로직 구현 * feat: GET 메서드를 사용하는 api 호출 함수들에 에러 처리 전략을 인자로 받을 수 있도록 수정 * fix: 로직이 반대의 값을 반환하는 것을 수정 * test: 에러 이름 수정과 에러 코드가 어떤 코드인지 의미를 담은 변수명으로 수정 * rename: 의미를 직관적으로 알 수 있도록 UnHandledErrorBoundary -> UnPredictableErrorBoundary로 이름 수정 * rename: 규칙에 맞도록 쿼리 hook이름 수정 * refactor: errorInfo를 제거하고 불필요한 분기문 제거 * chore: 충돌 해결 --- client/src/App.tsx | 6 +- ...ary.tsx => UnPredictableErrorBoundary.tsx} | 4 +- client/src/apis/fetcher.ts | 149 ++++++++++++------ client/src/apis/request/bill.ts | 9 +- client/src/apis/request/event.ts | 4 +- client/src/apis/request/member.ts | 8 +- client/src/apis/request/report.ts | 5 +- client/src/apis/request/step.ts | 4 +- .../AppErrorBoundary/ErrorCatcher.test.tsx | 32 ++-- .../AppErrorBoundary/ErrorCatcher.tsx | 63 +++----- .../QueryClientBoundary.tsx | 11 ++ client/src/errors/FetchError.ts | 23 --- client/src/errors/RequestError.ts | 24 +++ client/src/errors/RequestGetError.ts | 21 +++ client/src/errors/requestErrorType.ts | 10 ++ .../queries/bill/useRequestGetBillDetails.ts | 9 +- .../hooks/queries/event/useRequestGetEvent.ts | 5 +- .../queries/member/useRequestGetAllMembers.ts | 5 +- .../member/useRequestGetCurrentMembers.ts | 5 +- .../queries/report/useRequestGetReports.ts | 5 +- .../hooks/queries/step/useRequestGetSteps.ts | 5 +- .../hooks/useBillDetails/useBillDetails.ts | 2 +- client/src/hooks/useSetEventPasswordPage.ts | 1 + client/src/types/fetchErrorType.ts | 11 -- client/src/utils/captureError.ts | 62 ++++---- client/src/utils/isRequestError.ts | 7 + client/src/utils/sendLogToSentry.ts | 38 ++--- 27 files changed, 306 insertions(+), 222 deletions(-) rename client/src/{UnhandledErrorBoundary.tsx => UnPredictableErrorBoundary.tsx} (68%) delete mode 100644 client/src/errors/FetchError.ts create mode 100644 client/src/errors/RequestError.ts create mode 100644 client/src/errors/RequestGetError.ts create mode 100644 client/src/errors/requestErrorType.ts delete mode 100644 client/src/types/fetchErrorType.ts create mode 100644 client/src/utils/isRequestError.ts diff --git a/client/src/App.tsx b/client/src/App.tsx index 006a6af4f..7e86b12b7 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -12,12 +12,12 @@ import {HDesignProvider} from '@HDesign/index'; import NetworkStateCatcher from '@utils/NetworkStateCatcher'; import {GlobalStyle} from './GlobalStyle'; -import UnhandledErrorBoundary from './UnhandledErrorBoundary'; +import UnPredictableErrorBoundary from './UnPredictableErrorBoundary'; const App: React.FC = () => { return ( <HDesignProvider> - <UnhandledErrorBoundary> + <UnPredictableErrorBoundary> <Global styles={GlobalStyle} /> <ToastProvider> <ErrorCatcher> @@ -30,7 +30,7 @@ const App: React.FC = () => { </QueryClientBoundary> </ErrorCatcher> </ToastProvider> - </UnhandledErrorBoundary> + </UnPredictableErrorBoundary> </HDesignProvider> ); }; diff --git a/client/src/UnhandledErrorBoundary.tsx b/client/src/UnPredictableErrorBoundary.tsx similarity index 68% rename from client/src/UnhandledErrorBoundary.tsx rename to client/src/UnPredictableErrorBoundary.tsx index 3e1f4378f..7dce07a58 100644 --- a/client/src/UnhandledErrorBoundary.tsx +++ b/client/src/UnPredictableErrorBoundary.tsx @@ -3,8 +3,8 @@ import {ErrorBoundary} from 'react-error-boundary'; import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; -const UnhandledErrorBoundary = ({children}: StrictPropsWithChildren) => { +const UnPredictableErrorBoundary = ({children}: StrictPropsWithChildren) => { return <ErrorBoundary fallback={<ErrorPage />}>{children}</ErrorBoundary>; }; -export default UnhandledErrorBoundary; +export default UnPredictableErrorBoundary; diff --git a/client/src/apis/fetcher.ts b/client/src/apis/fetcher.ts index 2e1c2d067..a1c205739 100644 --- a/client/src/apis/fetcher.ts +++ b/client/src/apis/fetcher.ts @@ -1,120 +1,165 @@ -import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; +import {RequestGetError, WithErrorHandlingStrategy} from '@errors/RequestGetError'; import objectToQueryString from '@utils/objectToQueryString'; -import {UNKNOWN_ERROR} from '@constants/errorMessage'; - -import FetchError from '../errors/FetchError'; +import RequestError from '../errors/RequestError'; export type Method = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'; -type Body = ReadableStream | XMLHttpRequestBodyInit; +export type ObjectQueryParams = Record<string, string | number | boolean>; + +type ErrorInfo = { + errorCode: string; + message: string; +}; + +/** + * fetch의 2번째 인자로 들어가는 데이터의 타입은 RequestInit으로 기본적으로 제공됩니다. + * 다만 이 RequestInit의 타입이 method가 optional이라서 이를 반드시 받도록하기 위해 RequestInitWithMethod라는 타입으로 확장하게 되었습니다. + */ +type RequestInitWithMethod = Omit<RequestInit, 'method'> & {method: Method}; + type HeadersType = [string, string][] | Record<string, string> | Headers; -export type ObjectQueryParams = Record<string, string | number | boolean>; +export type Body = BodyInit | object | null; type RequestProps = { baseUrl?: string; endpoint: string; headers?: HeadersType; - body?: Body | object | null; + body?: Body; queryParams?: ObjectQueryParams; -}; - -type FetcherProps = RequestProps & { method: Method; }; -type Options = { - method: Method; - headers: HeadersType; - body?: Body | null; -}; +type RequestMethodProps = Omit<RequestProps, 'method'>; -type ErrorHandlerProps = { +type FetchType = { url: string; - options: Options; - body: string; + requestInit: RequestInitWithMethod; }; const API_BASE_URL = process.env.API_BASE_URL ?? ''; -export const requestGet = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { - const response = await fetcher({ +export const requestGet = async <T>({ + headers = {}, + errorHandlingStrategy, + ...args +}: WithErrorHandlingStrategy<RequestMethodProps>): Promise<T> => { + const response = await request({ ...args, method: 'GET', headers, + errorHandlingStrategy, }); const data: T = await response!.json(); return data; }; -export const requestPatch = ({headers = {}, ...args}: RequestProps) => { - return fetcher({method: 'PATCH', headers, ...args}); +export const requestPatch = ({headers = {}, ...args}: RequestMethodProps) => { + return request({method: 'PATCH', headers, ...args}); }; -export const requestPut = ({headers = {}, ...args}: RequestProps) => { - return fetcher({method: 'PUT', headers, ...args}); +export const requestPut = ({headers = {}, ...args}: RequestMethodProps) => { + return request({method: 'PUT', headers, ...args}); }; -export const requestPostWithoutResponse = async ({headers = {}, ...args}: RequestProps) => { - await fetcher({method: 'POST', headers, ...args}); +export const requestPostWithoutResponse = async ({headers = {}, ...args}: RequestMethodProps) => { + await request({method: 'POST', headers, ...args}); }; -export const requestPostWithResponse = async <T>({headers = {}, ...args}: RequestProps): Promise<T> => { - const response = await fetcher({method: 'POST', headers, ...args}); +export const requestPostWithResponse = async <T>({headers = {}, ...args}: RequestMethodProps): Promise<T> => { + const response = await request({method: 'POST', headers, ...args}); const data: T = await response!.json(); return data; }; -export const requestDelete = ({headers = {}, ...args}: RequestProps) => { - return fetcher({method: 'DELETE', headers, ...args}); +export const requestDelete = ({headers = {}, ...args}: RequestMethodProps) => { + return request({method: 'DELETE', headers, ...args}); }; -const fetcher = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: FetcherProps) => { - const options = { - method, +const prepareRequest = ({baseUrl = API_BASE_URL, method, endpoint, headers, body, queryParams}: RequestProps) => { + let url = `${baseUrl}${endpoint}`; + + if (queryParams) url += `?${objectToQueryString(queryParams)}`; + + const requestInit: RequestInitWithMethod = { credentials: 'include', headers: { 'Content-Type': 'application/json', ...headers, }, + method, body: body ? JSON.stringify(body) : null, }; - let url = `${baseUrl}${endpoint}`; - - if (queryParams) url += `?${objectToQueryString(queryParams)}`; - - return errorHandler({url, options, body: JSON.stringify(body)}); + return {url, requestInit}; }; -const errorHandler = async ({url, options, body}: ErrorHandlerProps) => { +const executeRequest = async ({url, requestInit, errorHandlingStrategy}: WithErrorHandlingStrategy<FetchType>) => { try { - const response: Response = await fetch(url, options); + const response: Response = await fetch(url, requestInit); if (!response.ok) { - const serverErrorInfo: ErrorInfo = await response.json(); - - throw new FetchError({ - status: response.status, - requestBody: body, - endpoint: response.url, - errorInfo: serverErrorInfo, - name: serverErrorInfo.errorCode, - message: serverErrorInfo.message || '', - method: options.method, + throw await createError({ + response, + body: requestInit.body ? JSON.stringify(requestInit.body) : null, + requestInit, + errorHandlingStrategy, }); } return response; } catch (error) { if (error instanceof Error) { - throw error; // 그대로 FetchError || Error 인스턴스를 던집니다. + throw error; // 그대로 RequestError 또는 Error 인스턴스를 던집니다. } - throw new Error(UNKNOWN_ERROR); + throw error; } }; + +const request = async (props: WithErrorHandlingStrategy<RequestProps>) => { + const {url, requestInit} = prepareRequest(props); + return executeRequest({url, requestInit, errorHandlingStrategy: props.errorHandlingStrategy}); +}; + +type CreateError = { + response: Response; + body: Body; + requestInit: RequestInitWithMethod; +}; + +const createError = async ({ + response, + body, + requestInit, + errorHandlingStrategy, +}: WithErrorHandlingStrategy<CreateError>) => { + const {errorCode, message}: ErrorInfo = await response.json(); + + if (requestInit.method === 'GET') { + return new RequestGetError({ + status: response.status, + requestBody: body, + endpoint: response.url, + name: errorCode, + method: requestInit.method, + errorHandlingStrategy, + message, + errorCode, + }); + } + + return new RequestError({ + status: response.status, + requestBody: body, + endpoint: response.url, + name: errorCode, + method: requestInit.method, + message, + errorCode, + }); +}; diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 561afcc52..03bbd5317 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -1,5 +1,7 @@ import type {BillDetails} from 'types/serviceType'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + import {BASE_URL} from '@apis/baseUrl'; import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestDelete, requestGet, requestPostWithoutResponse, requestPut} from '@apis/fetcher'; @@ -43,10 +45,15 @@ export const requestPutBill = async ({eventId, billId, title, price}: WithEventI }); }; -export const requestGetBillDetails = async ({eventId, billId}: WithEventId<WithBillId>) => { +export const requestGetBillDetails = async ({ + eventId, + billId, + ...props +}: WithEventId<WithErrorHandlingStrategy<WithBillId>>) => { return requestGet<BillDetails>({ baseUrl: BASE_URL.HD, endpoint: `${USER_API_PREFIX}/${eventId}/bills/${billId}/fixed`, + ...props, }); }; diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index c8c218f3a..a81e4c00e 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -1,4 +1,5 @@ import {Event, EventId} from 'types/serviceType'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import {USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestGet, requestPostWithResponse, requestPut} from '@apis/fetcher'; @@ -19,9 +20,10 @@ export const requestPostEvent = async ({eventName, password}: RequestPostEvent) }); }; -export const requestGetEvent = async ({eventId}: WithEventId) => { +export const requestGetEvent = async ({eventId, ...props}: WithEventId<WithErrorHandlingStrategy>) => { return await requestGet<Event>({ endpoint: `${USER_API_PREFIX}/${eventId}`, + ...props, }); }; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 9c0a0506f..4e5da1bb4 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -1,5 +1,7 @@ import type {AllMembers, Members} from 'types/serviceType'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + import {BASE_URL} from '@apis/baseUrl'; import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestDelete, requestGet, requestPut, requestPostWithResponse} from '@apis/fetcher'; @@ -54,15 +56,17 @@ export const requestPutMembers = async ({eventId, members}: WithEventId<RequestP }); }; -export const requestGetCurrentMembers = async ({eventId}: WithEventId) => { +export const requestGetCurrentMembers = async ({eventId, ...props}: WithEventId<WithErrorHandlingStrategy>) => { return await requestGet<Members>({ baseUrl: BASE_URL.HD, endpoint: `${USER_API_PREFIX}/${eventId}/members/current`, + ...props, }); }; -export const requestGetAllMembers = async ({eventId}: WithEventId) => { +export const requestGetAllMembers = async ({eventId, ...props}: WithEventId<WithErrorHandlingStrategy>) => { return await requestGet<AllMembers>({ endpoint: `${USER_API_PREFIX}/${eventId}/members`, + ...props, }); }; diff --git a/client/src/apis/request/report.ts b/client/src/apis/request/report.ts index 6d73ff161..51fc418a8 100644 --- a/client/src/apis/request/report.ts +++ b/client/src/apis/request/report.ts @@ -1,13 +1,16 @@ import type {Reports} from 'types/serviceType'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; + import {BASE_URL} from '@apis/baseUrl'; import {USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestGet} from '@apis/fetcher'; import {WithEventId} from '@apis/withId.type'; -export const requestGetReports = async ({eventId}: WithEventId) => { +export const requestGetReports = async ({eventId, ...props}: WithEventId<WithErrorHandlingStrategy>) => { return await requestGet<Reports>({ baseUrl: BASE_URL.HD, endpoint: `${USER_API_PREFIX}/${eventId}/reports`, + ...props, }); }; diff --git a/client/src/apis/request/step.ts b/client/src/apis/request/step.ts index f67615e2d..e0f205e22 100644 --- a/client/src/apis/request/step.ts +++ b/client/src/apis/request/step.ts @@ -1,14 +1,16 @@ import {Steps} from 'types/serviceType'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import {BASE_URL} from '@apis/baseUrl'; import {USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestGet} from '@apis/fetcher'; import {WithEventId} from '@apis/withId.type'; -export const requestGetSteps = async ({eventId}: WithEventId) => { +export const requestGetSteps = async ({eventId, ...props}: WithEventId<WithErrorHandlingStrategy>) => { const {steps} = await requestGet<Steps>({ baseUrl: BASE_URL.HD, endpoint: `${USER_API_PREFIX}/${eventId}/bills`, + ...props, }); return steps; diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx index 9a802df14..9367e65dd 100644 --- a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx @@ -2,7 +2,7 @@ import {render, screen, waitFor} from '@testing-library/react'; import {act, ReactNode} from 'react'; import {MemoryRouter} from 'react-router-dom'; -import FetchError from '@errors/FetchError'; +import RequestError from '@errors/RequestError'; import {ToastProvider} from '@hooks/useToast/ToastProvider'; import {useAppErrorStore} from '@store/appErrorStore'; @@ -11,7 +11,7 @@ import {HDesignProvider} from '@HDesign/index'; import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; -import UnhandledErrorBoundary from '../../UnhandledErrorBoundary'; +import UnPredictableErrorBoundary from '../../UnPredictableErrorBoundary'; import ErrorCatcher from './ErrorCatcher'; @@ -23,13 +23,13 @@ const TestComponent = ({triggerError}: {triggerError: () => void}) => { const setup = (ui: ReactNode) => render( <HDesignProvider> - <UnhandledErrorBoundary> + <UnPredictableErrorBoundary> <ToastProvider> <ErrorCatcher> <MemoryRouter>{ui}</MemoryRouter> </ErrorCatcher> </ToastProvider> - </UnhandledErrorBoundary> + </UnPredictableErrorBoundary> </HDesignProvider>, ); @@ -39,16 +39,16 @@ describe('ErrorCatcher', () => { useNavigate: jest.fn(), })); - it('핸들링 가능한 에러인 경우 토스트가 표시된다.', async () => { - const errorCode = 'EVENT_NOT_FOUND'; - const error = new FetchError({ - errorInfo: {errorCode, message: '서버의 에러메세지'}, - name: errorCode, - message: '에러메세지', + it('예측 가능한 에러인 경우 토스트가 표시된다.', async () => { + const predictableErrorCode = 'EVENT_NOT_FOUND'; + const error = new RequestError({ + message: '서버의 에러메세지', + name: predictableErrorCode, status: 200, endpoint: '', method: 'GET', requestBody: '', + errorCode: predictableErrorCode, }); const {updateAppError} = useAppErrorStore.getState(); @@ -59,7 +59,7 @@ describe('ErrorCatcher', () => { screen.getByText('Trigger Error').click(); }); - const errorMessage = SERVER_ERROR_MESSAGES[errorCode]; + const errorMessage = SERVER_ERROR_MESSAGES[predictableErrorCode]; await waitFor(() => { expect(screen.getByText(errorMessage)).toBeInTheDocument(); @@ -67,15 +67,15 @@ describe('ErrorCatcher', () => { }); it('핸들링 불가능한 에러인 경우 에러 바운더리가 표시된다.', async () => { - const errorCode = '모르겠는 에러'; - const error = new FetchError({ - errorInfo: {errorCode, message: '모르겠는 에러메세지'}, - name: errorCode, - message: '에러메세지', + const unPredictableErrorCode = '모르겠는 에러'; + const error = new RequestError({ + message: '모르겠는 에러메세지', + name: unPredictableErrorCode, status: 400, endpoint: '', method: 'GET', requestBody: '', + errorCode: unPredictableErrorCode, }); const {updateAppError} = useAppErrorStore.getState(); diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx index dde5f3d64..9e9e2f484 100644 --- a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx @@ -1,60 +1,41 @@ import {useEffect} from 'react'; -import FetchError from '@errors/FetchError'; import {useToast} from '@hooks/useToast/useToast'; import {useAppErrorStore} from '@store/appErrorStore'; import {captureError} from '@utils/captureError'; +import isRequestError from '@utils/isRequestError'; -import {SERVER_ERROR_MESSAGES, UNKNOWN_ERROR} from '@constants/errorMessage'; +import {SERVER_ERROR_MESSAGES} from '@constants/errorMessage'; -export type ErrorInfo = { - errorCode: string; - message: string; -}; - -const convertAppErrorToErrorInfo = (appError: Error) => { - if (appError instanceof Error) { - const errorInfo = - appError instanceof FetchError ? appError.errorInfo : {errorCode: appError.name, message: appError.message}; - - return errorInfo; - } else { - const errorInfo = {errorCode: UNKNOWN_ERROR, message: JSON.stringify(appError)}; - - return errorInfo; - } -}; - -const isUnhandledError = (errorInfo: ErrorInfo) => { - if (errorInfo.errorCode === 'INTERNAL_SERVER_ERROR') return true; +const isPredictableError = (error: Error) => { + if (isRequestError(error)) if (error.errorCode === 'INTERNAL_SERVER_ERROR') return false; - return SERVER_ERROR_MESSAGES[errorInfo.errorCode] === undefined; + return SERVER_ERROR_MESSAGES[error.name] !== undefined; }; const ErrorCatcher = ({children}: React.PropsWithChildren) => { - const {appError} = useAppErrorStore(); + const {appError: error} = useAppErrorStore(); const {showToast} = useToast(); useEffect(() => { - if (appError) { - const errorInfo = convertAppErrorToErrorInfo(appError); - captureError(appError, errorInfo); - - if (!isUnhandledError(errorInfo)) { - showToast({ - showingTime: 3000, - message: SERVER_ERROR_MESSAGES[errorInfo.errorCode], - type: 'error', - position: 'bottom', - bottom: '8rem', - }); - } else { - throw appError; - } - } - }, [appError]); + if (!error) return; + + captureError(error); + + console.log(isRequestError(error)); + console.log(isPredictableError(error)); + if (!isRequestError(error) || !isPredictableError(error)) throw error; + + showToast({ + showingTime: 3000, + message: SERVER_ERROR_MESSAGES[error.errorCode], + type: 'error', + position: 'bottom', + bottom: '8rem', + }); + }, [error]); return children; }; diff --git a/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx index aeec24c3a..0ff8bf202 100644 --- a/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx +++ b/client/src/components/QueryClientBoundary/QueryClientBoundary.tsx @@ -1,13 +1,24 @@ import {MutationCache, QueryCache, QueryClient, QueryClientProvider} from '@tanstack/react-query'; +import {RequestGetError} from '@errors/RequestGetError'; + import {useAppErrorStore} from '@store/appErrorStore'; const QueryClientBoundary = ({children}: React.PropsWithChildren) => { const {updateAppError} = useAppErrorStore(); const queryClient = new QueryClient({ + // errorBoundary를 사용하기 위해 true로 해줘야함. + defaultOptions: { + queries: { + throwOnError: true, + }, + }, queryCache: new QueryCache({ onError: (error: Error) => { + // errorBoundary로 처리해야하는 에러인 경우 updateAppError를 하지 못하도록 얼리리턴 + if (error instanceof RequestGetError && error.errorHandlingStrategy === 'errorBoundary') return; + updateAppError(error); }, }), diff --git a/client/src/errors/FetchError.ts b/client/src/errors/FetchError.ts deleted file mode 100644 index 9123a80b5..000000000 --- a/client/src/errors/FetchError.ts +++ /dev/null @@ -1,23 +0,0 @@ -import {FetchErrorType} from '../types/fetchErrorType'; - -class FetchError extends Error { - requestBody; - status; - endpoint; - errorInfo; - method; - - constructor({requestBody, status, endpoint, errorInfo, method, name, message}: FetchErrorType) { - super(errorInfo.errorCode); - - this.requestBody = requestBody; - this.status = status; - this.endpoint = endpoint; - this.errorInfo = errorInfo; - this.method = method; - this.name = name; - this.message = message; - } -} - -export default FetchError; diff --git a/client/src/errors/RequestError.ts b/client/src/errors/RequestError.ts new file mode 100644 index 000000000..939b29586 --- /dev/null +++ b/client/src/errors/RequestError.ts @@ -0,0 +1,24 @@ +import {RequestErrorType} from './requestErrorType'; + +class RequestError extends Error { + requestBody; + status; + endpoint; + method; + errorCode; + message; + + constructor({requestBody, status, endpoint, errorCode, method, name, message}: RequestErrorType) { + super(errorCode); + + this.requestBody = requestBody; + this.status = status; + this.endpoint = endpoint; + this.errorCode = errorCode; + this.message = message; + this.method = method; + this.name = name; + } +} + +export default RequestError; diff --git a/client/src/errors/RequestGetError.ts b/client/src/errors/RequestGetError.ts new file mode 100644 index 000000000..da9a8e10b --- /dev/null +++ b/client/src/errors/RequestGetError.ts @@ -0,0 +1,21 @@ +import RequestError from './RequestError'; +import {RequestErrorType} from './requestErrorType'; + +type ErrorHandlingStrategy = 'toast' | 'errorBoundary'; + +export type WithErrorHandlingStrategy<P = unknown> = P & { + errorHandlingStrategy?: ErrorHandlingStrategy; +}; + +class RequestGetError extends RequestError { + errorHandlingStrategy: string; + + // errorHandlingType은 기본적으로 제일 많이 사용되는 toast로 했습니다. + constructor({errorHandlingStrategy = 'toast', ...rest}: WithErrorHandlingStrategy<RequestErrorType>) { + super(rest); + + this.errorHandlingStrategy = errorHandlingStrategy; + } +} + +export {RequestGetError}; diff --git a/client/src/errors/requestErrorType.ts b/client/src/errors/requestErrorType.ts new file mode 100644 index 000000000..22c9f05f5 --- /dev/null +++ b/client/src/errors/requestErrorType.ts @@ -0,0 +1,10 @@ +import {Body, Method} from '@apis/fetcher'; + +export type RequestErrorType = Error & { + requestBody: Body; + status: number; + endpoint: string; + errorCode: string; + message: string; + method?: Method; +}; diff --git a/client/src/hooks/queries/bill/useRequestGetBillDetails.ts b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts index 604bd7cd8..181777011 100644 --- a/client/src/hooks/queries/bill/useRequestGetBillDetails.ts +++ b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts @@ -1,17 +1,22 @@ import {useQuery} from '@tanstack/react-query'; import {requestGetBillDetails} from '@apis/request/bill'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestGetBillDetails = (billId: number) => { +type UseRequestGetBillDetails = { + billId: number; +}; + +const useRequestGetBillDetails = ({billId, ...props}: WithErrorHandlingStrategy<UseRequestGetBillDetails>) => { const eventId = getEventIdByUrl(); const {data, ...rest} = useQuery({ queryKey: [QUERY_KEYS.billDetails, billId], - queryFn: () => requestGetBillDetails({eventId, billId}), + queryFn: () => requestGetBillDetails({eventId, billId, ...props}), }); return { diff --git a/client/src/hooks/queries/event/useRequestGetEvent.ts b/client/src/hooks/queries/event/useRequestGetEvent.ts index c85faae83..999688842 100644 --- a/client/src/hooks/queries/event/useRequestGetEvent.ts +++ b/client/src/hooks/queries/event/useRequestGetEvent.ts @@ -1,17 +1,18 @@ import {useQuery} from '@tanstack/react-query'; import {requestGetEvent} from '@apis/request/event'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestGetEvent = () => { +const useRequestGetEvent = ({...props}: WithErrorHandlingStrategy | null = {}) => { const eventId = getEventIdByUrl(); const {data, ...rest} = useQuery({ queryKey: [QUERY_KEYS.eventName], - queryFn: () => requestGetEvent({eventId}), + queryFn: () => requestGetEvent({eventId, ...props}), }); return { diff --git a/client/src/hooks/queries/member/useRequestGetAllMembers.ts b/client/src/hooks/queries/member/useRequestGetAllMembers.ts index 0efe290b9..bd28e5836 100644 --- a/client/src/hooks/queries/member/useRequestGetAllMembers.ts +++ b/client/src/hooks/queries/member/useRequestGetAllMembers.ts @@ -1,17 +1,18 @@ import {useQuery} from '@tanstack/react-query'; import {requestGetAllMembers} from '@apis/request/member'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestGetAllMembers = () => { +const useRequestGetAllMembers = ({...props}: WithErrorHandlingStrategy | null = {}) => { const eventId = getEventIdByUrl(); const {data, ...rest} = useQuery({ queryKey: [QUERY_KEYS.allMembers], - queryFn: () => requestGetAllMembers({eventId}), + queryFn: () => requestGetAllMembers({eventId, ...props}), }); return {members: data?.members ?? [], ...rest}; diff --git a/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts b/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts index 06c595e3b..536438b36 100644 --- a/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts +++ b/client/src/hooks/queries/member/useRequestGetCurrentMembers.ts @@ -1,17 +1,18 @@ import {useQuery} from '@tanstack/react-query'; import {requestGetCurrentMembers} from '@apis/request/member'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestGetCurrentMembers = () => { +const useRequestGetCurrentMembers = ({...props}: WithErrorHandlingStrategy | null = {}) => { const eventId = getEventIdByUrl(); const {data, ...rest} = useQuery({ queryKey: [QUERY_KEYS.currentMembers], - queryFn: () => requestGetCurrentMembers({eventId}), + queryFn: () => requestGetCurrentMembers({eventId, ...props}), }); return {currentMembers: data?.members ?? [], ...rest}; diff --git a/client/src/hooks/queries/report/useRequestGetReports.ts b/client/src/hooks/queries/report/useRequestGetReports.ts index 5cb4de120..e1a91fc74 100644 --- a/client/src/hooks/queries/report/useRequestGetReports.ts +++ b/client/src/hooks/queries/report/useRequestGetReports.ts @@ -1,17 +1,18 @@ import {useQuery} from '@tanstack/react-query'; import {requestGetReports} from '@apis/request/report'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestGetReports = () => { +const useRequestGetReports = ({...props}: WithErrorHandlingStrategy | null = {}) => { const eventId = getEventIdByUrl(); const {data, ...rest} = useQuery({ queryKey: [QUERY_KEYS.reports], - queryFn: () => requestGetReports({eventId}), + queryFn: () => requestGetReports({eventId, ...props}), }); return { diff --git a/client/src/hooks/queries/step/useRequestGetSteps.ts b/client/src/hooks/queries/step/useRequestGetSteps.ts index 312c03164..7b70bacef 100644 --- a/client/src/hooks/queries/step/useRequestGetSteps.ts +++ b/client/src/hooks/queries/step/useRequestGetSteps.ts @@ -2,6 +2,7 @@ import {useQuery} from '@tanstack/react-query'; import {useEffect} from 'react'; import {requestGetSteps} from '@apis/request/step'; +import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; @@ -9,13 +10,13 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestGetSteps = () => { +const useRequestGetSteps = ({...props}: WithErrorHandlingStrategy | null = {}) => { const eventId = getEventIdByUrl(); const {updateTotalExpenseAmount} = useTotalExpenseAmountStore(); const queryResult = useQuery({ queryKey: [QUERY_KEYS.steps], - queryFn: () => requestGetSteps({eventId}), + queryFn: () => requestGetSteps({eventId, ...props}), }); useEffect(() => { diff --git a/client/src/hooks/useBillDetails/useBillDetails.ts b/client/src/hooks/useBillDetails/useBillDetails.ts index 408bd043b..e4b7da915 100644 --- a/client/src/hooks/useBillDetails/useBillDetails.ts +++ b/client/src/hooks/useBillDetails/useBillDetails.ts @@ -6,7 +6,7 @@ import useRequestGetBillDetails from '@hooks/queries/bill/useRequestGetBillDetai import useRequestPutBillDetails from '@hooks/queries/bill/useRequestPutBillDetails'; const useBillDetails = (billId: number, totalPrice: number, onClose: () => void) => { - const {reportFromServer, isSuccess} = useRequestGetBillDetails(billId); + const {reportFromServer, isSuccess} = useRequestGetBillDetails({billId}); const {putBillDetails} = useRequestPutBillDetails(billId); const [billDetails, setBillDetails] = useState<BillDetail[]>(reportFromServer); diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts index 849f6f5f2..ba8549258 100644 --- a/client/src/hooks/useSetEventPasswordPage.ts +++ b/client/src/hooks/useSetEventPasswordPage.ts @@ -61,4 +61,5 @@ const useSetEventPasswordPage = () => { return {submitPassword, errorMessage, password, handleChange, onSuccess, canSubmit, isPostEventPending}; }; + export default useSetEventPasswordPage; diff --git a/client/src/types/fetchErrorType.ts b/client/src/types/fetchErrorType.ts deleted file mode 100644 index 19fe8ee6f..000000000 --- a/client/src/types/fetchErrorType.ts +++ /dev/null @@ -1,11 +0,0 @@ -import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; - -import {Method} from '@apis/fetcher'; - -export type FetchErrorType = Error & { - requestBody: string; - status: number; - endpoint: string; - errorInfo: ErrorInfo; - method: Method; -}; diff --git a/client/src/utils/captureError.ts b/client/src/utils/captureError.ts index 67a30ac99..2c445cf82 100644 --- a/client/src/utils/captureError.ts +++ b/client/src/utils/captureError.ts @@ -1,49 +1,53 @@ -import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; +import RequestError from '@errors/RequestError'; import sendLogToSentry from './sendLogToSentry'; -export const captureError = async (error: Error, errorInfo: ErrorInfo) => { +export const captureError = async (error: Error) => { // prod 환경에서만 Sentry capture 실행 if (process.env.NODE_ENV !== 'production') return; - switch (errorInfo?.errorCode) { - case 'INTERNAL_SERVER_ERROR': - sendLogToSentry({error, errorInfo, level: 'fatal'}); - break; + if (error instanceof RequestError) { + switch (error.errorCode) { + case 'INTERNAL_SERVER_ERROR': + sendLogToSentry({error, level: 'fatal'}); + break; - case 'FORBIDDEN': - sendLogToSentry({error, errorInfo}); + case 'FORBIDDEN': + sendLogToSentry({error}); - break; + break; - case 'TOKEN_INVALID': - sendLogToSentry({error, errorInfo}); + case 'TOKEN_INVALID': + sendLogToSentry({error}); - break; + break; - case 'TOKEN_EXPIRED': - sendLogToSentry({error, errorInfo}); + case 'TOKEN_EXPIRED': + sendLogToSentry({error}); - break; + break; - case 'TOKEN_NOT_FOUND': - sendLogToSentry({error, errorInfo}); + case 'TOKEN_NOT_FOUND': + sendLogToSentry({error}); - break; + break; - // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 - case 'PASSWORD_INVALID': - sendLogToSentry({error, errorInfo, level: 'debug'}); + // 비밀 번호를 까먹는 사람이 얼마나 많은 지 추측하기 위함 + case 'PASSWORD_INVALID': + sendLogToSentry({error, level: 'debug'}); - break; + break; - // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 - case 'BILL_ACTION_PRICE_INVALID': - sendLogToSentry({error, errorInfo, level: 'debug'}); - break; + // 1천만원 이상 입력하는 사람이 얼마나 많은 지 추측하기 위함 + case 'BILL_ACTION_PRICE_INVALID': + sendLogToSentry({error, level: 'debug'}); + break; - default: - sendLogToSentry({error, errorInfo, level: 'fatal'}); - break; + default: + sendLogToSentry({error, level: 'fatal'}); + break; + } + } else { + sendLogToSentry({error, level: 'fatal'}); } }; diff --git a/client/src/utils/isRequestError.ts b/client/src/utils/isRequestError.ts new file mode 100644 index 000000000..98dfc90f5 --- /dev/null +++ b/client/src/utils/isRequestError.ts @@ -0,0 +1,7 @@ +import RequestError from '@errors/RequestError'; + +const isRequestError = (error: Error) => { + return error instanceof RequestError; +}; + +export default isRequestError; diff --git a/client/src/utils/sendLogToSentry.ts b/client/src/utils/sendLogToSentry.ts index 22d736b6c..e7aec9286 100644 --- a/client/src/utils/sendLogToSentry.ts +++ b/client/src/utils/sendLogToSentry.ts @@ -1,10 +1,6 @@ import * as Sentry from '@sentry/react'; -import {ErrorInfo} from '@components/AppErrorBoundary/ErrorCatcher'; - -import {UNKNOWN_ERROR} from '@constants/errorMessage'; - -import FetchError from '../errors/FetchError'; +import RequestError from '../errors/RequestError'; /** * level은 아래와 같은 용도에 맞게 지정해줍니다. @@ -21,44 +17,34 @@ type SentryLevel = 'fatal' | 'error' | 'warning' | 'info' | 'debug' | 'log'; type SendLogToSentry = { level?: SentryLevel; error: Error; - errorInfo: ErrorInfo; }; -const sendLogToSentry = ({level = 'error', error, errorInfo}: SendLogToSentry) => { +const sendLogToSentry = ({level = 'error', error}: SendLogToSentry) => { Sentry.withScope(scope => { - const {errorCode, message} = errorInfo; scope.setLevel(level); - scope.setTag('environment', process.env.NODE_ENV); - - if (error instanceof FetchError) { + if (error instanceof RequestError) { + const {errorCode, message} = error; scope.setTags({ endpoint: error.endpoint, url: window.location.href, - errorCode, errorMessage: message, status: error.status, - // requestBody: JSON.stringify(error.requestBody), - method: error.method, - }); - - Sentry.captureMessage(`${errorCode}`); - } else if (error instanceof Error) { - scope.setTags({ - url: window.location.href, errorCode, - errorMessage: message, + requestBody: JSON.stringify(error.requestBody), + method: error.method, }); - Sentry.captureMessage(`${errorCode}`); } else { + const {name, message} = error; + scope.setTags({ url: window.location.href, - errorCode, - message: UNKNOWN_ERROR, - name: UNKNOWN_ERROR, + name, + message, }); - Sentry.captureMessage(`${errorCode}`); + + Sentry.captureMessage(`${name}`); } }); }; From e7fe3dd82a8a15089334718be01d578a42089f2d Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:30:37 +0900 Subject: [PATCH 236/273] =?UTF-8?q?docs:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EC=86=8C=EA=B0=9C=EA=B8=80=20=EC=9E=91=EC=84=B1=20(#295)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: 서비스 소개글 작성 * docs: 서비스 소개 이미지로 대체 --------- Co-authored-by: kunsanglee <85242378+kunsanglee@users.noreply.github.com> --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4bf6bd7c1..c0b59222a 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ -# 2024-haeng-dong \ No newline at end of file +# 행동대장들의 정산을 간편하게💰행동대장 + +![service introduce](https://github.com/user-attachments/assets/9e51f7a3-0326-4c06-8b03-65aca574c10c) From 349230b82159f3e5a05d2ba2dc799e85455cde3e Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:03:07 +0900 Subject: [PATCH 237/273] =?UTF-8?q?feat:=20=EC=B0=B8=EC=97=AC=EC=9E=90=20?= =?UTF-8?q?=EB=B3=84=20=EB=82=B4=EC=97=AD=EC=97=90=EC=84=9C=20=ED=86=A0?= =?UTF-8?q?=EC=8A=A4=EB=A1=9C=20=EC=86=A1=EA=B8=88=20=EC=9C=A0=EB=8F=84?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20(=EB=A7=88=EB=AC=B4?= =?UTF-8?q?=EB=A6=AC)=20(#577)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: png 확장자 추가로 인한 file-loader설치 및 png 확장자 선언 * feat: icon에 toss 타입 추가 * feat: 은행 선택 디자인 구현 * design: 은행선택 grid 반응형적용 * feat: 계좌번호 입력 플로우 생성 * fix: 콘솔 창 오류 제거 * fix: 은행 이름 변경 * design: 지출 리스트 갭 변경 * feat: 참여자 별 내역에서 은행아이콘(토스) 보이도록 설정 * feat: cansubmit 추가 * fix: 스토리북 prop 누락 추가 * chore: png도 jest mock되도록 설정 * fix: 테스트 환경에선 상대경로 api, 브라우저 환경에선 절대경로 api를 호출하도록 설정 * feat: 은행 송금 버튼 생성 * feat: 버튼 클릭 시 모바일 환경에서 토스로 넘기는 기능 * feat: 모바일 기기 감지 기능 구현 * refactor: 디자인 컴포넌트에 맞게 디자인 외 기능 외부로 분리 * style: Bank send Flex 컴포넌트 이용 * style: bank select Flex 컴포넌트 이용 * style: expense list flex 컴포넌트로 이용 * style: 사용하지 않는 import 제거 * style: fileMock -> imageFileMock으로 파일 이름 변경 * feat: 이벤트 정보를 불러오고 정보를 수정하는 api 구현 * feat: eventName -> eventOutline으로 이름 변경 * feat: 계좌를 입력받는 기능 구현 * feat: 계좌번호 라우트 이벤트 id를 받도록 변경 * fix: 서버상태와 클라이언트 상태 분리 * test: event outline 수정 핸들러 등록 * fix: input 초기값 undefined 주지 않도록 설정 * fix: 변경된 상태를 보내도록 수정 * test: 초기 은행이름 맞춰줌 * feat: input에 항상 테두리가 보이도록 설정하는 옵션 추가 * feat: label input 라벨이 항상 보이도록 하는 옵션 추가 * fix: Line 컴포넌트 key prop 추가 * feat: index에 Line, FunnelLayout 추가 * feat: FunnelLayout 추가 * fix: 변경된 파일구조 반영 * style: eventName => event로 포괄적인 의미로 수정 * style: account => update로 라우팅 변경 * style: 퍼널 구조 형식으로 페이지 레이아웃 수정 * style: get event return을 묶어서 return * fix: mocking base url 수정 * style: 디렉토리 이름 변경 * style: 사용하지 않게 된 핸들러 제거 * refactor: Event type 확장으로 기존에 선언했던 EventOutline 타입 제거 및 반영 * fix: 변경된 api 반영 * refactor: mutateAsync로 변경하여 비동기함수로 변경 * feat: 계좌번호 등록하고 관리페이지로 돌아가는 기능 구현 * feat: 계좌정보가 등록되지 않았을 때 공유 버튼을 누르면 계좌번호 입력을 유도하는 기능 구현 * refactor: 마지막 path를 바꿔주는 함수를 사용해서 route 하는 방식으로 변경 * feat: 마지막 변경이 아니라 마지막 path를 빼는 기능으로 변경 * feat: 바뀐 url path 정책 반영 * feat: 송금액이 0원일 때의 대체 버튼 추가 * design: 토스 아이콘 크기 수정 * feat: 계좌번호 정보를 복사 후 토스를 여는 기능 구현 * feat: 계좌번호가 입력되지 않았을 때 토스 송금 버튼을 눌렀을 때 토스트가 나오도록 설정 * Merge branch 'fe-dev' of https://github.com/woowacourse-teams/2024-haeng-dong into feature/#569 * fix: 지우지 않은 코드 삭제 * fix: 홈에서 버튼 누를 때 navigate 오류나는 버그 수정 * style: isFinish -> isDeposited로 prop 명 변경 * design: 불필요한 gap 제거 * refactor: mutation rest return하도록 설정 --- client/src/apis/request/event.ts | 22 +++--- .../BankSendButton/BankSelect.stories.tsx | 7 +- .../BankSendButton/BankSendButton.style.ts | 13 +++- .../BankSendButton/BankSendButton.tsx | 27 +++++-- .../components/ExpenseList/ExpenseList.tsx | 6 +- .../Design/components/Icon/Icon.tsx | 2 +- .../Design/components/Input/Input.style.ts | 30 +++++--- .../Design/components/Input/Input.tsx | 15 +++- .../Design/components/Input/Input.type.ts | 1 + .../components/LabelInput/LabelInput.style.ts | 14 +++- .../components/LabelInput/LabelInput.tsx | 19 ++++- .../components/LabelInput/LabelInput.type.ts | 7 +- .../components/Design/components/Top/Line.tsx | 9 ++- client/src/components/Design/index.tsx | 4 + .../Design/layouts/FunnelLayout.tsx | 19 +++++ client/src/components/Reports/Reports.tsx | 24 +----- .../ShareEventButton/ShareEventButton.tsx | 37 +++++++++- client/src/constants/errorMessage.ts | 1 + client/src/constants/queryKeys.ts | 2 +- client/src/constants/routerUrls.ts | 1 + .../hooks/queries/event/useRequestGetEvent.ts | 6 +- .../queries/event/useRequestPatchEvent.ts | 31 ++++++++ client/src/hooks/useAccount.ts | 51 ++++++++++--- client/src/hooks/useEventPageLayout.ts | 14 +++- client/src/hooks/useReportsPage.ts | 55 ++++++++++++++ client/src/hooks/useShareEvent.ts | 6 +- client/src/mocks/handlers/eventHandlers.ts | 8 +- client/src/mocks/sharedState.ts | 4 +- client/src/pages/Account/Account.tsx | 52 ------------- client/src/pages/AccountPage/Account.tsx | 73 +++++++++++++++++++ .../src/pages/EventPage/EventPageLayout.tsx | 11 +-- client/src/router.tsx | 6 +- client/src/utils/getDeletedLastPath.ts | 7 ++ 33 files changed, 429 insertions(+), 155 deletions(-) create mode 100644 client/src/components/Design/layouts/FunnelLayout.tsx create mode 100644 client/src/hooks/queries/event/useRequestPatchEvent.ts create mode 100644 client/src/hooks/useReportsPage.ts delete mode 100644 client/src/pages/Account/Account.tsx create mode 100644 client/src/pages/AccountPage/Account.tsx create mode 100644 client/src/utils/getDeletedLastPath.ts diff --git a/client/src/apis/request/event.ts b/client/src/apis/request/event.ts index a81e4c00e..27104d0c8 100644 --- a/client/src/apis/request/event.ts +++ b/client/src/apis/request/event.ts @@ -1,8 +1,8 @@ import {Event, EventId} from 'types/serviceType'; import {WithErrorHandlingStrategy} from '@errors/RequestGetError'; -import {USER_API_PREFIX} from '@apis/endpointPrefix'; -import {requestGet, requestPostWithResponse, requestPut} from '@apis/fetcher'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; +import {requestGet, requestPatch, requestPostWithResponse, requestPut} from '@apis/fetcher'; import {WithEventId} from '@apis/withId.type'; export interface RequestPostEvent { @@ -27,19 +27,15 @@ export const requestGetEvent = async ({eventId, ...props}: WithEventId<WithError }); }; -export interface RequestPutEvent { - eventName?: string; - bankName?: string; - accountNumber?: string; -} +export type RequestPatchEvent = WithEventId & { + eventOutline: Partial<Event>; +}; -export const requestPutEvent = async ({eventId, eventName, bankName, accountNumber}: WithEventId<RequestPutEvent>) => { - return await requestPut({ - endpoint: `${USER_API_PREFIX}/${eventId}`, +export const requestPatchEvent = async ({eventId, eventOutline}: RequestPatchEvent) => { + return requestPatch({ + endpoint: `${ADMIN_API_PREFIX}/${eventId}`, body: { - eventName, - bankName, - accountNumber, + ...eventOutline, }, }); }; diff --git a/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx b/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx index 87d597212..3d68811ae 100644 --- a/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx +++ b/client/src/components/Design/components/BankSendButton/BankSelect.stories.tsx @@ -10,7 +10,12 @@ const meta = { parameters: { // layout: 'centered', }, - argTypes: {}, + argTypes: { + isDeposited: { + description: '', + control: {type: 'boolean'}, + }, + }, args: { clipboardText: '토스뱅크 010100-10-123123', onBankButtonClick: () => console.log('안녕'), diff --git a/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts b/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts index 584fafde0..bb6bbffb7 100644 --- a/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts +++ b/client/src/components/Design/components/BankSendButton/BankSendButton.style.ts @@ -4,9 +4,20 @@ import {Theme} from '@components/Design/theme/theme.type'; export const bankButtonStyle = (theme: Theme) => css({ - padding: '0.125rem 0.34375rem', + width: '3.25rem', + height: '1.5rem', backgroundColor: theme.colors.tertiary, borderRadius: '0.5rem', }); + +export const isDepositedStyle = (theme: Theme) => + css({ + width: '3.25rem', + height: '1.5rem', + + backgroundColor: theme.colors.grayContainer, + + borderRadius: '0.5rem', + }); diff --git a/client/src/components/Design/components/BankSendButton/BankSendButton.tsx b/client/src/components/Design/components/BankSendButton/BankSendButton.tsx index cd2a48cd2..3351b7dcc 100644 --- a/client/src/components/Design/components/BankSendButton/BankSendButton.tsx +++ b/client/src/components/Design/components/BankSendButton/BankSendButton.tsx @@ -7,23 +7,38 @@ import Icon from '../Icon/Icon'; import Text from '../Text/Text'; import Flex from '../Flex/Flex'; -import {bankButtonStyle} from './BankSendButton.style'; +import {bankButtonStyle, isDepositedStyle} from './BankSendButton.style'; type BankSendButtonProps = React.HTMLAttributes<HTMLButtonElement> & { clipboardText: string; onBankButtonClick: () => void; + isDeposited?: boolean; }; -const BankSendButton = ({clipboardText, onBankButtonClick, ...buttonProps}: BankSendButtonProps) => { +const BankSendButton = ({ + clipboardText, + onBankButtonClick, + isDeposited = false, + ...buttonProps +}: BankSendButtonProps) => { const {theme} = useTheme(); - return ( + + return isDeposited ? ( + <button css={isDepositedStyle(theme)} disabled {...buttonProps}> + <Flex justifyContent="center" alignItems="center"> + <Text size="tiny" textColor="black"> + 송금완료 + </Text> + </Flex> + </button> + ) : ( <CopyToClipboard text={clipboardText} onCopy={onBankButtonClick}> <button css={bankButtonStyle(theme)} {...buttonProps}> - <Flex alignItems="center" gap="0.25rem"> - <Icon iconType="toss" /> - <Text size="caption" textColor="black"> + <Flex justifyContent="center" alignItems="center" gap="0.125rem"> + <Text size="tiny" textColor="black"> 송금 </Text> + <Icon iconType="toss" /> </Flex> </button> </CopyToClipboard> diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx index 67d293111..6191e80ba 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx @@ -22,7 +22,11 @@ function ExpenseItem({name, price, onBankButtonClick, clipboardText, ...divProps <Flex alignItems="center" gap="0.5rem"> <Text>{price.toLocaleString('ko-kr')}원</Text> {isMobileDevice() ? ( - <BankSendButton clipboardText={clipboardText} onBankButtonClick={onBankButtonClick} /> + <BankSendButton + clipboardText={clipboardText} + onBankButtonClick={onBankButtonClick} + isDeposited={price <= 0} + /> ) : ( <IconButton variants="none" size="small"> <Icon iconType="rightChevron" /> diff --git a/client/src/components/Design/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx index c900c289c..da65acf1c 100644 --- a/client/src/components/Design/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -24,9 +24,9 @@ const ICON = { error: <Error />, confirm: <Confirm />, trash: <Trash />, + toss: <img src={Toss} width="16" height="16" alt="toss icon" />, check: <Check />, x: <X />, - toss: <img src={Toss} width="24" height="24" alt="toss icon" />, meatballs: <Meatballs />, }; diff --git a/client/src/components/Design/components/Input/Input.style.ts b/client/src/components/Design/components/Input/Input.style.ts index a9ddff89d..3748d6b46 100644 --- a/client/src/components/Design/components/Input/Input.style.ts +++ b/client/src/components/Design/components/Input/Input.style.ts @@ -25,20 +25,32 @@ export const inputBoxStyle = ( inputType: InputType = 'input', isFocus: boolean, isError: boolean | undefined, + isAlwaysOnBorder: boolean, ) => - css({ - display: 'flex', - justifyContent: 'space-between', - gap: '1rem', - padding: '0.75rem 1rem', - borderRadius: '1rem', - backgroundColor: getBackgroundColorStyle(theme, inputType), + css([ + { + display: 'flex', + justifyContent: 'space-between', + gap: '1rem', + padding: '0.75rem 1rem', + borderRadius: '1rem', + backgroundColor: getBackgroundColorStyle(theme, inputType), + + boxSizing: 'border-box', + boxShadow: getBorderStyle(isFocus, theme, isError), + }, + isAlwaysOnBorder ? inputBoxAlwaysBorderStyle(theme) : inputBoxAnimationStyle(), + ]); +export const inputBoxAnimationStyle = () => + css({ transition: '0.2s', transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); - boxSizing: 'border-box', - boxShadow: getBorderStyle(isFocus, theme, isError), +export const inputBoxAlwaysBorderStyle = (theme: Theme) => + css({ + boxShadow: `0 0 0 1px ${theme.colors.primary} inset`, }); export const inputStyle = (theme: Theme) => diff --git a/client/src/components/Design/components/Input/Input.tsx b/client/src/components/Design/components/Input/Input.tsx index 111b42f1c..61952517b 100644 --- a/client/src/components/Design/components/Input/Input.tsx +++ b/client/src/components/Design/components/Input/Input.tsx @@ -9,7 +9,18 @@ import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( - {value: propsValue, onChange, onFocus, onBlur, inputType, isError, placeholder, autoFocus, ...htmlProps}: InputProps, + { + value: propsValue, + onChange, + onFocus, + onBlur, + inputType, + isError, + placeholder, + autoFocus, + isAlwaysOnBorder = false, + ...htmlProps + }: InputProps, ref, ) { const {theme} = useTheme(); @@ -25,7 +36,7 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro useImperativeHandle(ref, () => inputRef.current!); return ( - <div css={inputBoxStyle(theme, inputType, hasFocus, isError)}> + <div css={inputBoxStyle(theme, inputType, hasFocus, isError, isAlwaysOnBorder)}> <input css={inputStyle(theme)} ref={inputRef} diff --git a/client/src/components/Design/components/Input/Input.type.ts b/client/src/components/Design/components/Input/Input.type.ts index 2cfdfcd4a..7360c1061 100644 --- a/client/src/components/Design/components/Input/Input.type.ts +++ b/client/src/components/Design/components/Input/Input.type.ts @@ -2,6 +2,7 @@ import {Theme} from '@theme/theme.type'; export interface InputStyleProps { theme?: Theme; + isAlwaysOnBorder?: boolean; } export type InputType = 'input' | 'search'; diff --git a/client/src/components/Design/components/LabelInput/LabelInput.style.ts b/client/src/components/Design/components/LabelInput/LabelInput.style.ts index df64636e9..e6f00284d 100644 --- a/client/src/components/Design/components/LabelInput/LabelInput.style.ts +++ b/client/src/components/Design/components/LabelInput/LabelInput.style.ts @@ -2,11 +2,17 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; -export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => - css({ - height: '1.125rem', - color: theme.colors.gray, +export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean, isAlwaysOnLabel: boolean) => + css([ + { + height: '1.125rem', + color: theme.colors.gray, + }, + !isAlwaysOnLabel && labelTextAnimationStyle(hasFocus, hasValue), + ]); +export const labelTextAnimationStyle = (hasFocus: boolean, hasValue: boolean) => + css({ opacity: hasFocus || hasValue ? '1' : '0', transition: '0.2s', diff --git a/client/src/components/Design/components/LabelInput/LabelInput.tsx b/client/src/components/Design/components/LabelInput/LabelInput.tsx index f3228cde2..8f7b1b5e3 100644 --- a/client/src/components/Design/components/LabelInput/LabelInput.tsx +++ b/client/src/components/Design/components/LabelInput/LabelInput.tsx @@ -13,7 +13,14 @@ import {useLabelInput} from './useLabelInput'; import {LabelInputProps} from './LabelInput.type'; const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, LabelInputProps>(function LabelInput( - {labelText, errorText, isError, ...htmlProps}: LabelInputProps, + { + labelText, + errorText, + isError, + isAlwaysOnLabel = false, + isAlwaysOnInputBorder = false, + ...htmlProps + }: LabelInputProps, ref, ) { useImperativeHandle(ref, () => inputRef.current!); @@ -25,7 +32,7 @@ const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, Label return ( <Flex flexDirection="column" gap="0.375rem"> <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> - <Text size="caption" css={labelTextStyle(theme, hasFocus, !!htmlProps.value)}> + <Text size="caption" css={labelTextStyle(theme, hasFocus, !!htmlProps.value, isAlwaysOnLabel)}> {labelText} </Text> {errorText && ( @@ -35,7 +42,13 @@ const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, Label )} </Flex> <Flex flexDirection="column" gap="0.5rem"> - <Input ref={inputRef} isError={isError} placeholder={labelText} {...htmlProps} /> + <Input + ref={inputRef} + isError={isError} + placeholder={labelText} + isAlwaysOnBorder={isAlwaysOnInputBorder} + {...htmlProps} + /> </Flex> </Flex> ); diff --git a/client/src/components/Design/components/LabelInput/LabelInput.type.ts b/client/src/components/Design/components/LabelInput/LabelInput.type.ts index 83e7e9751..84bfc7279 100644 --- a/client/src/components/Design/components/LabelInput/LabelInput.type.ts +++ b/client/src/components/Design/components/LabelInput/LabelInput.type.ts @@ -1,4 +1,7 @@ -export interface LabelInputStyleProps {} +export interface LabelInputStyleProps { + isAlwaysOnLabel?: boolean; + isAlwaysOnInputBorder?: boolean; +} export interface LabelInputCustomProps { labelText: string; @@ -7,6 +10,6 @@ export interface LabelInputCustomProps { autoFocus: boolean; } -export type LabelInputOptionProps = LabelInputCustomProps & LabelInputCustomProps; +export type LabelInputOptionProps = LabelInputCustomProps & LabelInputStyleProps; export type LabelInputProps = React.ComponentProps<'input'> & LabelInputOptionProps; diff --git a/client/src/components/Design/components/Top/Line.tsx b/client/src/components/Design/components/Top/Line.tsx index 552dc0276..06669eb1b 100644 --- a/client/src/components/Design/components/Top/Line.tsx +++ b/client/src/components/Design/components/Top/Line.tsx @@ -24,9 +24,14 @@ export default function Line({text, emphasize = []}: Props) { display: flex; `} > - {elements.map(text => { + {elements.map((text, index) => { return ( - <Text size="subTitle" textColor={emphasize.includes(text) ? 'black' : 'gray'} style={{whiteSpace: 'pre'}}> + <Text + key={`${text}-${index}`} + size="subTitle" + textColor={emphasize.includes(text) ? 'black' : 'gray'} + style={{whiteSpace: 'pre'}} + > {`${text}`} </Text> ); diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx index 9c5af6e8f..7f1f3e7a2 100644 --- a/client/src/components/Design/index.tsx +++ b/client/src/components/Design/index.tsx @@ -1,4 +1,5 @@ import {MainLayout} from './layouts/MainLayout'; +import FunnelLayout from './layouts/FunnelLayout'; import {ContentLayout} from './layouts/ContentLayout'; import {HDesignProvider, useTheme} from './theme/HDesignProvider'; import BankSelect from './components/BankSelect/BankSelect'; @@ -18,6 +19,7 @@ import ListButton from './components/ListButton/ListButton'; import LabelGroupInput from './components/LabelGroupInput/LabelGroupInput'; import Search from './components/Search/Search'; import Switch from './components/Switch/Switch'; +import Top from './components/Top/Top'; import Tab from './components/Tabs/Tab'; import Tabs from './components/Tabs/Tabs'; import Text from './components/Text/Text'; @@ -44,6 +46,7 @@ export { LabelGroupInput, Search, Switch, + Top, Tab, Tabs, Text, @@ -52,6 +55,7 @@ export { TopNav, Back, MainLayout, + FunnelLayout, ContentLayout, HDesignProvider, useTheme, diff --git a/client/src/components/Design/layouts/FunnelLayout.tsx b/client/src/components/Design/layouts/FunnelLayout.tsx new file mode 100644 index 000000000..7dbe0c8e6 --- /dev/null +++ b/client/src/components/Design/layouts/FunnelLayout.tsx @@ -0,0 +1,19 @@ +import {Flex} from '..'; + +const FunnelLayout = ({children}: React.PropsWithChildren) => { + return ( + <Flex + flexDirection="column" + justifyContent="flexStart" + padding="1rem" + paddingInline="1rem" + gap="1rem" + width="100%" + height="100%" + > + {children} + </Flex> + ); +}; + +export default FunnelLayout; diff --git a/client/src/components/Reports/Reports.tsx b/client/src/components/Reports/Reports.tsx index 028c55d17..75804f920 100644 --- a/client/src/components/Reports/Reports.tsx +++ b/client/src/components/Reports/Reports.tsx @@ -1,31 +1,13 @@ -import React, {useState} from 'react'; - -import {useSearchReports} from '@hooks/useSearchReports'; +import useReportsPage from '@hooks/useReportsPage'; import {ExpenseList, Flex, Input, Text} from '@HDesign/index'; const Reports = () => { - const [name, setName] = useState(''); - const {matchedReports, reports} = useSearchReports({name}); - - const changeName = ({target}: React.ChangeEvent<HTMLInputElement>) => { - setName(target.value); - }; - - const onBankButtonClick = () => { - const url = 'supertoss://'; - window.location.href = url; - }; - - const expenseListProp = matchedReports.map(member => ({ - ...member, - clipboardText: `계좌번호 받아와야 함 ${member.price}원`, - onBankButtonClick, - })); + const {isEmpty, matchedReports, expenseListProp, name, changeName} = useReportsPage(); return ( <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - {reports.length > 0 ? ( + {!isEmpty ? ( <> <Input inputType="search" value={name} onChange={changeName} placeholder="참여자 이름" /> {matchedReports.length !== 0 && <ExpenseList expenseList={expenseListProp} />} diff --git a/client/src/components/ShareEventButton/ShareEventButton.tsx b/client/src/components/ShareEventButton/ShareEventButton.tsx index ff191a4cc..765bc11cc 100644 --- a/client/src/components/ShareEventButton/ShareEventButton.tsx +++ b/client/src/components/ShareEventButton/ShareEventButton.tsx @@ -1,21 +1,50 @@ import CopyToClipboard from 'react-copy-to-clipboard'; +import {useNavigate} from 'react-router-dom'; import {useToast} from '@hooks/useToast/useToast'; +import {Event} from 'types/serviceType'; import useShareEvent from '@hooks/useShareEvent'; import {Button} from '@components/Design'; import isMobileDevice from '@utils/isMobileDevice'; +import getDeletedLastPath from '@utils/getDeletedLastPath'; + +type ShareEventButtonProps = { + eventOutline: Event; +}; + +const ShareEventButton = ({eventOutline}: ShareEventButtonProps) => { + const {eventName, bankName, accountNumber} = eventOutline; + const navigate = useNavigate(); -const ShareEventButton = () => { const {showToast} = useToast(); const isMobile = isMobileDevice(); - const {shareText, onShareButtonClick} = useShareEvent(isMobile); + const {shareText, onShareButtonClick} = useShareEvent(eventName, isMobile); + + const induceBankInfoBeforeShare = () => { + if (bankName === '' || accountNumber === '') { + showToast({ + showingTime: 3000, + message: '잠깐! 정산을 초대하기 전에\n계좌를 등록해주세요.', + type: 'error', + position: 'bottom', + bottom: '8rem', + }); + + const navigatePath = `${getDeletedLastPath(location.pathname)}/admin/edit`; + + navigate(navigatePath); + return; + } + + onShareButtonClick(); + }; return isMobile ? ( - <Button size="small" variants="secondary" onClick={onShareButtonClick}> + <Button size="small" variants="secondary" onClick={induceBankInfoBeforeShare}> 카카오톡으로 정산 초대하기 </Button> ) : ( @@ -31,7 +60,7 @@ const ShareEventButton = () => { }) } > - <Button size="small" variants="secondary" onClick={onShareButtonClick}> + <Button size="small" variants="secondary" onClick={induceBankInfoBeforeShare}> 정산 초대하기 </Button> </CopyToClipboard> diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index 42703bdf0..b33c12d5a 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -44,6 +44,7 @@ export const ERROR_MESSAGE = { purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', preventEmpty: '값은 비어있을 수 없어요', invalidInput: '올바르지 않은 입력이에요.', + emptyBank: '계좌번호가 입력되지 않아서\n토스 송금 기능을 사용할 수 없어요', }; export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; diff --git a/client/src/constants/queryKeys.ts b/client/src/constants/queryKeys.ts index 476c05766..b0835cfd5 100644 --- a/client/src/constants/queryKeys.ts +++ b/client/src/constants/queryKeys.ts @@ -1,6 +1,6 @@ const QUERY_KEYS = { steps: 'steps', - eventName: 'eventName', + event: 'event', allMembers: 'allMembers', currentMembers: 'currentMembers', reports: 'reports', diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index 99e82b5fe..2955115d7 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -8,4 +8,5 @@ export const ROUTER_URLS = { eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', addBill: 'event/:eventId/addBill', + eventEdit: 'event/:eventId/admin/edit', }; diff --git a/client/src/hooks/queries/event/useRequestGetEvent.ts b/client/src/hooks/queries/event/useRequestGetEvent.ts index 999688842..4ce9cd259 100644 --- a/client/src/hooks/queries/event/useRequestGetEvent.ts +++ b/client/src/hooks/queries/event/useRequestGetEvent.ts @@ -11,14 +11,14 @@ const useRequestGetEvent = ({...props}: WithErrorHandlingStrategy | null = {}) = const eventId = getEventIdByUrl(); const {data, ...rest} = useQuery({ - queryKey: [QUERY_KEYS.eventName], + queryKey: [QUERY_KEYS.event], queryFn: () => requestGetEvent({eventId, ...props}), }); return { eventName: data?.eventName ?? '', - bankName: data?.bankName, - accountName: data?.accountNumber, + bankName: data?.bankName ?? '', + accountNumber: data?.accountNumber ?? '', ...rest, }; }; diff --git a/client/src/hooks/queries/event/useRequestPatchEvent.ts b/client/src/hooks/queries/event/useRequestPatchEvent.ts new file mode 100644 index 000000000..e09a19c8b --- /dev/null +++ b/client/src/hooks/queries/event/useRequestPatchEvent.ts @@ -0,0 +1,31 @@ +import type {Event} from 'types/serviceType'; + +import {useMutation, useQueryClient} from '@tanstack/react-query'; + +import {requestPatchEvent} from '@apis/request/event'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import QUERY_KEYS from '@constants/queryKeys'; + +const useRequestPatchEventOutline = () => { + const eventId = getEventIdByUrl(); + + const queryClient = useQueryClient(); + + const {mutateAsync, ...rest} = useMutation({ + mutationFn: (eventOutline: Partial<Event>) => requestPatchEvent({eventId, eventOutline}), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [QUERY_KEYS.event], + }); + }, + }); + + return { + patchEventOutline: mutateAsync, + ...rest, + }; +}; + +export default useRequestPatchEventOutline; diff --git a/client/src/hooks/useAccount.ts b/client/src/hooks/useAccount.ts index 265ca04b5..4e3e83dfc 100644 --- a/client/src/hooks/useAccount.ts +++ b/client/src/hooks/useAccount.ts @@ -1,29 +1,60 @@ +import type {Event} from 'types/serviceType'; + import {useEffect, useState} from 'react'; +import useRequestPatchEvent from './queries/event/useRequestPatchEvent'; +import useRequestGetEvent from './queries/event/useRequestGetEvent'; + const useAccount = () => { - const [bank, setBank] = useState(''); - const [account, setAccount] = useState(''); + const {bankName, accountNumber} = useRequestGetEvent(); + + const [bankNameState, setBankName] = useState(bankName); + const [accountNumberState, setAccountNumber] = useState(accountNumber); const [canSubmit, setCanSubmit] = useState(false); + useEffect(() => { + setBankName(bankName); + setAccountNumber(accountNumber); + }, [bankName, accountNumber]); + + const {patchEventOutline} = useRequestPatchEvent(); + const selectBank = (name: string) => { - setBank(name); + setBankName(name); }; const handleAccount = (event: React.ChangeEvent<HTMLInputElement>) => { - setAccount(event.target.value); + setAccountNumber(event.target.value); }; - const enrollAccount = () => { - console.log('bank', bank, 'account', account); + const getChangedField = () => { + const changedField: Partial<Event> = {}; + + if (bankName.trim() !== '' && bankName !== bankNameState) { + changedField.bankName = bankNameState; + } + + if (accountNumber.trim() !== '' && accountNumber !== accountNumberState) { + changedField.accountNumber = accountNumberState; + } + + return changedField; + }; + + const enrollAccount = async () => { + await patchEventOutline(getChangedField()); }; useEffect(() => { - setCanSubmit(bank !== '' && account !== ''); - }, [bank, account]); + const existEmptyField = bankName.trim() === '' && accountNumber.trim() === ''; + const isChanged = bankName !== bankNameState || accountNumber !== accountNumberState; + + setCanSubmit(!existEmptyField && isChanged); + }, [bankName, accountNumber, bankNameState, accountNumberState]); return { - bank, - account, + bankName: bankNameState, + accountNumber: accountNumberState, canSubmit, selectBank, handleAccount, diff --git a/client/src/hooks/useEventPageLayout.ts b/client/src/hooks/useEventPageLayout.ts index 227ef402d..4322d5c4c 100644 --- a/client/src/hooks/useEventPageLayout.ts +++ b/client/src/hooks/useEventPageLayout.ts @@ -1,5 +1,7 @@ import {useMatch} from 'react-router-dom'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + import {ROUTER_URLS} from '@constants/routerUrls'; import useNavSwitch from './useNavSwitch'; @@ -7,16 +9,24 @@ import useRequestGetEvent from './queries/event/useRequestGetEvent'; const useEventPageLayout = () => { const navProps = useNavSwitch(); - const {eventName} = useRequestGetEvent(); + const eventId = getEventIdByUrl(); + const {eventName, bankName, accountNumber} = useRequestGetEvent(); const isAdmin = useMatch(ROUTER_URLS.eventManage) !== null; const isLoginPage = useMatch(ROUTER_URLS.eventLogin) !== null; + const eventOutline = { + eventName, + bankName, + accountNumber, + }; + return { + eventId, navProps, isAdmin, - eventName, isLoginPage, + eventOutline, }; }; diff --git a/client/src/hooks/useReportsPage.ts b/client/src/hooks/useReportsPage.ts new file mode 100644 index 000000000..0690f7895 --- /dev/null +++ b/client/src/hooks/useReportsPage.ts @@ -0,0 +1,55 @@ +import {useState} from 'react'; +import {useOutletContext} from 'react-router-dom'; + +import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; + +import {ERROR_MESSAGE} from '@constants/errorMessage'; + +import {useSearchReports} from './useSearchReports'; +import {useToast} from './useToast/useToast'; + +const useReportsPage = () => { + const {showToast} = useToast(); + + const [name, setName] = useState(''); + const {bankName, accountNumber} = useOutletContext<EventPageContextProps>(); + const {matchedReports, reports} = useSearchReports({name}); + + const changeName = ({target}: React.ChangeEvent<HTMLInputElement>) => { + setName(target.value); + }; + + const onBankButtonClick = () => { + if (bankName.trim() === '' || accountNumber.trim() === '') { + showToast({ + showingTime: 3000, + message: ERROR_MESSAGE.emptyBank, + type: 'error', + position: 'bottom', + bottom: '8rem', + }); + return; + } + + const url = 'supertoss://'; + window.location.href = url; + }; + + const expenseListProp = matchedReports.map(member => ({ + ...member, + clipboardText: `${bankName} ${accountNumber} ${member.price}원`, + onBankButtonClick, + })); + + const isEmpty = reports.length <= 0; + + return { + isEmpty, + matchedReports, + expenseListProp, + name, + changeName, + }; +}; + +export default useReportsPage; diff --git a/client/src/hooks/useShareEvent.ts b/client/src/hooks/useShareEvent.ts index 4a6ae1923..86d185f48 100644 --- a/client/src/hooks/useShareEvent.ts +++ b/client/src/hooks/useShareEvent.ts @@ -1,11 +1,7 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import getEventPageUrlByEnvironment from '@utils/getEventPageUrlByEnvironment'; -import useRequestGetEvent from './queries/event/useRequestGetEvent'; - -const useShareEvent = (isMobile: boolean) => { - const {eventName} = useRequestGetEvent(); - +const useShareEvent = (eventName: string, isMobile: boolean) => { const eventId = getEventIdByUrl(); const url = getEventPageUrlByEnvironment(eventId, 'home'); diff --git a/client/src/mocks/handlers/eventHandlers.ts b/client/src/mocks/handlers/eventHandlers.ts index 23fefaa47..1b06c5f9d 100644 --- a/client/src/mocks/handlers/eventHandlers.ts +++ b/client/src/mocks/handlers/eventHandlers.ts @@ -2,7 +2,7 @@ import type {EventId} from 'types/serviceType'; import {http, HttpResponse} from 'msw'; -import {USER_API_PREFIX} from '@apis/endpointPrefix'; +import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; @@ -50,9 +50,9 @@ export const eventHandler = [ return HttpResponse.json(eventData); }), - // PUT /api/events/:eventId (requestPutEvent) - http.put<any, {eventName?: string; bankName?: string; accountNumber?: string}>( - `${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId`, + // PATCH /api/admin/events/:eventId (requestPatchEvent) + http.patch<any, {eventName?: string; bankName?: string; accountNumber?: string}>( + `${MOCK_API_PREFIX}${ADMIN_API_PREFIX}/:eventId`, async ({request}) => { const updates = await request.json(); diff --git a/client/src/mocks/sharedState.ts b/client/src/mocks/sharedState.ts index d35b7926a..444e3c4dc 100644 --- a/client/src/mocks/sharedState.ts +++ b/client/src/mocks/sharedState.ts @@ -1,7 +1,7 @@ export let eventData = { - eventName: 'MSW 야유회', + eventName: '행동대장 야유회', bankName: '', - accountNumber: '', + accountNumber: '000000-01-121212', }; export let memberData = { diff --git a/client/src/pages/Account/Account.tsx b/client/src/pages/Account/Account.tsx deleted file mode 100644 index d3d45e410..000000000 --- a/client/src/pages/Account/Account.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import {useState} from 'react'; - -import BankSelectModal from '@components/Modal/BankSelectModal/BankSelectModal'; - -import useAccount from '@hooks/useAccount'; - -import {Back, Button, LabelInput, MainLayout, Title, TopNav} from '@components/Design'; - -const Account = () => { - const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); - const {bank, account, canSubmit, selectBank, handleAccount, enrollAccount} = useAccount(); - - return ( - <MainLayout backgroundColor="white"> - <TopNav> - <Back /> - </TopNav> - {/* <Title title="계좌번호" description="행사에 사용한 계좌번호를 입력해주세요." /> */} - <fieldset> - <LabelInput - labelText="은행" - placeholder="은행을 선택해주세요" - value={bank} - errorText={null} - autoFocus={false} - readOnly - onClick={() => setIsBottomSheetOpen(true)} - /> - <LabelInput - labelText="계좌번호" - placeholder="030302-04-191806" - errorText={null} - value={account} - onChange={handleAccount} - autoFocus={false} - /> - {isBottomSheetOpen && ( - <BankSelectModal - isBottomSheetOpened={isBottomSheetOpen} - setIsBottomSheetOpened={setIsBottomSheetOpen} - selectBank={selectBank} - /> - )} - </fieldset> - <Button disabled={!canSubmit} onClick={enrollAccount}> - 확인 - </Button> - </MainLayout> - ); -}; - -export default Account; diff --git a/client/src/pages/AccountPage/Account.tsx b/client/src/pages/AccountPage/Account.tsx new file mode 100644 index 000000000..1b7d685ff --- /dev/null +++ b/client/src/pages/AccountPage/Account.tsx @@ -0,0 +1,73 @@ +import {useState} from 'react'; +import {useLocation, useNavigate} from 'react-router-dom'; + +import BankSelectModal from '@components/Modal/BankSelectModal/BankSelectModal'; + +import useAccount from '@hooks/useAccount'; + +import {Back, FixedButton, Flex, FunnelLayout, LabelInput, MainLayout, Top, TopNav} from '@components/Design'; + +import getDeletedLastPath from '@utils/getDeletedLastPath'; + +const Account = () => { + const navigate = useNavigate(); + const location = useLocation(); + + const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); + + const {bankName, accountNumber, canSubmit, selectBank, handleAccount, enrollAccount} = useAccount(); + + const enrollAccountAndNavigateAdmin = async () => { + await enrollAccount(); + navigate(getDeletedLastPath(location.pathname)); + }; + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + <FunnelLayout> + <Top> + <Top.Line text="행사 정산 금액은" /> + <Top.Line text="어떤 계좌로 받을까요?" emphasize={['어떤 계좌']} /> + </Top> + <Flex flexDirection="column" gap="1rem"> + <LabelInput + labelText="은행" + placeholder="은행을 선택해주세요" + value={bankName ?? ''} + errorText={null} + autoFocus={false} + isAlwaysOnLabel + isAlwaysOnInputBorder + readOnly + onClick={() => setIsBottomSheetOpen(true)} + /> + <LabelInput + labelText="계좌번호" + placeholder="030302-04-191806" + errorText={null} + value={accountNumber ?? ''} + onChange={handleAccount} + autoFocus={false} + isAlwaysOnLabel + isAlwaysOnInputBorder + /> + {isBottomSheetOpen && ( + <BankSelectModal + isBottomSheetOpened={isBottomSheetOpen} + setIsBottomSheetOpened={setIsBottomSheetOpen} + selectBank={selectBank} + /> + )} + </Flex> + </FunnelLayout> + <FixedButton disabled={!canSubmit} onClick={enrollAccountAndNavigateAdmin} onBackClick={() => navigate(-1)}> + 확인 + </FixedButton> + </MainLayout> + ); +}; + +export default Account; diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 1f33cdc01..3e33fedde 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -1,3 +1,5 @@ +import type {Event} from 'types/serviceType'; + import {Outlet} from 'react-router-dom'; import useEventPageLayout from '@hooks/useEventPageLayout'; @@ -6,25 +8,24 @@ import {ShareEventButton} from '@components/ShareEventButton'; import {MainLayout, TopNav, Switch} from '@HDesign/index'; -export type EventPageContextProps = { +export type EventPageContextProps = Event & { isAdmin: boolean; - eventName: string; }; const EventPageLayout = () => { - const {navProps, isAdmin, isLoginPage, eventName} = useEventPageLayout(); + const {navProps, isAdmin, isLoginPage, eventOutline} = useEventPageLayout(); const {nav, paths, onChange} = navProps; const outletContext: EventPageContextProps = { isAdmin, - eventName, + ...eventOutline, }; return ( <MainLayout backgroundColor="gray"> <TopNav> <Switch value={nav} values={paths} onChange={onChange} /> - {!isLoginPage && <ShareEventButton />} + {!isLoginPage && <ShareEventButton eventOutline={eventOutline} />} </TopNav> <Outlet context={outletContext} /> </MainLayout> diff --git a/client/src/router.tsx b/client/src/router.tsx index e1592bd2e..01dc4d53e 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -4,7 +4,7 @@ import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; -import Account from '@pages/Account/Account'; +import Account from '@pages/AccountPage/Account'; import AddBillFunnel from '@pages/BillPage/AddBillFunnel'; import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; @@ -57,6 +57,10 @@ const router = createBrowserRouter([ path: ROUTER_URLS.addBill, element: <AddBillFunnel />, }, + { + path: ROUTER_URLS.eventEdit, + element: <Account />, + }, { path: '*', element: <ErrorPage />, diff --git a/client/src/utils/getDeletedLastPath.ts b/client/src/utils/getDeletedLastPath.ts new file mode 100644 index 000000000..f2edfb154 --- /dev/null +++ b/client/src/utils/getDeletedLastPath.ts @@ -0,0 +1,7 @@ +const getDeletedLastPath = (url: string) => { + const urlParts = url.split('/'); + urlParts.pop(); + return urlParts.join('/'); +}; + +export default getDeletedLastPath; From e419eb291be55f23d92d264e09ab4f01646d84ba Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:13:28 +0900 Subject: [PATCH 238/273] =?UTF-8?q?feat:=20=ED=86=A0=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=84=B1=20=EA=B0=9C=EC=84=A0=20(#579)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 컨벤션에 맞도록 공백 추가 * feat: 토스트 컴포넌트와 훅에서 공용으로 사용하는 타입을 분리 * feat: 전역 상태로 관리할 필요가 없어졌으므로 ToastProvider -> useToast로 내용물 이전 * fix: 토스트 컴포넌트에 isAutoClosed 가 false면 계속 떠있도록 수정 * refactor: 공용 토스트 타입을 재사용하도록 수정 * feat: 콜백을 등록해두고, 토스트 이벤트 발생 시 등록되어있는 콜백 함수르 실행하는 객체 구현 * feat: 토스트를 간편하게 사용할 수 있도록 인터페이스 역할을 하는 toast 함수 구현 * feat: 토스트를 띄우기 위한 컨테이너 구현 * feat: 토스트 콜백 함수를 다루는 객체에서 사용하는 타입 분리 * test: 변경된 토스트에 맞게 테스트 코드 수정 * feat: 토스트를 띄우기 위해 App에 ToastContainer 호출 * test: ToastProvider -> ToastContainer로 수정 * feat: 토스트를 호출하는 곳을 바뀐 토스트 호출 형식으로 수정 * style: 이벤트의 콜백 목록을 저장한다는 의미가 드러나도록 eventList -> eventCallbackList로 변수명 수정 * chore: 테스트를 위해 작성한 코드 제거 * feat: 기존 토스트 방식에서 개선된 토스트방식으로 수정 --- client/src/App.tsx | 23 ++++----- .../AppErrorBoundary/ErrorCatcher.test.tsx | 11 ++-- .../AppErrorBoundary/ErrorCatcher.tsx | 9 +--- .../Design/components/Title/Title.tsx | 1 - .../ShareEventButton/ShareEventButton.tsx | 14 ++--- client/src/components/Toast/Toast.style.ts | 10 +--- client/src/components/Toast/Toast.tsx | 29 ++++++----- client/src/components/Toast/Toast.type.ts | 25 ++++----- .../src/components/Toast/ToastContainer.tsx | 11 ++++ client/src/hooks/useReportsPage.ts | 9 +--- client/src/hooks/useToast/ToastProvider.tsx | 48 ----------------- client/src/hooks/useToast/toast.ts | 19 +++++++ .../src/hooks/useToast/toastEventManager.ts | 24 +++++++++ .../hooks/useToast/toastEventManager.type.ts | 21 ++++++++ client/src/hooks/useToast/useToast.test.tsx | 33 +++++------- client/src/hooks/useToast/useToast.tsx | 51 ++++++++++++++++--- .../CreateEventPage/SetEventNamePage.tsx | 3 +- .../CreateEventPage/SetEventPasswordPage.tsx | 3 +- .../pages/MainPage/Section/MainSection.tsx | 1 + client/src/types/toastType.ts | 17 +++++++ client/src/utils/NetworkStateCatcher.tsx | 11 ++-- 21 files changed, 207 insertions(+), 166 deletions(-) create mode 100644 client/src/components/Toast/ToastContainer.tsx delete mode 100644 client/src/hooks/useToast/ToastProvider.tsx create mode 100644 client/src/hooks/useToast/toast.ts create mode 100644 client/src/hooks/useToast/toastEventManager.ts create mode 100644 client/src/hooks/useToast/toastEventManager.type.ts create mode 100644 client/src/types/toastType.ts diff --git a/client/src/App.tsx b/client/src/App.tsx index 7e86b12b7..33ea71b6c 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -2,9 +2,9 @@ import {Outlet} from 'react-router-dom'; import {Global} from '@emotion/react'; import {ReactQueryDevtools} from '@tanstack/react-query-devtools'; -import {ToastProvider} from '@hooks/useToast/ToastProvider'; import QueryClientBoundary from '@components/QueryClientBoundary/QueryClientBoundary'; import ErrorCatcher from '@components/AppErrorBoundary/ErrorCatcher'; +import ToastContainer from '@components/Toast/ToastContainer'; import KakaoInitializer from '@components/KakaoInitializer/KakaoInitializer'; import {HDesignProvider} from '@HDesign/index'; @@ -19,17 +19,16 @@ const App: React.FC = () => { <HDesignProvider> <UnPredictableErrorBoundary> <Global styles={GlobalStyle} /> - <ToastProvider> - <ErrorCatcher> - <QueryClientBoundary> - <ReactQueryDevtools initialIsOpen={false} /> - <NetworkStateCatcher /> - <KakaoInitializer> - <Outlet /> - </KakaoInitializer> - </QueryClientBoundary> - </ErrorCatcher> - </ToastProvider> + <ErrorCatcher> + <QueryClientBoundary> + <ReactQueryDevtools initialIsOpen={false} /> + <NetworkStateCatcher /> + <ToastContainer /> + <KakaoInitializer> + <Outlet /> + </KakaoInitializer> + </QueryClientBoundary> + </ErrorCatcher> </UnPredictableErrorBoundary> </HDesignProvider> ); diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx index 9367e65dd..f263e18fb 100644 --- a/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.test.tsx @@ -2,8 +2,8 @@ import {render, screen, waitFor} from '@testing-library/react'; import {act, ReactNode} from 'react'; import {MemoryRouter} from 'react-router-dom'; +import ToastContainer from '@components/Toast/ToastContainer'; import RequestError from '@errors/RequestError'; -import {ToastProvider} from '@hooks/useToast/ToastProvider'; import {useAppErrorStore} from '@store/appErrorStore'; @@ -24,11 +24,10 @@ const setup = (ui: ReactNode) => render( <HDesignProvider> <UnPredictableErrorBoundary> - <ToastProvider> - <ErrorCatcher> - <MemoryRouter>{ui}</MemoryRouter> - </ErrorCatcher> - </ToastProvider> + <ToastContainer /> + <ErrorCatcher> + <MemoryRouter>{ui}</MemoryRouter> + </ErrorCatcher> </UnPredictableErrorBoundary> </HDesignProvider>, ); diff --git a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx index 9e9e2f484..9cb179602 100644 --- a/client/src/components/AppErrorBoundary/ErrorCatcher.tsx +++ b/client/src/components/AppErrorBoundary/ErrorCatcher.tsx @@ -1,6 +1,6 @@ import {useEffect} from 'react'; -import {useToast} from '@hooks/useToast/useToast'; +import toast from '@hooks/useToast/toast'; import {useAppErrorStore} from '@store/appErrorStore'; @@ -17,21 +17,16 @@ const isPredictableError = (error: Error) => { const ErrorCatcher = ({children}: React.PropsWithChildren) => { const {appError: error} = useAppErrorStore(); - const {showToast} = useToast(); useEffect(() => { if (!error) return; captureError(error); - console.log(isRequestError(error)); - console.log(isPredictableError(error)); if (!isRequestError(error) || !isPredictableError(error)) throw error; - showToast({ + toast.error(SERVER_ERROR_MESSAGES[error.errorCode], { showingTime: 3000, - message: SERVER_ERROR_MESSAGES[error.errorCode], - type: 'error', position: 'bottom', bottom: '8rem', }); diff --git a/client/src/components/Design/components/Title/Title.tsx b/client/src/components/Design/components/Title/Title.tsx index 1c28c3325..ac33cfb49 100644 --- a/client/src/components/Design/components/Title/Title.tsx +++ b/client/src/components/Design/components/Title/Title.tsx @@ -1,5 +1,4 @@ /** @jsxImportSource @emotion/react */ -import Flex from '@HDcomponents/Flex/Flex'; import Text from '@HDcomponents/Text/Text'; import {amountContainerStyle, titleContainerStyle, titleStyle} from '@HDcomponents/Title/Title.style'; import {TitleProps} from '@HDcomponents/Title/Title.type'; diff --git a/client/src/components/ShareEventButton/ShareEventButton.tsx b/client/src/components/ShareEventButton/ShareEventButton.tsx index 765bc11cc..df8e659f8 100644 --- a/client/src/components/ShareEventButton/ShareEventButton.tsx +++ b/client/src/components/ShareEventButton/ShareEventButton.tsx @@ -1,7 +1,7 @@ import CopyToClipboard from 'react-copy-to-clipboard'; import {useNavigate} from 'react-router-dom'; -import {useToast} from '@hooks/useToast/useToast'; +import toast from '@hooks/useToast/toast'; import {Event} from 'types/serviceType'; import useShareEvent from '@hooks/useShareEvent'; @@ -19,19 +19,14 @@ const ShareEventButton = ({eventOutline}: ShareEventButtonProps) => { const {eventName, bankName, accountNumber} = eventOutline; const navigate = useNavigate(); - const {showToast} = useToast(); - const isMobile = isMobileDevice(); const {shareText, onShareButtonClick} = useShareEvent(eventName, isMobile); const induceBankInfoBeforeShare = () => { if (bankName === '' || accountNumber === '') { - showToast({ + toast.confirm('잠깐! 정산을 초대하기 전에\n계좌를 등록해주세요', { showingTime: 3000, - message: '잠깐! 정산을 초대하기 전에\n계좌를 등록해주세요.', - type: 'error', position: 'bottom', - bottom: '8rem', }); const navigatePath = `${getDeletedLastPath(location.pathname)}/admin/edit`; @@ -51,12 +46,9 @@ const ShareEventButton = ({eventOutline}: ShareEventButtonProps) => { <CopyToClipboard text={shareText} onCopy={() => - showToast({ + toast.confirm('링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', { showingTime: 3000, - message: '링크가 복사되었어요 :) \n참여자들에게 링크를 공유해 주세요!', - type: 'confirm', position: 'bottom', - bottom: '8rem', }) } > diff --git a/client/src/components/Toast/Toast.style.ts b/client/src/components/Toast/Toast.style.ts index a0b5c7cd4..510a2275c 100644 --- a/client/src/components/Toast/Toast.style.ts +++ b/client/src/components/Toast/Toast.style.ts @@ -1,12 +1,6 @@ import {css, keyframes} from '@emotion/react'; -import {ToastPosition} from './Toast.type'; - -type ToastMarginStyle = { - position?: ToastPosition; - bottom?: string; - top?: string; -}; +import {ToastOptions} from 'types/toastType'; // 애니메이션 키프레임 정의 const fadeInWithTransformY = keyframes` @@ -31,7 +25,7 @@ const fadeOutWithTransformY = keyframes` } `; -export const toastMarginStyle = ({position, bottom, top}: ToastMarginStyle) => +export const toastMarginStyle = ({position, bottom, top}: ToastOptions) => css({ position: 'absolute', bottom: position === 'bottom' ? `${bottom}` : 'auto', diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx index d688d1395..0081f3978 100644 --- a/client/src/components/Toast/Toast.tsx +++ b/client/src/components/Toast/Toast.tsx @@ -17,8 +17,9 @@ const ANIMATION_TIME = 500; const Toast = ({ type = 'confirm', top = '0px', - bottom = '0px', - isClickToClose = true, + bottom = '6rem', + isCloseOnClick = true, + isAutoClosed = true, position = 'bottom', showingTime = 3000, message, @@ -29,7 +30,16 @@ const Toast = ({ const [isVisible, setIsVisible] = useState(true); const styleProps = {position, top, bottom}; - useEffect(() => { + const handleClickToClose = () => { + if (!isCloseOnClick || !onClose) return; + + setIsVisible(false); + setTimeout(() => { + onClose(); + }, ANIMATION_TIME); // fadeOut 애니메이션 시간과 동일하게 설정 + }; + + const handleAutoClose = () => { const timer = setTimeout(() => { setIsVisible(false); setTimeout(() => { @@ -40,17 +50,12 @@ const Toast = ({ return () => { clearTimeout(timer); }; - }, [onClose]); - - const handleClickToClose = () => { - if (!isClickToClose || !onClose) return; - - setIsVisible(false); - setTimeout(() => { - onClose(); - }, ANIMATION_TIME); // fadeOut 애니메이션 시간과 동일하게 설정 }; + useEffect(() => { + if (isAutoClosed) handleAutoClose(); + }, []); + return createPortal( <div css={toastMarginStyle({...styleProps})} {...htmlProps} onClick={handleClickToClose} id="toast"> <div css={toastStyle(isVisible)}> diff --git a/client/src/components/Toast/Toast.type.ts b/client/src/components/Toast/Toast.type.ts index 20b92c0db..a1ff70c40 100644 --- a/client/src/components/Toast/Toast.type.ts +++ b/client/src/components/Toast/Toast.type.ts @@ -1,22 +1,15 @@ -export type ToastPosition = 'bottom' | 'top'; -export type ToastType = 'error' | 'confirm' | 'none'; +import {ToastMessage, ToastOptions} from 'types/toastType'; -export interface ToastStyleProps { - bottom?: string; - top?: string; -} +export type ToastType = 'error' | 'confirm' | 'none'; -export interface ToastOptionProps { - position?: ToastPosition; +export type ToastOptionProps = ToastOptions & { type?: ToastType; - onUndo?: () => void; - isClickToClose?: boolean; onClose?: () => void; - showingTime?: number; -} + onUndo?: () => void; +}; -export interface ToastRequiredProps { - message: string; -} +export type ToastRequiredProps = { + message: ToastMessage; +}; -export type ToastProps = React.ComponentProps<'div'> & ToastStyleProps & ToastOptionProps & ToastRequiredProps; +export type ToastProps = React.ComponentProps<'div'> & ToastOptionProps & ToastRequiredProps; diff --git a/client/src/components/Toast/ToastContainer.tsx b/client/src/components/Toast/ToastContainer.tsx new file mode 100644 index 000000000..40439f9b6 --- /dev/null +++ b/client/src/components/Toast/ToastContainer.tsx @@ -0,0 +1,11 @@ +import {useToast} from '@hooks/useToast/useToast'; + +import Toast from './Toast'; + +const ToastContainer = () => { + const {currentToast, closeToast} = useToast(); + + return <>{currentToast && <Toast onClose={closeToast} {...currentToast.options} message={currentToast.message} />}</>; +}; + +export default ToastContainer; diff --git a/client/src/hooks/useReportsPage.ts b/client/src/hooks/useReportsPage.ts index 0690f7895..9b7555b2f 100644 --- a/client/src/hooks/useReportsPage.ts +++ b/client/src/hooks/useReportsPage.ts @@ -6,11 +6,9 @@ import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; import {ERROR_MESSAGE} from '@constants/errorMessage'; import {useSearchReports} from './useSearchReports'; -import {useToast} from './useToast/useToast'; +import toast from './useToast/toast'; const useReportsPage = () => { - const {showToast} = useToast(); - const [name, setName] = useState(''); const {bankName, accountNumber} = useOutletContext<EventPageContextProps>(); const {matchedReports, reports} = useSearchReports({name}); @@ -21,12 +19,9 @@ const useReportsPage = () => { const onBankButtonClick = () => { if (bankName.trim() === '' || accountNumber.trim() === '') { - showToast({ + toast.error(ERROR_MESSAGE.emptyBank, { showingTime: 3000, - message: ERROR_MESSAGE.emptyBank, - type: 'error', position: 'bottom', - bottom: '8rem', }); return; } diff --git a/client/src/hooks/useToast/ToastProvider.tsx b/client/src/hooks/useToast/ToastProvider.tsx deleted file mode 100644 index 60f16f186..000000000 --- a/client/src/hooks/useToast/ToastProvider.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {createContext, useEffect, useState} from 'react'; - -import {ToastProps} from '../../components/Toast/Toast.type'; -import Toast from '../../components/Toast/Toast'; - -export const ToastContext = createContext<ToastContextProps | null>(null); - -const DEFAULT_TIME = 3000; - -interface ToastContextProps { - showToast: (args: ShowToast) => void; - closeToast: () => void; -} - -type ShowToast = ToastProps & { - showingTime?: number; - isAlwaysOn?: boolean; -}; - -export const ToastProvider = ({children}: React.PropsWithChildren) => { - const [currentToast, setCurrentToast] = useState<ShowToast | null>(null); - - const showToast = ({showingTime = DEFAULT_TIME, isAlwaysOn = false, ...toastProps}: ShowToast) => { - setCurrentToast({showingTime, isAlwaysOn, ...toastProps}); - }; - - const closeToast = () => { - setCurrentToast(null); - }; - - useEffect(() => { - if (currentToast && !currentToast.isAlwaysOn) { - const timer = setTimeout(() => setCurrentToast(null), currentToast.showingTime); - - return () => clearTimeout(timer); - } - - return; - }, [currentToast]); - - return ( - <ToastContext.Provider value={{showToast, closeToast}}> - {currentToast && <Toast onClose={closeToast} {...currentToast} />} - {children} - </ToastContext.Provider> - ); -}; diff --git a/client/src/hooks/useToast/toast.ts b/client/src/hooks/useToast/toast.ts new file mode 100644 index 000000000..362227a62 --- /dev/null +++ b/client/src/hooks/useToast/toast.ts @@ -0,0 +1,19 @@ +import {ToastMessage, ToastOptions} from 'types/toastType'; + +import toastEventManager from './toastEventManager'; +import {TOAST_EVENT} from './toastEventManager.type'; + +const showToast = (message: ToastMessage, options: ToastOptions) => { + return toastEventManager.trigger(TOAST_EVENT.show, message, options); +}; + +// toast('안녕') 처럼도 사용할 수 있도록 +const toast = (message: ToastMessage, options: ToastOptions = {}) => { + return showToast(message, options); +}; + +toast.error = (message: ToastMessage, options: ToastOptions = {}) => showToast(message, options); +toast.confirm = (message: ToastMessage, options: ToastOptions = {}) => showToast(message, options); +toast.none = (message: ToastMessage, options: ToastOptions = {}) => showToast(message, options); + +export default toast; diff --git a/client/src/hooks/useToast/toastEventManager.ts b/client/src/hooks/useToast/toastEventManager.ts new file mode 100644 index 000000000..fc70d5af3 --- /dev/null +++ b/client/src/hooks/useToast/toastEventManager.ts @@ -0,0 +1,24 @@ +import {AddEventHandlerArgs, ToastEventCallbackMap} from './toastEventManager.type'; + +const toastEventManager = (() => { + const eventCallbackList = new Map(); + + return { + // eventType은 ToastEventCallbackMap 중 하나의 값을 받고 이 값에 따라 callback타입이 결정됩니다. + // 모티브는 addEventListener으로.. listener 인자에 적용되는 타입 narrowing방법을 흉내낸 것입니다. + addEventHandler<K extends keyof ToastEventCallbackMap>({eventType, callback}: AddEventHandlerArgs<K>) { + eventCallbackList.set(eventType, callback); + }, + + trigger<K extends keyof ToastEventCallbackMap>(eventType: K, ...args: any) { + if (!eventCallbackList.has(eventType)) { + throw new Error(`토스트 이벤트 핸들러에 등록된 ${eventType} 이벤트가 없습니다. 이벤트 등록 후 호출해주세요.`); + } + + const callback = eventCallbackList.get(eventType); + callback(...args); + }, + }; +})(); + +export default toastEventManager; diff --git a/client/src/hooks/useToast/toastEventManager.type.ts b/client/src/hooks/useToast/toastEventManager.type.ts new file mode 100644 index 000000000..0d7603983 --- /dev/null +++ b/client/src/hooks/useToast/toastEventManager.type.ts @@ -0,0 +1,21 @@ +import {ToastMessage, ToastOptions} from 'types/toastType'; + +const TOAST_SHOW = 'TOAST_SHOW' as const; +const TOAST_CLOSE = 'TOAST_CLOSE' as const; + +export const TOAST_EVENT = { + show: TOAST_SHOW, + close: TOAST_CLOSE, +}; + +export type ToastEventType = typeof TOAST_SHOW | typeof TOAST_CLOSE; + +export type ToastEventCallbackMap = { + [TOAST_SHOW]: (message: ToastMessage, options: ToastOptions) => void; + [TOAST_CLOSE]: () => void; +}; + +export type AddEventHandlerArgs<K extends keyof ToastEventCallbackMap> = { + eventType: K; + callback: ToastEventCallbackMap[K]; +}; diff --git a/client/src/hooks/useToast/useToast.test.tsx b/client/src/hooks/useToast/useToast.test.tsx index 80fa7d7ab..e8c1bdd3d 100644 --- a/client/src/hooks/useToast/useToast.test.tsx +++ b/client/src/hooks/useToast/useToast.test.tsx @@ -1,21 +1,19 @@ import {render, renderHook, screen, waitFor} from '@testing-library/react'; import {act} from 'react'; +import ToastContainer from '@components/Toast/ToastContainer'; + import {HDesignProvider} from '@HDesign/index'; -import {ToastProvider} from './ToastProvider'; // 위 코드에 해당하는 ToastProvider 경로 import {useToast} from './useToast'; +import toast from './toast'; -const TOAST_CONFIG = { - message: 'Test Toast Message', -}; +const TOAST_MESSAGE = '테스트 메세지에요.'; // 테스트용 헬퍼 컴포넌트 const TestComponent = () => { - const {showToast} = useToast(); - const handleClick = () => { - showToast(TOAST_CONFIG); + toast(TOAST_MESSAGE); }; return <button onClick={handleClick}>Show Toast</button>; @@ -24,9 +22,8 @@ const TestComponent = () => { const setup = () => render( <HDesignProvider> - <ToastProvider> - <TestComponent /> - </ToastProvider> + <ToastContainer /> + <TestComponent /> </HDesignProvider>, ); @@ -40,18 +37,18 @@ describe('ToastProvider', () => { }); // 토스트 메시지가 나타나는지 확인 - expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + expect(screen.getByText(TOAST_MESSAGE)).toBeInTheDocument(); // 1초 후에 토스트 메시지가 사라지는지 확인 await waitFor( () => { - expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + expect(screen.queryByText(TOAST_MESSAGE)).not.toBeInTheDocument(); }, {timeout: 3100}, ); // 타임아웃을 3100ms로 설정하여 정확히 3초 후 확인 }); - it('토스트 닫기 버튼을 눌렀을 때 사라진다', async () => { + it('토스트를 누르면 사라진다', async () => { setup(); // 토스트를 띄우기 위해 버튼 클릭 @@ -60,7 +57,7 @@ describe('ToastProvider', () => { }); // 토스트 메시지가 나타나는지 확인 - expect(screen.getByText(TOAST_CONFIG.message)).toBeInTheDocument(); + expect(screen.getByText(TOAST_MESSAGE)).toBeInTheDocument(); // 토스트의 닫기 버튼을 클릭 act(() => { @@ -69,13 +66,7 @@ describe('ToastProvider', () => { // 닫기 버튼을 클릭한 후 토스트가 사라지는지 확인 await waitFor(() => { - expect(screen.queryByText(TOAST_CONFIG.message)).not.toBeInTheDocument(); + expect(screen.queryByText(TOAST_MESSAGE)).not.toBeInTheDocument(); }); }); - - it('Provider없이 useToast 사용할 경우 에러를 던진다.', () => { - expect(() => { - const _ = renderHook(() => useToast()); - }).toThrow('useToast는 ToastProvider 내에서 사용되어야 합니다.'); - }); }); diff --git a/client/src/hooks/useToast/useToast.tsx b/client/src/hooks/useToast/useToast.tsx index 189847405..e47d99c50 100644 --- a/client/src/hooks/useToast/useToast.tsx +++ b/client/src/hooks/useToast/useToast.tsx @@ -1,13 +1,50 @@ -import {useContext} from 'react'; +/** @jsxImportSource @emotion/react */ +import {useEffect, useState} from 'react'; -import {ToastContext} from './ToastProvider'; +import {ToastMessage, ToastOptions, ToastArgs} from 'types/toastType'; + +import toastEventManager from './toastEventManager'; +import {TOAST_EVENT} from './toastEventManager.type'; + +const DEFAULT_TIME = 3000; + +type Toast = { + message: ToastMessage; + options: ToastOptions; +}; export const useToast = () => { - const context = useContext(ToastContext); + const [currentToast, setCurrentToast] = useState<ToastArgs | null>(null); + + const showToast = (message: ToastMessage, options: ToastOptions) => { + setCurrentToast({message, options}); + }; + + const closeToast = () => { + setCurrentToast(null); + }; + + const setAutoCloseTimer = () => { + if (!currentToast) return; + + const showingTime = currentToast.options.showingTime || DEFAULT_TIME; + const timer = setTimeout(() => setCurrentToast(null), showingTime); + + return () => clearTimeout(timer); + }; + + useEffect(() => { + if (currentToast?.options.isAutoClosed) setAutoCloseTimer(); + + return; + }, [currentToast]); - if (!context) { - throw new Error('useToast는 ToastProvider 내에서 사용되어야 합니다.'); - } + useEffect(() => { + toastEventManager.addEventHandler({eventType: TOAST_EVENT.show, callback: showToast}); + }, []); - return context; + return { + currentToast, + closeToast, + }; }; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx index f9fc9f3f5..1f7d0acf6 100644 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ b/client/src/pages/CreateEventPage/SetEventNamePage.tsx @@ -5,7 +5,7 @@ import Top from '@components/Design/components/Top/Top'; import useSetEventNamePage from '@hooks/useSetEventNamePage'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back, Flex} from '@HDesign/index'; +import {FixedButton, MainLayout, LabelInput, TopNav, Back} from '@HDesign/index'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -46,6 +46,7 @@ const SetEventNamePage = () => { <Top.Line text="정산을 시작하려는" /> <Top.Line text="행사의 이름은 무엇인가요?" emphasize={['행사의 이름']} /> </Top> + <form onSubmit={submitEventName}> <LabelInput labelText="행사 이름" diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx index 914f0a25b..4c0b70ad2 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx @@ -4,10 +4,9 @@ import Top from '@components/Design/components/Top/Top'; import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; -import {FixedButton, MainLayout, LabelInput, Title, TopNav, Back} from '@HDesign/index'; +import {FixedButton, MainLayout, LabelInput, TopNav, Back} from '@HDesign/index'; import RULE from '@constants/rule'; -import {PASSWORD_LENGTH} from '@constants/password'; const SetEventPasswordPage = () => { const {submitPassword, onSuccess, errorMessage, password, handleChange, canSubmit, isPostEventPending} = diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx index 16bc67128..18f8e9208 100644 --- a/client/src/pages/MainPage/Section/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -10,6 +10,7 @@ import {ROUTER_URLS} from '@constants/routerUrls'; const MainSection = () => { const navigate = useNavigate(); + return ( <div css={css({ diff --git a/client/src/types/toastType.ts b/client/src/types/toastType.ts new file mode 100644 index 000000000..6b165f5ce --- /dev/null +++ b/client/src/types/toastType.ts @@ -0,0 +1,17 @@ +export type ToastPosition = 'bottom' | 'top'; + +export type ToastOptions = { + showingTime?: number; + isAutoClosed?: boolean; + isCloseOnClick?: boolean; + position?: ToastPosition; + bottom?: string; + top?: string; +}; + +export type ToastMessage = string; + +export type ToastArgs = { + message: ToastMessage; + options: ToastOptions; +}; diff --git a/client/src/utils/NetworkStateCatcher.tsx b/client/src/utils/NetworkStateCatcher.tsx index 8faadfee0..1a8158ec8 100644 --- a/client/src/utils/NetworkStateCatcher.tsx +++ b/client/src/utils/NetworkStateCatcher.tsx @@ -1,20 +1,17 @@ import {useEffect} from 'react'; import {useToast} from '@hooks/useToast/useToast'; +import toast from '@hooks/useToast/toast'; const NetworkStateCatcher = () => { - const {showToast, closeToast} = useToast(); - const handleNetworkOnline = () => { - closeToast(); + // closeToast(); }; const handleNetworkOffline = () => { // TODO: (@weadie) 토스트 높이는 z-index 이슈가 해결되면 반영할 예정입니다. - showToast({ - message: '네트워크 연결 상태를 확인해주세요.', - isAlwaysOn: true, - type: 'error', + toast.error('네트워크 연결 상태를 확인해주세요.', { + isAutoClosed: false, position: 'bottom', bottom: '6rem', }); From 396ff785aa1cd8bd6d61076006c0c7d7f0fc80ba Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:33:51 +0900 Subject: [PATCH 239/273] =?UTF-8?q?feat:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=99=88=20=ED=99=94=EB=A9=B4=20=EC=83=88=EB=A1=9C=EC=9A=B4=20?= =?UTF-8?q?=ED=94=8C=EB=A1=9C=EC=9A=B0=EB=A1=9C=20=EA=B5=90=EC=B2=B4=20(?= =?UTF-8?q?=EC=B0=B8=EC=97=AC=EC=9E=90=20=EB=B3=84=20=EC=A0=95=EC=82=B0,?= =?UTF-8?q?=20=EC=A0=84=EC=B2=B4=20=EC=A7=80=EC=B6=9C=20=EB=82=B4=EC=97=AD?= =?UTF-8?q?),=20Dropdown=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(#582)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: z index theme에 추가 * feat: 탭 컴포넌트 스타일 바뀐대로 설정 * design: gap 만큼 더 움직이도록 설정 * feat: ExpenseList안에 검색input 추가 * feat: Flex 컴포넌트에 다른 style 넣을 수 있도록 확장 * feat: inputType search일 때 검색 아이콘 보이도록 설정 * feat: 바뀐 이벤트 홈 디자인 반영 * remove: 사용하지 않는 Search 컴포넌트 삭제 * fix: Flex컴포넌트 다른 스타일 확장으로 인한 ts 오류 수정 * feat: ExpenseList isDeposited 내용 추가 * style: 사용하지 않는 import제거 * design: 버튼 색상 변경 * feat: 지출내역이 없을 때 fallback 추가 * feat: 지출 내역이 없을 때 fallback 적용 * feat: Dropdown 컴포넌트 구현 * fix: createPortal 제거 -> position absolute를 이용해 대체 * feat: AdminPage에 dropdown 컴포넌트 적용 * design: 모바일에서 클릭 시 파란색 강조되는 색 제거 * feat: 계좌번호 입력 드랍다운 눌렀을 때 페이지 이동 (머지되면 붙일 예정) * design: 탭 컴포넌트 애니메이션 cubic-bezier를 이용해서 변경 * design: 드랍다운 버튼 hover 강조 * fix: ResizeObserver를 이용해서 tab width의 값을 정확히 가져오도록 설정 * design: tab width가 0일 때 indicator가 랜더링 되지 않도록 설정 * chore: 충돌 병합 --- .../components/Dropdown/Dropdown.stories.tsx | 34 ++++++++++ .../components/Dropdown/Dropdown.style.ts | 33 ++++++++++ .../Design/components/Dropdown/Dropdown.tsx | 36 +++++++++++ .../components/Dropdown/Dropdown.type.ts | 7 +++ .../components/Dropdown/DropdownButton.tsx | 21 +++++++ .../Design/components/Dropdown/useDropdown.ts | 39 ++++++++++++ .../ExpenseList/ExpenseList.stories.tsx | 40 ++++++++++-- .../ExpenseList/ExpenseList.style.ts | 12 ---- .../components/ExpenseList/ExpenseList.tsx | 49 ++++++++++----- .../ExpenseList/ExpenseList.type.ts | 11 ++-- .../Design/components/Flex/Flex.style.ts | 2 - .../Design/components/Flex/Flex.tsx | 10 +-- .../Design/components/Flex/Flex.type.ts | 2 + .../Design/components/Input/Input.style.ts | 19 +----- .../Design/components/Input/Input.tsx | 9 ++- .../components/Search/Search.stories.tsx | 32 ---------- .../Design/components/Search/Search.style.ts | 42 ------------- .../Design/components/Search/Search.tsx | 36 ----------- .../Design/components/Tabs/Tabs.style.ts | 62 +++++++++++-------- .../Design/components/Tabs/Tabs.tsx | 48 +++++++++++--- .../Design/components/Title/Title.tsx | 5 +- .../Design/components/Title/Title.type.ts | 1 + client/src/components/Design/index.tsx | 6 +- .../Design/theme/HDesignProvider.tsx | 2 + .../src/components/Design/theme/theme.type.ts | 2 + client/src/components/Design/token/zIndex.ts | 8 +++ client/src/components/Reports/Reports.tsx | 25 +++----- .../ShareEventButton/ShareEventButton.tsx | 4 +- client/src/components/StepList/Steps.tsx | 22 +++---- client/src/hooks/useReportsPage.ts | 1 - .../pages/EventPage/AdminPage/AdminPage.tsx | 22 +++++-- .../BillEmptyFallback/index.tsx | 16 +++++ .../EventPageFallback/fallbackText.ts | 7 +++ .../EventPage/HomePage/HomePage.style.ts | 9 +++ .../src/pages/EventPage/HomePage/HomePage.tsx | 14 +++-- 35 files changed, 438 insertions(+), 250 deletions(-) create mode 100644 client/src/components/Design/components/Dropdown/Dropdown.stories.tsx create mode 100644 client/src/components/Design/components/Dropdown/Dropdown.style.ts create mode 100644 client/src/components/Design/components/Dropdown/Dropdown.tsx create mode 100644 client/src/components/Design/components/Dropdown/Dropdown.type.ts create mode 100644 client/src/components/Design/components/Dropdown/DropdownButton.tsx create mode 100644 client/src/components/Design/components/Dropdown/useDropdown.ts delete mode 100644 client/src/components/Design/components/ExpenseList/ExpenseList.style.ts delete mode 100644 client/src/components/Design/components/Search/Search.stories.tsx delete mode 100644 client/src/components/Design/components/Search/Search.style.ts delete mode 100644 client/src/components/Design/components/Search/Search.tsx create mode 100644 client/src/components/Design/token/zIndex.ts create mode 100644 client/src/pages/EventPage/EventPageFallback/BillEmptyFallback/index.tsx create mode 100644 client/src/pages/EventPage/EventPageFallback/fallbackText.ts create mode 100644 client/src/pages/EventPage/HomePage/HomePage.style.ts diff --git a/client/src/components/Design/components/Dropdown/Dropdown.stories.tsx b/client/src/components/Design/components/Dropdown/Dropdown.stories.tsx new file mode 100644 index 000000000..2504ecae7 --- /dev/null +++ b/client/src/components/Design/components/Dropdown/Dropdown.stories.tsx @@ -0,0 +1,34 @@ +/** @jsxImportSource @emotion/react */ +import type {Meta, StoryObj} from '@storybook/react'; + +import Dropdown from '@HDcomponents/Dropdown/Dropdown'; + +import DropdownButton from './DropdownButton'; + +const meta = { + title: 'Components/Dropdown', + component: Dropdown, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + decorators: [ + Story => ( + <div style={{height: '420px'}}> + <Story /> + </div> + ), + ], + args: { + children: [ + <DropdownButton text="전체 참여자 관리" onClick={() => alert('전체 참여자 관리 클릭')} />, + <DropdownButton text="계좌번호 입력하기" onClick={() => alert('계좌번호 입력하기 클릭')} />, + ], + }, +} satisfies Meta<typeof Dropdown>; + +export default meta; + +type Story = StoryObj<typeof meta>; + +export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Dropdown/Dropdown.style.ts b/client/src/components/Design/components/Dropdown/Dropdown.style.ts new file mode 100644 index 000000000..8b4fc91df --- /dev/null +++ b/client/src/components/Design/components/Dropdown/Dropdown.style.ts @@ -0,0 +1,33 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@components/Design/theme/theme.type'; + +import {FlexProps} from '../Flex/Flex.type'; + +export const dropdownStyle: FlexProps = { + flexDirection: 'column', + width: '12.5rem', + padding: '0.5rem', + paddingInline: '0.5rem', + gap: '0.25rem', + backgroundColor: 'white', + + otherStyle: { + position: 'absolute', + top: '2rem', + right: '-1rem', + borderRadius: '0.75rem', + boxShadow: '2px 4px 16px 0 rgba(0, 0, 0, 0.08)', + }, +}; + +export const dropdownButtonStyle = (theme: Theme) => + css({ + height: '2rem', + padding: '0.25rem 0.5rem', + + ':hover': { + borderRadius: '0.625rem', + backgroundColor: theme.colors.grayContainer, + }, + }); diff --git a/client/src/components/Design/components/Dropdown/Dropdown.tsx b/client/src/components/Design/components/Dropdown/Dropdown.tsx new file mode 100644 index 000000000..63045dd56 --- /dev/null +++ b/client/src/components/Design/components/Dropdown/Dropdown.tsx @@ -0,0 +1,36 @@ +/** @jsxImportSource @emotion/react */ +import Icon from '../Icon/Icon'; +import IconButton from '../IconButton/IconButton'; +import Flex from '../Flex/Flex'; + +import useDropdown from './useDropdown'; +import {DropdownProps} from './Dropdown.type'; +import DropdownButton from './DropdownButton'; +import {dropdownStyle} from './Dropdown.style'; + +const Dropdown = ({children}: DropdownProps) => { + const {isOpen, openDropdown, meetBallsRef, dropdownRef} = useDropdown(); + const isDropdownOpen = isOpen && meetBallsRef.current; + + return ( + <IconButton + ref={meetBallsRef} + variants="none" + onClick={openDropdown} + style={{position: 'relative', WebkitTapHighlightColor: 'transparent'}} + > + <Icon iconType="meatballs" /> + {isDropdownOpen && ( + <section ref={dropdownRef}> + <Flex {...dropdownStyle}> + {children.map(button => ( + <DropdownButton {...button.props} /> + ))} + </Flex> + </section> + )} + </IconButton> + ); +}; + +export default Dropdown; diff --git a/client/src/components/Design/components/Dropdown/Dropdown.type.ts b/client/src/components/Design/components/Dropdown/Dropdown.type.ts new file mode 100644 index 000000000..1b67bbc33 --- /dev/null +++ b/client/src/components/Design/components/Dropdown/Dropdown.type.ts @@ -0,0 +1,7 @@ +export type DropdownButtonProps = React.HTMLAttributes<HTMLButtonElement> & { + text: string; +}; + +export type DropdownProps = { + children: React.ReactElement<DropdownButtonProps>[]; +}; diff --git a/client/src/components/Design/components/Dropdown/DropdownButton.tsx b/client/src/components/Design/components/Dropdown/DropdownButton.tsx new file mode 100644 index 000000000..005a6042a --- /dev/null +++ b/client/src/components/Design/components/Dropdown/DropdownButton.tsx @@ -0,0 +1,21 @@ +/** @jsxImportSource @emotion/react */ + +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Text from '../Text/Text'; + +import {dropdownButtonStyle} from './Dropdown.style'; +import {DropdownButtonProps} from './Dropdown.type'; + +const DropdownButton = ({text, ...buttonProps}: DropdownButtonProps) => { + const {theme} = useTheme(); + return ( + <button css={dropdownButtonStyle(theme)} {...buttonProps}> + <Text size="body" color="black"> + {text} + </Text> + </button> + ); +}; + +export default DropdownButton; diff --git a/client/src/components/Design/components/Dropdown/useDropdown.ts b/client/src/components/Design/components/Dropdown/useDropdown.ts new file mode 100644 index 000000000..f484c62a0 --- /dev/null +++ b/client/src/components/Design/components/Dropdown/useDropdown.ts @@ -0,0 +1,39 @@ +import {useEffect, useRef, useState} from 'react'; + +const useDropdown = () => { + const [isOpen, setIsOpen] = useState(false); + const meetBallsRef = useRef<HTMLButtonElement>(null); + const dropdownRef = useRef<HTMLElement>(null); + + const openDropdown = () => { + setIsOpen(true); + }; + + useEffect(() => { + const clickOutSide = (event: MouseEvent) => { + const targetNode = event.target as Node; + + if ( + (dropdownRef.current && dropdownRef.current.contains(targetNode)) || + (meetBallsRef.current && meetBallsRef.current.contains(targetNode)) + ) { + return; + } + + setIsOpen(false); + }; + document.addEventListener('mousedown', clickOutSide); + return () => { + document.removeEventListener('mousedown', clickOutSide); + }; + }, [dropdownRef]); + + return { + isOpen, + openDropdown, + meetBallsRef, + dropdownRef, + }; +}; + +export default useDropdown; diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx index efade71d5..af2a5af0d 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx @@ -13,11 +13,43 @@ const meta = { }, }, args: { + name: '소하', + onSearch: () => console.log('쿠키'), + placeholder: '안녕', + expenseList: [ - {name: '소하', price: 2000, clipboardText: '토스은행 2000원', onBankButtonClick: () => console.log('소하')}, - {name: '토다리', price: 2000, clipboardText: '토스은행 2000원', onBankButtonClick: () => console.log('토다리')}, - {name: '웨디', price: 1080, clipboardText: '토스은행 1080원', onBankButtonClick: () => console.log('웨디')}, - {name: '쿠키', price: 3020, clipboardText: '토스은행 3020원', onBankButtonClick: () => console.log('쿠키')}, + { + memberId: 1, + name: '소하', + price: 2000, + isDeposited: true, + clipboardText: '토스은행 2000원', + onBankButtonClick: () => console.log('소하'), + }, + { + memberId: 2, + name: '토다리', + price: 2000, + isDeposited: false, + clipboardText: '토스은행 2000원', + onBankButtonClick: () => console.log('토다리'), + }, + { + memberId: 3, + name: '웨디', + price: 1080, + isDeposited: true, + clipboardText: '토스은행 1080원', + onBankButtonClick: () => console.log('웨디'), + }, + { + memberId: 4, + name: '쿠키', + price: 3020, + isDeposited: false, + clipboardText: '토스은행 3020원', + onBankButtonClick: () => console.log('쿠키'), + }, ], }, } satisfies Meta<typeof ExpenseList>; diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.style.ts b/client/src/components/Design/components/ExpenseList/ExpenseList.style.ts deleted file mode 100644 index f24e4914a..000000000 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.style.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const expenseListStyle = (theme: Theme) => - css({ - width: '100%', - backgroundColor: theme.colors.white, - padding: '0.5rem 1rem', - borderRadius: '1rem', - height: '100%', - }); diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx index 6191e80ba..17d7a6ef5 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx @@ -1,7 +1,5 @@ /** @jsxImportSource @emotion/react */ - import Text from '@HDcomponents/Text/Text'; -import {useTheme} from '@theme/HDesignProvider'; import isMobileDevice from '@utils/isMobileDevice'; @@ -9,18 +7,30 @@ import BankSendButton from '../BankSendButton/BankSendButton'; import Icon from '../Icon/Icon'; import IconButton from '../IconButton/IconButton'; import Flex from '../Flex/Flex'; +import Input from '../Input/Input'; +import Amount from '../Amount/Amount'; +import DepositCheck from '../DepositCheck/DepositCheck'; import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; -import {expenseListStyle} from './ExpenseList.style'; -// TODO: (@soha) 따로 파일 분리할까 고민중.. 여기서만 사용할 것 같긴 한데.. 흠 -// TODO: (@todari) : 추후 클릭 시 상호작용이 생기면 iconButton으로 변경할 수 있음 -function ExpenseItem({name, price, onBankButtonClick, clipboardText, ...divProps}: ExpenseItemProps) { +function ExpenseItem({name, price, isDeposited, onBankButtonClick, clipboardText, ...divProps}: ExpenseItemProps) { return ( - <Flex justifyContent="spaceBetween" alignItems="center" height="2.5rem" padding="0.5rem 1rem" {...divProps}> - <Text size="bodyBold">{name}</Text> + <Flex + justifyContent="spaceBetween" + alignItems="center" + height="2.5rem" + padding="0.5rem 1rem" + paddingInline="0.5rem" + {...divProps} + > + <Flex gap="0.5rem" alignItems="center"> + <DepositCheck isDeposited={isDeposited} /> + <Text size="bodyBold" color="onTertiary"> + {name} + </Text> + </Flex> <Flex alignItems="center" gap="0.5rem"> - <Text>{price.toLocaleString('ko-kr')}원</Text> + <Amount amount={price} /> {isMobileDevice() ? ( <BankSendButton clipboardText={clipboardText} @@ -37,14 +47,21 @@ function ExpenseItem({name, price, onBankButtonClick, clipboardText, ...divProps ); } -function ExpenseList({expenseList = []}: ExpenseListProps) { - const {theme} = useTheme(); +function ExpenseList({name, onSearch, placeholder, expenseList = []}: ExpenseListProps) { return ( - <div css={expenseListStyle(theme)}> - {expenseList.map((expense, index: number) => ( - <ExpenseItem key={expense.name + index} {...expense} /> - ))} - </div> + <Flex + flexDirection="column" + width="100%" + backgroundColor="white" + padding="0.5rem 1rem" + paddingInline="0.5rem" + gap="0.5rem" + height="100%" + otherStyle={{borderRadius: '1rem'}} + > + <Input inputType="search" value={name} onChange={onSearch} placeholder={placeholder} /> + {expenseList.length !== 0 && expenseList.map(expense => <ExpenseItem key={expense.memberId} {...expense} />)} + </Flex> ); } diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts index 3987688a3..2340e38c1 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts @@ -1,12 +1,15 @@ -export interface ExpenseItemCustomProps { - name: string; - price: number; +import {Report} from 'types/serviceType'; + +export type ExpenseItemCustomProps = Report & { onBankButtonClick: () => void; clipboardText: string; -} +}; export type ExpenseItemProps = React.ComponentProps<'div'> & ExpenseItemCustomProps; export type ExpenseListProps = { + name: string; + onSearch: ({target}: React.ChangeEvent<HTMLInputElement>) => void; + placeholder: string; expenseList: ExpenseItemProps[]; }; diff --git a/client/src/components/Design/components/Flex/Flex.style.ts b/client/src/components/Design/components/Flex/Flex.style.ts index 548a37654..646fae1cc 100644 --- a/client/src/components/Design/components/Flex/Flex.style.ts +++ b/client/src/components/Design/components/Flex/Flex.style.ts @@ -17,7 +17,6 @@ export const flexStyle = ({ minHeight, backgroundColor, theme, - ...rest }: FlexProps) => css({ display: 'flex', @@ -32,7 +31,6 @@ export const flexStyle = ({ width, height, minHeight, - ...rest, backgroundColor: (() => { switch (backgroundColor) { diff --git a/client/src/components/Design/components/Flex/Flex.tsx b/client/src/components/Design/components/Flex/Flex.tsx index 08709701a..d114a90d7 100644 --- a/client/src/components/Design/components/Flex/Flex.tsx +++ b/client/src/components/Design/components/Flex/Flex.tsx @@ -1,6 +1,4 @@ /** @jsxImportSource @emotion/react */ -import {css} from '@emotion/react'; - import {StrictPropsWithChildren} from '@type/strictPropsWithChildren'; import {useTheme} from '../../index'; @@ -9,9 +7,13 @@ import {FlexProps} from './Flex.type'; import {flexStyle} from './Flex.style'; // TODO: (@weadie) 지정된 프롭 말고 다른 프롭도 가져올 수 있게 하자. -function Flex({children, ...props}: StrictPropsWithChildren<FlexProps>) { +function Flex({children, otherStyle, ...props}: StrictPropsWithChildren<FlexProps>) { const {theme} = useTheme(); - return <div css={flexStyle({theme, ...props})}>{children}</div>; + return ( + <div css={flexStyle({theme, ...props})} style={otherStyle}> + {children} + </div> + ); } export default Flex; diff --git a/client/src/components/Design/components/Flex/Flex.type.ts b/client/src/components/Design/components/Flex/Flex.type.ts index d3db7b414..56ab47d2a 100644 --- a/client/src/components/Design/components/Flex/Flex.type.ts +++ b/client/src/components/Design/components/Flex/Flex.type.ts @@ -17,4 +17,6 @@ export interface FlexProps { backgroundColor?: FlexBackgroundColor; theme?: Theme; minHeight?: string; + + otherStyle?: React.CSSProperties; } diff --git a/client/src/components/Design/components/Input/Input.style.ts b/client/src/components/Design/components/Input/Input.style.ts index 3748d6b46..666508cf8 100644 --- a/client/src/components/Design/components/Input/Input.style.ts +++ b/client/src/components/Design/components/Input/Input.style.ts @@ -2,27 +2,11 @@ import {css} from '@emotion/react'; import {Theme} from '@theme/theme.type'; -import {InputType} from './Input.type'; - -const getBackgroundColorStyle = (theme: Theme, inputType: InputType = 'input') => { - switch (inputType) { - case 'input': - return theme.colors.lightGrayContainer; - - case 'search': - return theme.colors.white; - - default: - return theme.colors.lightGrayContainer; - } -}; - const getBorderStyle = (isFocus: boolean, theme: Theme, isError?: boolean) => isError ? `0 0 0 1px ${theme.colors.error} inset` : isFocus ? `0 0 0 1px ${theme.colors.primary} inset` : 'none'; export const inputBoxStyle = ( theme: Theme, - inputType: InputType = 'input', isFocus: boolean, isError: boolean | undefined, isAlwaysOnBorder: boolean, @@ -34,8 +18,7 @@ export const inputBoxStyle = ( gap: '1rem', padding: '0.75rem 1rem', borderRadius: '1rem', - backgroundColor: getBackgroundColorStyle(theme, inputType), - + backgroundColor: theme.colors.lightGrayContainer, boxSizing: 'border-box', boxShadow: getBorderStyle(isFocus, theme, isError), }, diff --git a/client/src/components/Design/components/Input/Input.tsx b/client/src/components/Design/components/Input/Input.tsx index 61952517b..08d879c6a 100644 --- a/client/src/components/Design/components/Input/Input.tsx +++ b/client/src/components/Design/components/Input/Input.tsx @@ -36,7 +36,7 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro useImperativeHandle(ref, () => inputRef.current!); return ( - <div css={inputBoxStyle(theme, inputType, hasFocus, isError, isAlwaysOnBorder)}> + <div css={inputBoxStyle(theme, hasFocus, isError, isAlwaysOnBorder)}> <input css={inputStyle(theme)} ref={inputRef} @@ -49,11 +49,16 @@ export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputPro autoFocus={autoFocus} {...htmlProps} /> - {value && hasFocus && ( + {inputType === 'input' && value && hasFocus && ( <IconButton tabIndex={-1} variants="none" onMouseDown={handleClickDelete}> <Icon iconType="inputDelete" /> </IconButton> )} + {inputType === 'search' && ( + <IconButton tabIndex={-1} variants="none"> + <Icon iconType="search" /> + </IconButton> + )} </div> ); }); diff --git a/client/src/components/Design/components/Search/Search.stories.tsx b/client/src/components/Design/components/Search/Search.stories.tsx deleted file mode 100644 index c1cba856d..000000000 --- a/client/src/components/Design/components/Search/Search.stories.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import React from 'react'; - -import Search from '@HDcomponents/Search/Search'; - -const meta = { - title: 'Components/Search', - component: Search, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - decorators: [ - Story => ( - <div style={{minHeight: '10rem'}}> - <Story /> - </div> - ), - ], - args: { - isShowTargetInput: true, - matchItems: ['todari', 'cookie'], - onMatchItemClick: keyword => alert(keyword), - }, -} satisfies Meta<typeof Search>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Search/Search.style.ts b/client/src/components/Design/components/Search/Search.style.ts deleted file mode 100644 index d75e8fe25..000000000 --- a/client/src/components/Design/components/Search/Search.style.ts +++ /dev/null @@ -1,42 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const searchStyle = css({ - position: 'relative', - - width: '100%', -}); - -export const searchTermsStyle = (theme: Theme) => - css({ - position: 'absolute', - top: '3.5rem', - zIndex: 1, - - width: '100%', - padding: '0.5rem 1rem', - - borderRadius: '1rem', - - backgroundColor: theme.colors.white, - - boxShadow: '0 0.25rem 0.5rem 0 rgba(0, 0, 0, 0.12)', - }); - -export const searchTermStyle = (theme: Theme) => - css( - { - width: '100%', - padding: '0.5rem', - - color: theme.colors.onTertiary, - - '&:hover': { - borderRadius: '0.5rem', - - backgroundColor: theme.colors.lightGrayContainer, - }, - }, - theme.typography.body, - ); diff --git a/client/src/components/Design/components/Search/Search.tsx b/client/src/components/Design/components/Search/Search.tsx deleted file mode 100644 index aa1fa8a4c..000000000 --- a/client/src/components/Design/components/Search/Search.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import Flex from '@HDcomponents/Flex/Flex'; -import {useTheme} from '@theme/HDesignProvider'; - -import {searchStyle, searchTermsStyle, searchTermStyle} from './Search.style'; - -export interface SearchProps { - isShowTargetInput: boolean; - matchItems: string[]; - onMatchItemClick: (term: string) => void; -} - -const Search = ({isShowTargetInput, matchItems, onMatchItemClick, children}: React.PropsWithChildren<SearchProps>) => { - const {theme} = useTheme(); - - return ( - <fieldset css={searchStyle}> - {children} - {matchItems.length > 0 && isShowTargetInput && ( - <ul css={searchTermsStyle(theme)}> - <Flex flexDirection="column" gap="0.5rem"> - {matchItems.map((matchItem, index) => ( - <li key={`${matchItem}-${index}`}> - <button type="button" css={searchTermStyle(theme)} onClick={() => onMatchItemClick(matchItem)}> - {matchItem} - </button> - </li> - ))} - </Flex> - </ul> - )} - </fieldset> - ); -}; - -export default Search; diff --git a/client/src/components/Design/components/Tabs/Tabs.style.ts b/client/src/components/Design/components/Tabs/Tabs.style.ts index 3ea38924c..7c1eb771a 100644 --- a/client/src/components/Design/components/Tabs/Tabs.style.ts +++ b/client/src/components/Design/components/Tabs/Tabs.style.ts @@ -1,53 +1,63 @@ import {css} from '@emotion/react'; -import {Theme} from '@theme/theme.type'; +import {WithTheme} from '@components/Design/type/withTheme'; -export const tabListStyle = (theme: Theme) => +export const tabListStyle = ({theme}: WithTheme) => css({ position: 'relative', + height: '3rem', + marginBottom: '0.5rem', + + borderRadius: '0.75rem', backgroundColor: theme.colors.white, cursor: 'pointer', WebkitTapHighlightColor: 'transparent', - - '&::after': { - position: 'absolute', - left: 0, - bottom: 0, - zIndex: 1, - - width: '100%', - height: '0.0625rem', - - backgroundColor: theme.colors.gray, - - content: '""', - }, }); export const tabItemStyle = css({ flex: 1, - textAlign: 'center', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + + height: '100%', }); -export const tabTextStyle = (theme: Theme, selected: boolean) => +type WithSelected = WithTheme & { + selected: boolean; +}; + +type IndicatorType = WithTheme & { + tabWidth: number; + activeTabIndex: number; +}; + +export const tabTextStyle = ({theme, selected}: WithSelected) => css({ color: selected ? theme.colors.onTertiary : theme.colors.gray, + + zIndex: theme.zIndex.visible, }); -export const indicatorStyle = (theme: Theme, leftPosition: string, tabLength: number) => +export const indicatorStyle = ({theme, tabWidth, activeTabIndex}: IndicatorType) => css({ position: 'absolute', - left: leftPosition, - bottom: 0, - zIndex: 2, + bottom: '0.5rem', + left: '0.5rem', + width: `${tabWidth}px`, + height: 'calc(100% - 1rem)', + + borderRadius: '0.625rem', + backgroundColor: theme.colors.tertiary, + + transform: `translateX(${(tabWidth + 8) * activeTabIndex}px)`, - width: `calc(100% / ${tabLength})`, - height: '0.125rem', + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - backgroundColor: theme.colors.onSecondary, - transition: 'left 0.3s', + zIndex: theme.zIndex.normal, }); diff --git a/client/src/components/Design/components/Tabs/Tabs.tsx b/client/src/components/Design/components/Tabs/Tabs.tsx index 0245b5ba7..8a5e3fad0 100644 --- a/client/src/components/Design/components/Tabs/Tabs.tsx +++ b/client/src/components/Design/components/Tabs/Tabs.tsx @@ -1,28 +1,60 @@ /** @jsxImportSource @emotion/react */ -import React, {useState} from 'react'; -import {css} from '@emotion/react'; +import React, {useEffect, useRef, useState} from 'react'; import {useTheme} from '@theme/HDesignProvider'; import Text from '../Text/Text'; import Flex from '../Flex/Flex'; -import {tabListStyle, indicatorStyle, tabItemStyle, tabTextStyle} from './Tabs.style'; +import {tabListStyle, tabItemStyle, tabTextStyle, indicatorStyle} from './Tabs.style'; import {TabsProps} from './Tab.type'; const Tabs: React.FC<TabsProps> = ({children, tabsContainerStyle}) => { const {theme} = useTheme(); const [activeTabIndex, setActiveTabIndex] = useState(0); + const [tabWidth, setTabWidth] = useState(0); + const tabRef = useRef<HTMLLIElement>(null); const isActive = (index: number) => activeTabIndex === index; - const tabItemCount = children.length; + + const setTabWidthResizeObserveCallback = (entries: ResizeObserverEntry[]) => { + for (const entry of entries) { + if (entry.target === tabRef.current) { + setTabWidth(entry.contentRect.width); + } + } + }; + + useEffect(() => { + const tabCurrent = tabRef.current; + + if (tabCurrent) { + const resizeObserver = new ResizeObserver(setTabWidthResizeObserveCallback); + resizeObserver.observe(tabCurrent); + + return () => { + resizeObserver.unobserve(tabCurrent); + }; + } + + // useEffect 경고문구 제거를 위해 return 추가 (Not all code paths return a value.) + return; + }, [tabRef]); return ( <Flex flexDirection="column" {...tabsContainerStyle}> - <ul role="tablist" css={tabListStyle(theme)}> - <Flex justifyContent="spaceBetween" alignItems="center" padding="0.5rem"> + <ul role="tablist" css={tabListStyle({theme})}> + <Flex + justifyContent="spaceBetween" + alignItems="center" + height="100%" + padding="0.5rem" + paddingInline="0.5rem" + gap="0.5rem" + > {children.map((tabItem, index) => ( <li + ref={tabRef} key={tabItem.props.label} role="tab" id={`tab-${tabItem.props.label}`} @@ -31,13 +63,13 @@ const Tabs: React.FC<TabsProps> = ({children, tabsContainerStyle}) => { onClick={() => setActiveTabIndex(index)} aria-controls={`tabpanel-${tabItem.props.label}`} > - <Text css={tabTextStyle(theme, isActive(index))} size={isActive(index) ? 'bodyBold' : 'body'}> + <Text css={tabTextStyle({theme, selected: isActive(index)})} size={isActive(index) ? 'bodyBold' : 'body'}> {tabItem.props.label} </Text> </li> ))} - <div css={indicatorStyle(theme, `${(activeTabIndex * 100) / tabItemCount}%`, tabItemCount)} /> </Flex> + {tabRef.current && tabWidth !== 0 && <div css={indicatorStyle({theme, tabWidth, activeTabIndex})} />} </ul> <section role="tabpanel" diff --git a/client/src/components/Design/components/Title/Title.tsx b/client/src/components/Design/components/Title/Title.tsx index ac33cfb49..deab3ec4a 100644 --- a/client/src/components/Design/components/Title/Title.tsx +++ b/client/src/components/Design/components/Title/Title.tsx @@ -4,16 +4,15 @@ import {amountContainerStyle, titleContainerStyle, titleStyle} from '@HDcomponen import {TitleProps} from '@HDcomponents/Title/Title.type'; import {useTheme} from '@theme/HDesignProvider'; -import Icon from '../Icon/Icon'; import Amount from '../Amount/Amount'; -export const Title: React.FC<TitleProps> = ({title, amount}: TitleProps) => { +export const Title: React.FC<TitleProps> = ({title, amount, dropdown}: TitleProps) => { const {theme} = useTheme(); return ( <div css={titleStyle(theme)}> <div css={titleContainerStyle}> <Text size="subTitle">{title}</Text> - <Icon iconType="meatballs" /> + {dropdown} </div> <div css={amountContainerStyle}> <Text textColor="gray" size="caption"> diff --git a/client/src/components/Design/components/Title/Title.type.ts b/client/src/components/Design/components/Title/Title.type.ts index 2b0718dda..cb28743f4 100644 --- a/client/src/components/Design/components/Title/Title.type.ts +++ b/client/src/components/Design/components/Title/Title.type.ts @@ -3,6 +3,7 @@ export interface TitleStyleProps {} export interface TitleCustomProps { title: string; amount?: number; + dropdown?: React.ReactNode; } export type TitleOptionProps = TitleStyleProps & TitleCustomProps; diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx index 7f1f3e7a2..8ba2d1d0e 100644 --- a/client/src/components/Design/index.tsx +++ b/client/src/components/Design/index.tsx @@ -17,7 +17,6 @@ import Input from './components/Input/Input'; import LabelInput from './components/LabelInput/LabelInput'; import ListButton from './components/ListButton/ListButton'; import LabelGroupInput from './components/LabelGroupInput/LabelGroupInput'; -import Search from './components/Search/Search'; import Switch from './components/Switch/Switch'; import Top from './components/Top/Top'; import Tab from './components/Tabs/Tab'; @@ -27,6 +26,8 @@ import TextButton from './components/TextButton/TextButton'; import Title from './components/Title/Title'; import Back from './components/TopNav/Back'; import TopNav from './components/TopNav/TopNav'; +import Dropdown from './components/Dropdown/Dropdown'; +import DropdownButton from './components/Dropdown/DropdownButton'; export { BankSelect, @@ -44,7 +45,6 @@ export { LabelInput, ListButton, LabelGroupInput, - Search, Switch, Top, Tab, @@ -59,4 +59,6 @@ export { ContentLayout, HDesignProvider, useTheme, + Dropdown, + DropdownButton, }; diff --git a/client/src/components/Design/theme/HDesignProvider.tsx b/client/src/components/Design/theme/HDesignProvider.tsx index e4b5312f7..c5367afa1 100644 --- a/client/src/components/Design/theme/HDesignProvider.tsx +++ b/client/src/components/Design/theme/HDesignProvider.tsx @@ -5,6 +5,7 @@ import {Theme} from '@theme/theme.type'; import {GlobalStyle} from '@theme/GlobalStyle'; import {COLORS} from '@token/colors'; import {TYPOGRAPHY} from '@token/typography'; +import {ZINDEX} from '@token/zIndex'; interface ThemeContextProps { theme: Theme; @@ -13,6 +14,7 @@ interface ThemeContextProps { const defaultTheme: Theme = { colors: COLORS, typography: TYPOGRAPHY, + zIndex: ZINDEX, }; const ThemeContext = createContext<ThemeContextProps | undefined>(undefined); diff --git a/client/src/components/Design/theme/theme.type.ts b/client/src/components/Design/theme/theme.type.ts index dffd961f0..c6dbe0544 100644 --- a/client/src/components/Design/theme/theme.type.ts +++ b/client/src/components/Design/theme/theme.type.ts @@ -1,7 +1,9 @@ import {ColorTokens} from '@token/colors'; import {TypographyTokens} from '@token/typography'; +import {ZIndexTokens} from '@token/zIndex'; export interface Theme { colors: ColorTokens; typography: TypographyTokens; + zIndex: ZIndexTokens; } diff --git a/client/src/components/Design/token/zIndex.ts b/client/src/components/Design/token/zIndex.ts new file mode 100644 index 000000000..1a7991b34 --- /dev/null +++ b/client/src/components/Design/token/zIndex.ts @@ -0,0 +1,8 @@ +export const ZINDEX = { + normal: 0, + hidden: -1, + visible: 1, +} as const; + +type ZIndexKeys = 'normal' | 'hidden' | 'visible'; +export type ZIndexTokens = Record<ZIndexKeys, number>; diff --git a/client/src/components/Reports/Reports.tsx b/client/src/components/Reports/Reports.tsx index 75804f920..cdd6d6bea 100644 --- a/client/src/components/Reports/Reports.tsx +++ b/client/src/components/Reports/Reports.tsx @@ -1,24 +1,19 @@ +import BillEmptyFallback from '@pages/EventPage/EventPageFallback/BillEmptyFallback'; + import useReportsPage from '@hooks/useReportsPage'; -import {ExpenseList, Flex, Input, Text} from '@HDesign/index'; +import {ExpenseList, Flex} from '@HDesign/index'; const Reports = () => { - const {isEmpty, matchedReports, expenseListProp, name, changeName} = useReportsPage(); + const {isEmpty, expenseListProp, name, changeName} = useReportsPage(); + + if (isEmpty) { + return <BillEmptyFallback />; + } return ( - <Flex flexDirection="column" gap="0.5rem" paddingInline="0.5rem"> - {!isEmpty ? ( - <> - <Input inputType="search" value={name} onChange={changeName} placeholder="참여자 이름" /> - {matchedReports.length !== 0 && <ExpenseList expenseList={expenseListProp} />} - </> - ) : ( - <Flex width="100%" justifyContent="center"> - <Text size="body" textColor="gray" style={{paddingTop: '1rem'}}> - 지금은 참여자가 한 명도 없어요. :( - </Text> - </Flex> - )} + <Flex flexDirection="column" gap="0.5rem"> + <ExpenseList name={name} onSearch={changeName} placeholder="이름 검색" expenseList={expenseListProp} /> </Flex> ); }; diff --git a/client/src/components/ShareEventButton/ShareEventButton.tsx b/client/src/components/ShareEventButton/ShareEventButton.tsx index df8e659f8..8f9bd6727 100644 --- a/client/src/components/ShareEventButton/ShareEventButton.tsx +++ b/client/src/components/ShareEventButton/ShareEventButton.tsx @@ -39,7 +39,7 @@ const ShareEventButton = ({eventOutline}: ShareEventButtonProps) => { }; return isMobile ? ( - <Button size="small" variants="secondary" onClick={induceBankInfoBeforeShare}> + <Button size="small" variants="tertiary" onClick={induceBankInfoBeforeShare}> 카카오톡으로 정산 초대하기 </Button> ) : ( @@ -52,7 +52,7 @@ const ShareEventButton = ({eventOutline}: ShareEventButtonProps) => { }) } > - <Button size="small" variants="secondary" onClick={induceBankInfoBeforeShare}> + <Button size="small" variants="tertiary" onClick={induceBankInfoBeforeShare}> 정산 초대하기 </Button> </CopyToClipboard> diff --git a/client/src/components/StepList/Steps.tsx b/client/src/components/StepList/Steps.tsx index 3146e355a..0f1a525ad 100644 --- a/client/src/components/StepList/Steps.tsx +++ b/client/src/components/StepList/Steps.tsx @@ -1,25 +1,25 @@ import {Step as StepType} from 'types/serviceType'; +import BillEmptyFallback from '@pages/EventPage/EventPageFallback/BillEmptyFallback'; -import {Flex, Text} from '@HDesign/index'; +import {Flex} from '@HDesign/index'; import Step from './Step'; interface Props { data: StepType[]; + isAdmin: boolean; } -const Steps = ({data}: Props) => { +const Steps = ({data, isAdmin}: Props) => { + if (data.length <= 0 && !isAdmin) { + return <BillEmptyFallback />; + } + return ( <Flex flexDirection="column" gap="0.5rem"> - {data.length > 0 ? ( - data.map(step => <Step step={step} />) - ) : ( - <Flex width="100%" justifyContent="center"> - <Text size="body" textColor="gray" style={{paddingTop: '1rem'}}> - 지금은 지출 내역이 없어요. :( - </Text> - </Flex> - )} + {data.map((step, index) => ( + <Step key={index} step={step} /> + ))} </Flex> ); }; diff --git a/client/src/hooks/useReportsPage.ts b/client/src/hooks/useReportsPage.ts index 9b7555b2f..7dc7e2726 100644 --- a/client/src/hooks/useReportsPage.ts +++ b/client/src/hooks/useReportsPage.ts @@ -40,7 +40,6 @@ const useReportsPage = () => { return { isEmpty, - matchedReports, expenseListProp, name, changeName, diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 7a5168d27..24d9cfde0 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -7,7 +7,7 @@ import useRequestGetSteps from '@hooks/queries/step/useRequestGetSteps'; import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; -import {Title, Button} from '@HDesign/index'; +import {Title, Button, Dropdown, DropdownButton} from '@HDesign/index'; import getEventIdByUrl from '@utils/getEventIdByUrl'; @@ -18,7 +18,7 @@ import {receiptStyle} from './AdminPage.style'; const AdminPage = () => { const navigate = useNavigate(); const eventId = getEventIdByUrl(); - const {eventName} = useOutletContext<EventPageContextProps>(); + const {isAdmin, eventName} = useOutletContext<EventPageContextProps>(); const {totalExpenseAmount} = useTotalExpenseAmountStore(); @@ -29,10 +29,24 @@ const AdminPage = () => { postAuthenticate(); }, [postAuthenticate]); + const navigateAccountInputPage = () => { + // TODO:(@cookie) 569 브랜치가 머지된 후에 작업 가능합니다. + navigate('/'); + }; + return ( <section css={receiptStyle}> - <Title title={eventName} amount={totalExpenseAmount} /> - <StepList data={steps ?? []} /> + <Title + title={eventName} + amount={totalExpenseAmount} + dropdown={ + <Dropdown> + <DropdownButton text="전체 참여자 관리" /> + <DropdownButton text="계좌번호 입력하기" /> + </Dropdown> + } + /> + <StepList data={steps ?? []} isAdmin={isAdmin} /> <Button size="medium" onClick={() => navigate(`/event/${eventId}/addBill`)} style={{width: '100%'}}> 지출내역 추가하기 </Button> diff --git a/client/src/pages/EventPage/EventPageFallback/BillEmptyFallback/index.tsx b/client/src/pages/EventPage/EventPageFallback/BillEmptyFallback/index.tsx new file mode 100644 index 000000000..4e8c0d7d7 --- /dev/null +++ b/client/src/pages/EventPage/EventPageFallback/BillEmptyFallback/index.tsx @@ -0,0 +1,16 @@ +import {Flex, Text} from '@components/Design'; + +import FALLBACK_TEXT from '../fallbackText'; + +const BillEmptyFallback = () => { + return ( + <Flex flexDirection="column" justifyContent="center" alignItems="center" gap="1.5rem" width="100%" height="20rem"> + <Text size="subTitle">{FALLBACK_TEXT.billEmptyTitle}</Text> + <Text size="body" style={{textAlign: 'center'}}> + {FALLBACK_TEXT.billEmptyHome} + </Text> + </Flex> + ); +}; + +export default BillEmptyFallback; diff --git a/client/src/pages/EventPage/EventPageFallback/fallbackText.ts b/client/src/pages/EventPage/EventPageFallback/fallbackText.ts new file mode 100644 index 000000000..6238264aa --- /dev/null +++ b/client/src/pages/EventPage/EventPageFallback/fallbackText.ts @@ -0,0 +1,7 @@ +const FALLBACK_TEXT = { + billEmptyTitle: '행사가 시작되지 않았어요', + billEmptyHome: `주최자가 아직 지출 내역을 +등록하지 않았어요.`, +} as const; + +export default FALLBACK_TEXT; diff --git a/client/src/pages/EventPage/HomePage/HomePage.style.ts b/client/src/pages/EventPage/HomePage/HomePage.style.ts new file mode 100644 index 000000000..d02747cb2 --- /dev/null +++ b/client/src/pages/EventPage/HomePage/HomePage.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +export const receiptStyle = css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + paddingInline: '1rem', + paddingBottom: '2rem', +}); diff --git a/client/src/pages/EventPage/HomePage/HomePage.tsx b/client/src/pages/EventPage/HomePage/HomePage.tsx index 34b91a762..1876327bf 100644 --- a/client/src/pages/EventPage/HomePage/HomePage.tsx +++ b/client/src/pages/EventPage/HomePage/HomePage.tsx @@ -1,3 +1,5 @@ +import type {EventPageContextProps} from '../EventPageLayout'; + import {useOutletContext} from 'react-router-dom'; import StepList from '@components/StepList/Steps'; @@ -8,19 +10,19 @@ import {useTotalExpenseAmountStore} from '@store/totalExpenseAmountStore'; import {Tab, Tabs, Title} from '@HDesign/index'; -import {EventPageContextProps} from '../EventPageLayout'; +import {receiptStyle} from './HomePage.style'; const HomePage = () => { - const {eventName} = useOutletContext<EventPageContextProps>(); + const {isAdmin, eventName} = useOutletContext<EventPageContextProps>(); const {steps} = useRequestGetSteps(); const {totalExpenseAmount} = useTotalExpenseAmountStore(); return ( - <div style={{paddingBottom: '2rem'}}> + <div css={receiptStyle}> <Title title={eventName} amount={totalExpenseAmount} /> - <Tabs tabsContainerStyle={{gap: '1rem'}}> - <Tab label="전체 지출 내역" content={<StepList data={steps ?? []} />} /> - <Tab label="참여자 별 내역" content={<Reports />} /> + <Tabs> + <Tab label="참여자 별 정산" content={<Reports />} /> + <Tab label="전체 지출 내역" content={<StepList data={steps ?? []} isAdmin={isAdmin} />} /> </Tabs> </div> ); From 8271194382d912b645694ea7ad70892c6989ea68 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:42:24 +0900 Subject: [PATCH 240/273] =?UTF-8?q?feat:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=83=9D=EC=84=B1=ED=95=98=EA=B8=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#587)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 지출 내역 생성 api 연결 및 유효성 검사 * feat: Funnel 파일 분리 및 member 생성 api 로직 변경 * fix: AddBillFunnel route 수정 * style: lint 적용 * refactor: BillStep hook 분리 * style: lint 적용 * fix: postMember api 요청 변경 * fix: addBill route 수정 * fix: TitleStep에서 PriceStep으로 이동했을 때, billInfo.price 초기화되던 오류 수정 * fix: MSW mocking 해제 * rename: AddBillFunnel 경로 수정 * fix: mutateAsync를 이용하여 postMembers 이후 postBills 요청을 보내도록 수정 * fix: API 변경에 맞추어 수정 * style: lint 적용 --- client/src/apis/request/bill.ts | 6 +- client/src/apis/request/member.ts | 2 +- .../NumberKeyboard/NumberKeyboard.tsx | 4 +- .../NumberKeyboard/useNumberKeyboard.tsx | 5 +- client/src/constants/regExp.ts | 4 +- client/src/constants/routerUrls.ts | 2 +- .../hooks/queries/bill/useRequestPostBill.ts | 2 +- .../queries/member/useRequestPostMembers.ts | 14 +- client/src/hooks/useAddBillFunnel.ts | 33 +++ client/src/hooks/useMembersStep.ts | 122 ++++++++++ client/src/hooks/usePriceStep.ts | 27 +++ client/src/hooks/useTitleStep.ts | 64 +++++ client/src/mocks/handlers/billHandler.ts | 16 +- .../src/pages/AddBillFunnel/AddBillFunnel.tsx | 34 +++ .../pages/AddBillFunnel/steps/MembersStep.tsx | 102 ++++++++ .../pages/AddBillFunnel/steps/PriceStep.tsx | 62 +++++ .../pages/AddBillFunnel/steps/TitleStep.tsx | 63 +++++ client/src/pages/BillPage/AddBillFunnel.tsx | 220 ------------------ client/src/router.tsx | 2 +- client/src/utils/validate/validatePurchase.ts | 47 ---- 20 files changed, 539 insertions(+), 292 deletions(-) create mode 100644 client/src/hooks/useAddBillFunnel.ts create mode 100644 client/src/hooks/useMembersStep.ts create mode 100644 client/src/hooks/usePriceStep.ts create mode 100644 client/src/hooks/useTitleStep.ts create mode 100644 client/src/pages/AddBillFunnel/AddBillFunnel.tsx create mode 100644 client/src/pages/AddBillFunnel/steps/MembersStep.tsx create mode 100644 client/src/pages/AddBillFunnel/steps/PriceStep.tsx create mode 100644 client/src/pages/AddBillFunnel/steps/TitleStep.tsx delete mode 100644 client/src/pages/BillPage/AddBillFunnel.tsx delete mode 100644 client/src/utils/validate/validatePurchase.ts diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 03bbd5317..63173a06f 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -10,17 +10,17 @@ import {WithBillId, WithEventId} from '@apis/withId.type'; export interface RequestPostBill { title: string; price: number; - members: number[]; + memberIds: number[]; } -export const requestPostBill = async ({eventId, title, price, members}: WithEventId<RequestPostBill>) => { +export const requestPostBill = async ({eventId, title, price, memberIds}: WithEventId<RequestPostBill>) => { await requestPostWithoutResponse({ baseUrl: BASE_URL.HD, endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills`, body: { title, price, - members, + memberIds, }, }); }; diff --git a/client/src/apis/request/member.ts b/client/src/apis/request/member.ts index 4e5da1bb4..756412784 100644 --- a/client/src/apis/request/member.ts +++ b/client/src/apis/request/member.ts @@ -7,7 +7,7 @@ import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; import {requestDelete, requestGet, requestPut, requestPostWithResponse} from '@apis/fetcher'; import {WithEventId} from '@apis/withId.type'; -interface PostMember { +export interface PostMember { name: string; } diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx index 0da3862de..61e36da7d 100644 --- a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx @@ -11,16 +11,18 @@ export type KeyboardType = 'number' | 'string' | 'amount'; interface Props { type: KeyboardType; maxNumber: number; + initialValue?: string; onChange: (value: string) => void; } -export default function NumberKeyboard({type, maxNumber, onChange}: Props) { +export default function NumberKeyboard({type, maxNumber, initialValue, onChange}: Props) { const {theme} = useTheme(); const amountKeypads = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '00', '0', '<-']; const numberKeypads = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '', '0', '<-']; const {onClickKeypad, onClickDelete, onClickDeleteAll, onClickAddAmount} = useNumberKeyboard({ type, + initialValue, maxNumber, onChange, }); diff --git a/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx index f8d5fbaed..48301ea8e 100644 --- a/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx +++ b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx @@ -5,11 +5,12 @@ import {KeyboardType} from './NumberKeyboard'; interface Props { type: KeyboardType; maxNumber?: number; + initialValue?: string; onChange: (value: string) => void; } -const useNumberKeyboard = ({type, maxNumber, onChange}: Props) => { - const [value, setValue] = useState(''); +const useNumberKeyboard = ({type, maxNumber, initialValue, onChange}: Props) => { + const [value, setValue] = useState(initialValue ?? ''); const onClickKeypad = (inputValue: string) => { const newValue = (value + inputValue).replace(/,/g, ''); diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts index 4d910ac99..d235c1f11 100644 --- a/client/src/constants/regExp.ts +++ b/client/src/constants/regExp.ts @@ -1,8 +1,8 @@ const REGEXP = { eventPassword: /^[0-9]*$/, - memberName: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z\s]*$/, - purchaseTitle: /^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9\s]*$/, eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, + billTitle: /^([ㄱ-ㅎ가-힣a-zA-Z0-9ㆍᆢ]\s?)*$/, + memberName: /^([ㄱ-ㅎ가-힣a-zA-Zㆍᆢ]\s?)*$/, }; export default REGEXP; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index 2955115d7..8cd486d9b 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -7,6 +7,6 @@ export const ROUTER_URLS = { eventLogin: '/event/:eventId/login', eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', - addBill: 'event/:eventId/addBill', + addBill: '/event/:eventId/add-bill', eventEdit: 'event/:eventId/admin/edit', }; diff --git a/client/src/hooks/queries/bill/useRequestPostBill.ts b/client/src/hooks/queries/bill/useRequestPostBill.ts index 80e4b685c..a9c7bce62 100644 --- a/client/src/hooks/queries/bill/useRequestPostBill.ts +++ b/client/src/hooks/queries/bill/useRequestPostBill.ts @@ -11,7 +11,7 @@ const useRequestPostBill = () => { const queryClient = useQueryClient(); const {mutate, ...rest} = useMutation({ - mutationFn: ({title, price, members}: RequestPostBill) => requestPostBill({eventId, title, price, members}), + mutationFn: ({title, price, memberIds}: RequestPostBill) => requestPostBill({eventId, title, price, memberIds}), onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); diff --git a/client/src/hooks/queries/member/useRequestPostMembers.ts b/client/src/hooks/queries/member/useRequestPostMembers.ts index 72da9f363..bddb9a322 100644 --- a/client/src/hooks/queries/member/useRequestPostMembers.ts +++ b/client/src/hooks/queries/member/useRequestPostMembers.ts @@ -10,23 +10,17 @@ const useRequestPostMembers = () => { const eventId = getEventIdByUrl(); const queryClient = useQueryClient(); - const {mutate, ...rest} = useMutation({ + const {mutate, mutateAsync, data, ...rest} = useMutation({ mutationFn: ({members}: RequestPostMembers) => requestPostMembers({eventId, members}), - // TODO: (@todari) : 낙관적 업데이트 적고 있었어용 - // onMutate: async ({type, memberName}) => { - // await queryClient.cancelQueries({queryKey: [QUERY_KEYS.step]}); - // const previousStep = queryClient.getQueryData([QUERY_KEYS.step]); - // queryClient.setQueryData([QUERY_KEYS.step], (prev: (MemberStep | BillStep)[]) => prev && { - // }); - // }, - onSuccess: () => { + onSuccess: responseData => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.allMembers]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); queryClient.invalidateQueries({queryKey: [QUERY_KEYS.reports]}); + return responseData; }, }); - return {postMember: mutate, ...rest}; + return {postMembers: mutate, postMembersAsync: mutateAsync, responseMemberIds: data, ...rest}; }; export default useRequestPostMembers; diff --git a/client/src/hooks/useAddBillFunnel.ts b/client/src/hooks/useAddBillFunnel.ts new file mode 100644 index 000000000..f0b1e87e8 --- /dev/null +++ b/client/src/hooks/useAddBillFunnel.ts @@ -0,0 +1,33 @@ +import {useEffect, useState} from 'react'; + +import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; + +import useRequestGetCurrentMembers from './queries/member/useRequestGetCurrentMembers'; + +export type BillStep = 'title' | 'price' | 'members'; + +const useAddBillFunnel = () => { + const {currentMembers} = useRequestGetCurrentMembers(); + const [step, setStep] = useState<BillStep>('price'); + const [billInfo, setBillInfo] = useState<BillInfo>({ + price: '', + title: '', + members: [], + }); + + useEffect(() => { + document.body.style.overflow = 'hidden'; + + return () => { + document.body.style.overflow = 'auto'; + }; + }, []); + + useEffect(() => { + currentMembers && setBillInfo(prev => ({...prev, members: currentMembers})); + }, [currentMembers]); + + return {step, setStep, billInfo, setBillInfo, currentMembers}; +}; + +export default useAddBillFunnel; diff --git a/client/src/hooks/useMembersStep.ts b/client/src/hooks/useMembersStep.ts new file mode 100644 index 000000000..9cd68f2a4 --- /dev/null +++ b/client/src/hooks/useMembersStep.ts @@ -0,0 +1,122 @@ +import {useEffect, useState} from 'react'; +import {useNavigate} from 'react-router-dom'; + +import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; +import {Member} from 'types/serviceType'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import REGEXP from '@constants/regExp'; + +import useRequestPostMembers from './queries/member/useRequestPostMembers'; +import useRequestPostBill from './queries/bill/useRequestPostBill'; +import {BillStep} from './useAddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>; + setStep: React.Dispatch<React.SetStateAction<BillStep>>; + currentMembers: Member[]; +} + +const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => { + const [errorMessage, setErrorMessage] = useState(''); + const [nameInput, setNameInput] = useState(''); + + const {postMembersAsync, isPending: isPendingPostMembers} = useRequestPostMembers(); + + const {postBill, isSuccess: isSuccessPostBill, isPending: isPendingPostBill} = useRequestPostBill(); + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); + + const onNameInputChange = (value: string) => { + if (REGEXP.memberName.test(value)) { + setNameInput(value); + } + }; + + const handleNameInputChange = (event: React.ChangeEvent<HTMLInputElement>) => { + if (event.target.value.length > 4) { + setErrorMessage('이름은 4자까지 입력 가능해요'); + onNameInputChange(nameInput.slice(0, 4)); + } else { + setErrorMessage(''); + onNameInputChange(event.target.value); + } + }; + + const canAddMembers = nameInput && !errorMessage; + + const canSubmitMembers = billInfo.members.length !== 0; + + const setBillInfoMemberWithId = (name: string) => { + const existingMember = currentMembers.find(currentMember => currentMember.name === name); + if (existingMember) { + setBillInfo(prev => ({...prev, members: [...prev.members, {id: existingMember.id, name: name}]})); + } else { + setBillInfo(prev => ({...prev, members: [...prev.members, {id: -1, name: name}]})); + } + }; + + const handleNameInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.nativeEvent.isComposing) { + return; + } + if (event.key === 'Enter' && canAddMembers) { + event.preventDefault(); + if (!billInfo.members.map(({name}) => name).includes(nameInput)) { + setBillInfoMemberWithId(nameInput); + } + setNameInput(''); + } + }; + + const handlePostBill = async () => { + if (billInfo.members.map(({id}) => id).includes(-1)) { + const newMembers = await postMembersAsync({ + members: billInfo.members + .filter(({id}) => id === -1) + .map(({name}) => ({ + name, + })), + }); + postBill({ + title: billInfo.title, + price: Number(billInfo.price.replace(',', '')), + memberIds: billInfo.members.map(member => + member.id === -1 ? newMembers.members.find(m => m.name === member.name)?.id || member.id : member.id, + ), + }); + } else { + postBill({ + title: billInfo.title, + price: Number(billInfo.price.replace(',', '')), + memberIds: billInfo.members.map(({id}) => id), + }); + } + }; + + useEffect(() => { + if (isSuccessPostBill) { + navigate(`/event/${eventId}/admin`); + } + }, [isSuccessPostBill]); + + const handlePrevStep = () => { + setStep('title'); + }; + + return { + errorMessage, + nameInput, + handleNameInputChange, + handleNameInputEnter, + isPendingPostBill, + isPendingPostMembers, + canSubmitMembers, + handlePostBill, + handlePrevStep, + }; +}; + +export default useMembersStep; diff --git a/client/src/hooks/usePriceStep.ts b/client/src/hooks/usePriceStep.ts new file mode 100644 index 000000000..181a44f3d --- /dev/null +++ b/client/src/hooks/usePriceStep.ts @@ -0,0 +1,27 @@ +import {useCallback} from 'react'; + +import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; + +import {BillStep} from './useAddBillFunnel'; + +interface Props { + setStep: React.Dispatch<React.SetStateAction<BillStep>>; + setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>; +} + +const usePriceStep = ({setStep, setBillInfo}: Props) => { + const handleNumberKeyboardChange = useCallback( + (value: string) => { + setBillInfo(prev => ({...prev, price: value})); + }, + [setBillInfo], + ); + + const handleNextStep = () => { + setStep('title'); + }; + + return {handleNumberKeyboardChange, handleNextStep}; +}; + +export default usePriceStep; diff --git a/client/src/hooks/useTitleStep.ts b/client/src/hooks/useTitleStep.ts new file mode 100644 index 000000000..8ed5c787c --- /dev/null +++ b/client/src/hooks/useTitleStep.ts @@ -0,0 +1,64 @@ +import {useState} from 'react'; + +import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; + +import REGEXP from '@constants/regExp'; + +import {BillStep} from './useAddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>; + setStep: React.Dispatch<React.SetStateAction<BillStep>>; +} + +const useTitleStep = ({billInfo, setBillInfo, setStep}: Props) => { + const [errorMessage, setErrorMessage] = useState(''); + + const onTitleInputChange = (value: string) => { + if (REGEXP.billTitle.test(value)) { + setBillInfo(prev => ({...prev, title: value})); + } + }; + + const handleTitleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => { + if (event.target.value.length > 12) { + setErrorMessage('지출내역은 12자까지 입력 가능해요'); + onTitleInputChange(billInfo.title.slice(0, 12)); + } else { + setErrorMessage(''); + onTitleInputChange(event.target.value); + } + }; + + const canSubmitTitleInput = billInfo.title && !errorMessage; + + const handleTitleInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.nativeEvent.isComposing) { + return; + } + if (event.key === 'Enter' && canSubmitTitleInput) { + event.preventDefault(); + setStep('members'); + } + }; + + const handleNextStep = () => { + setStep('members'); + }; + + const handlePrevStep = () => { + setStep('price'); + }; + + return { + errorMessage, + handleTitleInputChange, + handleTitleInputEnter, + canSubmitTitleInput, + handleNextStep, + handlePrevStep, + }; +}; + +export default useTitleStep; diff --git a/client/src/mocks/handlers/billHandler.ts b/client/src/mocks/handlers/billHandler.ts index 0130b52a2..67a8935b7 100644 --- a/client/src/mocks/handlers/billHandler.ts +++ b/client/src/mocks/handlers/billHandler.ts @@ -31,13 +31,23 @@ export const billHandler = [ const {title, price, members} = await request.json(); const newBill = {id: Date.now(), title, price, isFixed: false}; - billData.steps[0].bills.push(newBill); - billData.steps[0].members = members.map(id => ({id, name: `Member ${id}`})); + const lastStep = billData.steps[billData.steps.length - 1]; + const isSameMembers = JSON.stringify(lastStep.members.map(m => m.id).sort()) === JSON.stringify(members.sort()); + + if (isSameMembers) { + lastStep.bills.push(newBill); + } else { + billData.steps.push({ + bills: [newBill], + members: members.map(id => ({id, name: `Member ${id}`})), + }); + } (billDetailsData as unknown as BillDetailsData)[newBill.id.toString()] = { billDetails: members.map((id, index) => ({ id, - memberName: `Member ${id}`, + memberName: + billData.steps.flatMap(step => step.members).find(member => member.id === id)?.name || `Member ${id}`, price: (Math.floor(price / members.length) + (index < price % members.length ? 1 : 0)).toString(), })), }; diff --git a/client/src/pages/AddBillFunnel/AddBillFunnel.tsx b/client/src/pages/AddBillFunnel/AddBillFunnel.tsx new file mode 100644 index 000000000..a98b60919 --- /dev/null +++ b/client/src/pages/AddBillFunnel/AddBillFunnel.tsx @@ -0,0 +1,34 @@ +import {Member} from 'types/serviceType'; + +import useAddBillFunnel from '@hooks/useAddBillFunnel'; + +import {Back, MainLayout, TopNav} from '@components/Design'; + +import PriceStep from './steps/PriceStep'; +import {TitleStep} from './steps/TitleStep'; +import MembersStep from './steps/MembersStep'; + +export interface BillInfo { + price: string; + title: string; + members: Member[]; +} + +const AddBillFunnel = () => { + const {step, setStep, billInfo, setBillInfo, currentMembers} = useAddBillFunnel(); + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + {step === 'price' && <PriceStep billInfo={billInfo} setBillInfo={setBillInfo} setStep={setStep} />} + {step === 'title' && <TitleStep billInfo={billInfo} setBillInfo={setBillInfo} setStep={setStep} />} + {step === 'members' && ( + <MembersStep billInfo={billInfo} setBillInfo={setBillInfo} currentMembers={currentMembers} setStep={setStep} /> + )} + </MainLayout> + ); +}; + +export default AddBillFunnel; diff --git a/client/src/pages/AddBillFunnel/steps/MembersStep.tsx b/client/src/pages/AddBillFunnel/steps/MembersStep.tsx new file mode 100644 index 000000000..5d78083a9 --- /dev/null +++ b/client/src/pages/AddBillFunnel/steps/MembersStep.tsx @@ -0,0 +1,102 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; +import ChipButton from '@components/Design/components/ChipButton/ChipButton'; +import {Member} from 'types/serviceType'; + +import useMembersStep from '@hooks/useMembersStep'; +import {BillStep} from '@hooks/useAddBillFunnel'; + +import {FixedButton, Flex, LabelInput, Text} from '@components/Design'; + +import {BillInfo} from '../AddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>; + setStep: React.Dispatch<React.SetStateAction<BillStep>>; + currentMembers: Member[]; +} + +const MembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => { + const { + errorMessage, + nameInput, + handleNameInputChange, + handleNameInputEnter, + isPendingPostBill, + isPendingPostMembers, + canSubmitMembers, + handlePostBill, + handlePrevStep, + } = useMembersStep({billInfo, setBillInfo, currentMembers, setStep}); + + return ( + <> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text={`${billInfo.title}에`} /> + <Top.Line text="참여한 사람은 누구인가요?" emphasize={['참여한 사람']} /> + </Top> + <LabelInput + labelText="이름" + errorText={errorMessage ?? ''} + value={nameInput} + type="text" + placeholder="ex) 박행댕" + onChange={handleNameInputChange} + isError={!!errorMessage} + autoFocus + onKeyDown={handleNameInputEnter} + /> + <div + css={css` + display: flex; + flex-direction: column; + gap: 0.375rem; + `} + > + <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> + <Text size="caption" textColor="gray"> + 참여 인원 + </Text> + <Text size="caption" textColor="gray">{`총 ${billInfo.members.length}명`}</Text> + </Flex> + <div + css={css` + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + `} + > + {billInfo.members.map(member => ( + <ChipButton + key={member.name} + color="gray" + text={member.name} + onClick={() => setBillInfo(prev => ({...prev, members: prev.members.filter(name => name !== member)}))} + /> + ))} + </div> + </div> + </div> + <FixedButton + variants={isPendingPostBill || isPendingPostMembers ? 'loading' : 'primary'} + disabled={!canSubmitMembers} + onClick={handlePostBill} + onBackClick={handlePrevStep} + > + 추가완료 + </FixedButton> + </> + ); +}; + +export default MembersStep; diff --git a/client/src/pages/AddBillFunnel/steps/PriceStep.tsx b/client/src/pages/AddBillFunnel/steps/PriceStep.tsx new file mode 100644 index 000000000..260fb5b4a --- /dev/null +++ b/client/src/pages/AddBillFunnel/steps/PriceStep.tsx @@ -0,0 +1,62 @@ +import {css} from '@emotion/react'; +import {useNavigate} from 'react-router-dom'; + +import AmountInput from '@components/AmountInput/AmountInput'; +import NumberKeyboard from '@components/Design/components/NumberKeyboard/NumberKeyboard'; +import Top from '@components/Design/components/Top/Top'; + +import usePriceStep from '@hooks/usePriceStep'; +import {BillStep} from '@hooks/useAddBillFunnel'; + +import {FixedButton} from '@components/Design'; + +import {BillInfo} from '../AddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>; + setStep: React.Dispatch<React.SetStateAction<BillStep>>; +} + +const PriceStep = ({billInfo, setBillInfo, setStep}: Props) => { + const navigate = useNavigate(); + const {handleNumberKeyboardChange, handleNextStep} = usePriceStep({setBillInfo, setStep}); + + return ( + <> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="사용한 금액은 얼마인가요?" emphasize={['사용한 금액']} /> + </Top> + <AmountInput value={billInfo.price} /> + </div> + <div + css={css` + position: fixed; + width: 100%; + max-width: 768px; + bottom: 6.25rem; + `} + > + <NumberKeyboard + type="amount" + maxNumber={10000000} + initialValue={billInfo.price} + onChange={handleNumberKeyboardChange} + /> + </div> + <FixedButton disabled={!billInfo.price} onClick={handleNextStep} onBackClick={() => navigate(-1)}> + 다음으로 + </FixedButton> + </> + ); +}; + +export default PriceStep; diff --git a/client/src/pages/AddBillFunnel/steps/TitleStep.tsx b/client/src/pages/AddBillFunnel/steps/TitleStep.tsx new file mode 100644 index 000000000..eb910991f --- /dev/null +++ b/client/src/pages/AddBillFunnel/steps/TitleStep.tsx @@ -0,0 +1,63 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import useTitleStep from '@hooks/useTitleStep'; +import {BillStep} from '@hooks/useAddBillFunnel'; + +import {FixedButton, LabelInput} from '@components/Design'; + +import {BillInfo} from '../AddBillFunnel'; + +interface Props { + billInfo: BillInfo; + setBillInfo: React.Dispatch<React.SetStateAction<BillInfo>>; + setStep: React.Dispatch<React.SetStateAction<BillStep>>; +} + +export const TitleStep = ({billInfo, setBillInfo, setStep}: Props) => { + const { + errorMessage, + handleTitleInputChange, + handleTitleInputEnter, + canSubmitTitleInput, + handlePrevStep, + handleNextStep, + } = useTitleStep({ + billInfo, + setBillInfo, + setStep, + }); + + return ( + <> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text={`${billInfo.price}원을`} /> + <Top.Line text="어떤 곳에서 사용했나요??" emphasize={['어떤 곳']} /> + </Top> + <LabelInput + labelText="결제 내용" + errorText={errorMessage ?? ''} + value={billInfo.title} + type="text" + placeholder="ex) 행동대장 포차" + onChange={handleTitleInputChange} + isError={!!errorMessage} + autoFocus + onKeyDown={handleTitleInputEnter} + /> + </div> + <FixedButton disabled={!canSubmitTitleInput} onClick={handleNextStep} onBackClick={handlePrevStep}> + 다음으로 + </FixedButton> + </> + ); +}; diff --git a/client/src/pages/BillPage/AddBillFunnel.tsx b/client/src/pages/BillPage/AddBillFunnel.tsx deleted file mode 100644 index d8ff14845..000000000 --- a/client/src/pages/BillPage/AddBillFunnel.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import {css} from '@emotion/react'; -import {useEffect, useState} from 'react'; -import {useNavigate} from 'react-router-dom'; - -import NumberKeyboard from '@components/Design/components/NumberKeyboard/NumberKeyboard'; -import useRequestGetCurrentMembers from '@hooks/queries/member/useRequestGetCurrentMembers'; -import Top from '@components/Design/components/Top/Top'; -import ChipButton from '@components/Design/components/ChipButton/ChipButton'; -import AmountInput from '@components/AmountInput/AmountInput'; - -import {Back, FixedButton, Flex, LabelInput, MainLayout, Text, TopNav} from '@components/Design'; - -type BillStep = 'title' | 'price' | 'members'; - -interface BillInfo { - price: string; - title: string; - members: string[]; -} - -const AddBillFunnel = () => { - const {currentMembers} = useRequestGetCurrentMembers(); - const [step, setStep] = useState<BillStep>('price'); - const [billInfo, setBillInfo] = useState<BillInfo>({ - price: '', - title: '', - members: [], - }); - const [errorMessage, setErrorMessage] = useState(''); - const [nameInput, setNameInput] = useState(''); - const navigate = useNavigate(); - - useEffect(() => { - currentMembers && setBillInfo(prev => ({...prev, members: currentMembers.map(member => member.name)})); - }, [currentMembers]); - - const handleNumberKeyboardChange = (value: string) => { - setBillInfo(prev => ({...prev, price: value || prev.price})); - }; - - const handleTitleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => { - setBillInfo(prev => ({...prev, title: event.target.value})); - }; - - const handleTitleInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { - if (event.nativeEvent.isComposing) { - return; - } - if (event.key === 'Enter') { - event.preventDefault(); - setStep('members'); - } - }; - - const handleNameInputChange = (event: React.ChangeEvent<HTMLInputElement>) => setNameInput(event.target.value); - - const handleNameInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { - if (event.nativeEvent.isComposing) { - return; - } - if (event.key === 'Enter') { - console.log(nameInput); - event.preventDefault(); - if (!billInfo.members.includes(nameInput)) { - setBillInfo(prev => ({...prev, members: [...prev.members, nameInput]})); - } - setNameInput(''); - } - }; - - const setStepPrice = () => { - setStep('price'); - }; - - const setStepTitle = () => { - setStep('title'); - }; - - const setStepMembers = () => { - setStep('members'); - }; - - const priceStep = () => ( - <> - <div - css={css` - display: flex; - flex-direction: column; - gap: 1rem; - padding: 1rem; - `} - > - <Top> - <Top.Line text="사용한 금액은 얼마인가요?" emphasize={['사용한 금액']} /> - </Top> - <AmountInput value={billInfo.price} /> - </div> - <div - css={css` - position: fixed; - width: 100%; - max-width: 768px; - bottom: 6.25rem; - `} - > - <NumberKeyboard type="amount" maxNumber={10000000} onChange={handleNumberKeyboardChange} /> - </div> - <FixedButton disabled={!billInfo.price} onClick={setStepTitle} onBackClick={() => navigate(-1)}> - 다음으로 - </FixedButton> - </> - ); - - const titleStep = () => ( - <> - <div - css={css` - display: flex; - flex-direction: column; - gap: 1rem; - padding: 1rem; - `} - > - <Top> - <Top.Line text={`${billInfo.price}원을`} /> - <Top.Line text="어떤 곳에서 사용했나요??" emphasize={['어떤 곳']} /> - </Top> - <LabelInput - labelText="결제 내용" - errorText={errorMessage ?? ''} - value={billInfo.title} - type="text" - placeholder="행동대장 포차" - onChange={handleTitleInputChange} - isError={!!errorMessage} - autoFocus - onKeyDown={handleTitleInputEnter} - /> - </div> - <FixedButton disabled={!billInfo.title} onClick={setStepMembers} onBackClick={setStepPrice}> - 다음으로 - </FixedButton> - </> - ); - - const membersStep = () => ( - <> - <div - css={css` - display: flex; - flex-direction: column; - gap: 1rem; - padding: 1rem; - `} - > - <Top> - <Top.Line text={`${billInfo.title}에`} /> - <Top.Line text="참여한 사람은 누구인가요?" emphasize={['참여한 사람']} /> - </Top> - <LabelInput - labelText="이름" - errorText={errorMessage ?? ''} - value={nameInput} - type="text" - placeholder="박행댕" - onChange={handleNameInputChange} - isError={!!errorMessage} - autoFocus - onKeyDown={handleNameInputEnter} - /> - <div - css={css` - display: flex; - flex-direction: column; - gap: 0.375rem; - `} - > - <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> - <Text size="caption" textColor="gray"> - 참여 인원 - </Text> - <Text size="caption" textColor="gray">{`총 ${billInfo.members.length}명`}</Text> - </Flex> - <div - css={css` - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - `} - > - {billInfo.members.map(member => ( - <ChipButton - key={member} - color="gray" - text={member} - onClick={() => setBillInfo(prev => ({...prev, members: prev.members.filter(name => name !== member)}))} - /> - ))} - </div> - </div> - </div> - <FixedButton disabled={!billInfo.title} onClick={setStepMembers} onBackClick={setStepTitle}> - 추가완료 - </FixedButton> - </> - ); - - return ( - <MainLayout backgroundColor="white"> - <TopNav> - <Back /> - </TopNav> - {step === 'price' && priceStep()} - {step === 'title' && titleStep()} - {step === 'members' && membersStep()} - </MainLayout> - ); -}; - -export default AddBillFunnel; diff --git a/client/src/router.tsx b/client/src/router.tsx index 01dc4d53e..0a1372829 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -1,11 +1,11 @@ import {createBrowserRouter} from 'react-router-dom'; +import AddBillFunnel from '@pages/AddBillFunnel/AddBillFunnel'; import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; import Account from '@pages/AccountPage/Account'; -import AddBillFunnel from '@pages/BillPage/AddBillFunnel'; import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; import {MainPage} from '@pages/MainPage'; diff --git a/client/src/utils/validate/validatePurchase.ts b/client/src/utils/validate/validatePurchase.ts deleted file mode 100644 index 9915ce8b7..000000000 --- a/client/src/utils/validate/validatePurchase.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type {Bill} from 'types/serviceType'; - -import {ERROR_MESSAGE} from '@constants/errorMessage'; -import RULE from '@constants/rule'; -import REGEXP from '@constants/regExp'; - -import {ValidateResult} from './type'; - -const validatePurchase = (inputPair: Bill): ValidateResult => { - const {title, price} = inputPair; - let errorMessage: string | null = null; - - const errorInfo = { - price: false, - title: false, - }; - - const validatePrice = () => { - if (price > RULE.maxPrice) { - errorMessage = ERROR_MESSAGE.purchasePrice; - errorInfo.price = true; - return false; - } - - errorInfo.price = false; - return true; - }; - - const validateTitle = () => { - if (!REGEXP.purchaseTitle.test(title)) { - errorMessage = ERROR_MESSAGE.purchaseTitle; - errorInfo.title = true; - return false; - } - - errorInfo.title = false; - return true; - }; - - if (validatePrice() && validateTitle()) { - return {isValid: true, errorMessage: null}; - } - - return {isValid: false, errorMessage, errorInfo}; -}; - -export default validatePurchase; From 1bfc10e20f9a9b30d8dcc0f1aa5b20b87f3022ed Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:47:37 +0900 Subject: [PATCH 241/273] =?UTF-8?q?feat:=20=ED=96=89=EC=82=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20=ED=8D=BC?= =?UTF-8?q?=EB=84=90=20=EB=B0=A9=EC=8B=9D=20=EC=A0=81=EC=9A=A9=20(#591)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 행사 생성 페이지의 path 수정 * fix: 컴포넌트 구현이 바뀜에 따라 다른 컴포넌트를 사용해 제목을 그리도록 수정 * feat: 행사 생성 페이지를 퍼널 방식을 이용해 렌더링 하도록 수정 * feat: 퍼널 구조에서 사용되는 공통적인 로직과 컴포넌트를 위한 useFunnel 훅 구현 * rename: 퍼널 방식으로 변경됨에 따른 Page -> Step 으로의 이름 변경 * feat: 행사 생성 퍼널에서 여러 step에 걸쳐 사용되는 상태를 선언해 내려주는 useCreateEventData 훅 구현 * feat: 행사 생성 퍼널을 router에서 호출 * feat: 뒤로가기 버튼인 Back에 onClick인자가 주어지면 그 함수를 사용하고 주어지지 않으면 -1로 뒤로가도록 함 * feat: Funnel 컴포넌트에서 현재의 step을 위한 Step 컴포넌트를 찾지 못했다면 에러를 던지도록 함 * feat: 응답이 성공해야만 다음 로직을 실행할 수 있도록 mutateAsync 사용해 순서 보장 * feat: 퍼널 구조에서 사용되는 공통적인 로직과 컴포넌트를 위한 useFunnel 훅 구현 * style: return 위 개행 추가 * style: 가독성을 위해 Step간 개행을 넣음 * test: 퍼널이 도입되어 행사 생성 과정에서 url이 변경되지 않기 때문에 url이 올바르게 변경되었는지 판단하는 라인을 제거 * test: 행사 생성 url이 바뀐 것을 cypress에도 적용 * feat: 불필요해진 행사 생성 완료 path 제거 * test: url을 수정된 값으로 변경 * test: 테스트 임시 비활성화 * feat: 조건부로 기본 이벤트 동작을 막던 것에서 조건 제거 * feat: 불필요한 함수 제거 * feat: 키다운 핸들러를 없애 onSubmit으로 통합 * test: 주석처리했던 테스트 복구 --- client/cypress/e2e/createEvent.cy.ts | 16 ++--- client/cypress/support/commands.ts | 4 +- .../Design/components/TopNav/Back.tsx | 9 ++- client/src/constants/routerUrls.ts | 6 +- .../queries/event/useRequestPostEvent.ts | 5 +- client/src/hooks/useCreateEventData.tsx | 17 +++++ client/src/hooks/useFunnel.tsx | 58 +++++++++++++++ ...ventNamePage.ts => useSetEventNameStep.ts} | 6 +- client/src/hooks/useSetEventPasswordPage.ts | 65 ----------------- client/src/hooks/useSetEventPasswordStep.ts | 72 +++++++++++++++++++ ...ntPage.tsx => CompleteCreateEventStep.tsx} | 14 ++-- .../CreateEventPage/CreateEventFunnel.tsx | 56 +++++++++++++++ .../CreateEventPage/SetEventNamePage.tsx | 69 ------------------ .../CreateEventPage/SetEventNameStep.tsx | 56 +++++++++++++++ .../CreateEventPage/SetEventPasswordPage.tsx | 61 ---------------- .../CreateEventPage/SetEventPasswordStep.tsx | 61 ++++++++++++++++ client/src/pages/CreateEventPage/index.ts | 6 +- client/src/pages/ErrorPage/ErrorPage.tsx | 8 ++- client/src/pages/MainPage/Nav/Nav.tsx | 2 +- .../pages/MainPage/Section/MainSection.tsx | 2 +- client/src/router.tsx | 19 ++--- .../src/utils/validate/validateEventName.ts | 1 + 22 files changed, 367 insertions(+), 246 deletions(-) create mode 100644 client/src/hooks/useCreateEventData.tsx create mode 100644 client/src/hooks/useFunnel.tsx rename client/src/hooks/{useSetEventNamePage.ts => useSetEventNameStep.ts} (82%) delete mode 100644 client/src/hooks/useSetEventPasswordPage.ts create mode 100644 client/src/hooks/useSetEventPasswordStep.ts rename client/src/pages/CreateEventPage/{CompleteCreateEventPage.tsx => CompleteCreateEventStep.tsx} (78%) create mode 100644 client/src/pages/CreateEventPage/CreateEventFunnel.tsx delete mode 100644 client/src/pages/CreateEventPage/SetEventNamePage.tsx create mode 100644 client/src/pages/CreateEventPage/SetEventNameStep.tsx delete mode 100644 client/src/pages/CreateEventPage/SetEventPasswordPage.tsx create mode 100644 client/src/pages/CreateEventPage/SetEventPasswordStep.tsx diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts index 5de7f4592..edd4ddc6d 100644 --- a/client/cypress/e2e/createEvent.cy.ts +++ b/client/cypress/e2e/createEvent.cy.ts @@ -1,4 +1,6 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; import CONSTANTS from '../constants/constants'; + beforeEach(() => { cy.blockSentry(); cy.blockKakao(); @@ -8,18 +10,17 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl it('랜딩페이지에서 "행사 생성하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { cy.visit('/'); cy.get('header').find('button').click(); - cy.url().should('include', '/event/create/name'); + cy.url().should('include', ROUTER_URLS.createEvent); }); context('행사 이름 입력 페이지', () => { beforeEach(() => { - cy.visit('/event/create/name'); + cy.visit(ROUTER_URLS.createEvent); }); it('행사 이름 입력 페이지에서 input이 포커싱 되어 있고, "다음" 버튼이 비활성화 되어 있어야 한다.', () => { cy.get('input').focused(); cy.get('button').contains('다음').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/name'); }); it('행사 이름이 1자 이상 입력된 경우 "다음" 버튼이 활성화 되고, 값이 없는 경우 "다음" 버튼이 비활성화 되어야 한다.', () => { @@ -28,13 +29,14 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.get('input').clear(); cy.get('input').should('have.value', ''); cy.get('button').contains('다음').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/name'); }); it('행사 이름을 입력한 후 "다음" 버튼을 누르면 행사 비밀번호 설정 화면으로 이동해야 한다.', () => { cy.get('input').type(CONSTANTS.eventName); cy.get('button').contains('다음').click(); - cy.url().should('include', '/event/create/password'); + + // 다음 버튼을 클릭하면 /create/event 경로가 아니라 /create/event/?로 가네요.. 그래서 일단 제거함. + cy.contains('비밀번호').should('exist'); }); }); @@ -46,7 +48,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl it('행사 비밀번호 입력 페이지에서 input이 포커싱 되어 있고, "행동 개시!" 버튼이 비활성화 되어 있어야 한다.', () => { cy.get('input').focused(); cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/password'); }); it('행사 비밀번호에 숫자가 아닌 입력을 할 경우 값이 입력되지 않아야 한다.', () => { @@ -65,7 +66,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.get('input').clear(); cy.get('input').should('have.value', ''); cy.get('button').contains('행동 개시!').should('have.attr', 'disabled'); - cy.url().should('include', '/event/create/password'); }); it('행사 비밀번호을 입력한 후 "행동 개시!" 버튼을 누르면 행사 생성 완료 화면으로 이동해야 한다.', () => { @@ -73,8 +73,6 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.interceptAPI({type: 'getEventName', statusCode: 200}); cy.get('input').type(CONSTANTS.eventPassword); cy.get('button').contains('행동 개시!').click(); - - cy.url().should('include', '/event/create/complete'); }); }); }); diff --git a/client/cypress/support/commands.ts b/client/cypress/support/commands.ts index 70c8524ea..6ef75b4dc 100644 --- a/client/cypress/support/commands.ts +++ b/client/cypress/support/commands.ts @@ -1,3 +1,4 @@ +import {ROUTER_URLS} from '@constants/routerUrls'; import CONSTANTS from '../constants/constants'; type APIType = 'sentry' | 'postEvent' | 'getEventName'; @@ -46,10 +47,9 @@ Cypress.Commands.add('interceptAPI', ({type, delay = 0, statusCode = 200}: Inter }); Cypress.Commands.add('createEventName', (eventName: string) => { - cy.visit('/event/create/name'); + cy.visit(ROUTER_URLS.createEvent); cy.get('input').type(eventName); cy.get('button').contains('다음').click(); - cy.url().should('include', '/event/create/password'); }); declare global { diff --git a/client/src/components/Design/components/TopNav/Back.tsx b/client/src/components/Design/components/TopNav/Back.tsx index 73065ebce..5bbd83618 100644 --- a/client/src/components/Design/components/TopNav/Back.tsx +++ b/client/src/components/Design/components/TopNav/Back.tsx @@ -1,14 +1,17 @@ /** @jsxImportSource @emotion/react */ -import React from 'react'; import {useNavigate} from 'react-router-dom'; import TextButton from '@HDcomponents/TextButton/TextButton'; -function Back() { +type BackProps = { + onClick?: () => void; +}; + +function Back({onClick}: BackProps) { const navigate = useNavigate(); return ( - <TextButton onClick={() => navigate(-1)} textSize="bodyBold" textColor="gray"> + <TextButton onClick={() => (onClick ? onClick() : navigate(-1))} textSize="bodyBold" textColor="gray"> 뒤로가기 </TextButton> ); diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index 8cd486d9b..de3cc5946 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -1,9 +1,7 @@ export const ROUTER_URLS = { main: '/', - eventCreateName: '/event/create/name', - eventCreatePassword: '/event/create/password', - eventCreateComplete: '/event/create/complete', - event: '/event', // TODO: (@weadie) baseurl을 어떻게 관리할 것인가? + createEvent: '/event/create', + event: '/event', eventLogin: '/event/:eventId/login', eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', diff --git a/client/src/hooks/queries/event/useRequestPostEvent.ts b/client/src/hooks/queries/event/useRequestPostEvent.ts index ec4c6f2b0..d59f6b913 100644 --- a/client/src/hooks/queries/event/useRequestPostEvent.ts +++ b/client/src/hooks/queries/event/useRequestPostEvent.ts @@ -3,12 +3,13 @@ import {useMutation} from '@tanstack/react-query'; import {RequestPostEvent, requestPostEvent} from '@apis/request/event'; const useRequestPostEvent = () => { - const {mutate, ...rest} = useMutation({ + const {mutate, mutateAsync, ...rest} = useMutation({ mutationFn: ({eventName, password}: RequestPostEvent) => requestPostEvent({eventName, password}), }); + // 실행 순서를 await으로 보장하기 위해 mutateAsync 사용 return { - postEvent: mutate, + postEvent: mutateAsync, isPostEventPending: rest.isPending, ...rest, }; diff --git a/client/src/hooks/useCreateEventData.tsx b/client/src/hooks/useCreateEventData.tsx new file mode 100644 index 000000000..fed21d8ae --- /dev/null +++ b/client/src/hooks/useCreateEventData.tsx @@ -0,0 +1,17 @@ +import {useState} from 'react'; + +import useSetEventNameStep from './useSetEventNameStep'; + +// 행사 생성 페이지에서 여러 스텝에 걸쳐 사용되는 상태를 선언해 내려주는 용도의 훅입니다. +const useCreateEventData = () => { + const eventNameProps = useSetEventNameStep(); + const [eventToken, setEventToken] = useState(''); + + return { + eventNameProps, + eventToken, + setEventToken, + }; +}; + +export default useCreateEventData; diff --git a/client/src/hooks/useFunnel.tsx b/client/src/hooks/useFunnel.tsx new file mode 100644 index 000000000..196bb37b4 --- /dev/null +++ b/client/src/hooks/useFunnel.tsx @@ -0,0 +1,58 @@ +import {useState} from 'react'; + +type UseFunnel = { + defaultStep: string; + stepList: string[]; +}; + +type StepProps = { + children: React.ReactNode; + name: string; +}; + +type FunnelProps = { + children: React.ReactElement<StepProps>[]; +}; + +const useFunnel = ({defaultStep, stepList}: UseFunnel) => { + const [step, setStep] = useState(defaultStep); + + const moveToNextStep = () => { + const curStepIndex = stepList.indexOf(step); + + if (curStepIndex === stepList.length - 1) return; + + setStep(stepList[curStepIndex + 1]); + }; + + const moveToPrevStep = () => { + const curStepIndex = stepList.indexOf(step); + + if (curStepIndex === 0) return; + + setStep(stepList[curStepIndex - 1]); + }; + + const Step = (stepProps: StepProps) => { + return <>{stepProps.children}</>; + }; + + const Funnel = ({children}: FunnelProps) => { + const targetStep = children.find(curStep => curStep.props.name === step); + + if (!targetStep) + throw new Error(`현재 ${step} 단계에 보여줄 컴포넌트가 존재하지 않습니다. Step 컴포넌트를 호출해 사용해주세요.`); + + return <>{targetStep}</>; + }; + + return { + Step, + step, + Funnel, + moveToNextStep, + moveToPrevStep, + }; +}; + +export default useFunnel; diff --git a/client/src/hooks/useSetEventNamePage.ts b/client/src/hooks/useSetEventNameStep.ts similarity index 82% rename from client/src/hooks/useSetEventNamePage.ts rename to client/src/hooks/useSetEventNameStep.ts index f5b5bce12..cd2a35302 100644 --- a/client/src/hooks/useSetEventNamePage.ts +++ b/client/src/hooks/useSetEventNameStep.ts @@ -2,7 +2,9 @@ import {useState} from 'react'; import validateEventName from '@utils/validate/validateEventName'; -const useSetEventNamePage = () => { +export type UseSetEventNameStepReturnType = ReturnType<typeof useSetEventNameStep>; + +const useSetEventNameStep = () => { const [eventName, setEventName] = useState(''); const [errorMessage, setErrorMessage] = useState<string | null>(null); const [canSubmit, setCanSubmit] = useState(false); @@ -29,4 +31,4 @@ const useSetEventNamePage = () => { }; }; -export default useSetEventNamePage; +export default useSetEventNameStep; diff --git a/client/src/hooks/useSetEventPasswordPage.ts b/client/src/hooks/useSetEventPasswordPage.ts deleted file mode 100644 index ba8549258..000000000 --- a/client/src/hooks/useSetEventPasswordPage.ts +++ /dev/null @@ -1,65 +0,0 @@ -import {useEffect, useState} from 'react'; -import {useLocation, useNavigate} from 'react-router-dom'; - -import validateEventPassword from '@utils/validate/validateEventPassword'; - -import {ROUTER_URLS} from '@constants/routerUrls'; -import RULE from '@constants/rule'; - -import useRequestPostEvent from './queries/event/useRequestPostEvent'; - -const useSetEventPasswordPage = () => { - const [eventName, setEventName] = useState(''); - const [password, setPassword] = useState(''); - const [errorMessage, setErrorMessage] = useState(''); - const [canSubmit, setCanSubmit] = useState(false); - const navigate = useNavigate(); - const location = useLocation(); - const {postEvent, isPostEventPending} = useRequestPostEvent(); - - useEffect(() => { - if (!location.state) { - navigate(ROUTER_URLS.main); - } else { - setEventName(location.state.eventName); - } - }, []); - - const submitPassword = async (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - - onSuccess(); - }; - - const onSuccess = () => { - postEvent( - {eventName, password: String(password).padStart(4, '0')}, - { - onSuccess: data => { - navigate(`${ROUTER_URLS.eventCreateComplete}?${new URLSearchParams({eventId: data.eventId})}`, { - replace: true, - }); - }, - }, - ); - }; - - const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { - const newValue = event.target.value; - const validation = validateEventPassword(newValue); - - setCanSubmit(newValue.length === RULE.maxEventPasswordLength); - - if (validation.isValid) { - setPassword(newValue); - setErrorMessage(''); - } else { - event.target.value = password; - setErrorMessage(validation.errorMessage ?? ''); - } - }; - - return {submitPassword, errorMessage, password, handleChange, onSuccess, canSubmit, isPostEventPending}; -}; - -export default useSetEventPasswordPage; diff --git a/client/src/hooks/useSetEventPasswordStep.ts b/client/src/hooks/useSetEventPasswordStep.ts new file mode 100644 index 000000000..5705be855 --- /dev/null +++ b/client/src/hooks/useSetEventPasswordStep.ts @@ -0,0 +1,72 @@ +import {useState} from 'react'; +import {useNavigate} from 'react-router-dom'; + +import validateEventPassword from '@utils/validate/validateEventPassword'; + +import RULE from '@constants/rule'; + +import useRequestPostEvent from './queries/event/useRequestPostEvent'; + +export type UseSetEventPasswordStepReturnType = ReturnType<typeof useSetEventPasswordStep>; + +const useSetEventPasswordStep = () => { + const [password, setPassword] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + const [canSubmit, setCanSubmit] = useState(false); + const {postEvent: requestPostEvent, isPostEventPending} = useRequestPostEvent(); + + const submitDataForPostEvent = async ({ + event, + eventName, + setEventToken, + }: { + event: React.FormEvent<HTMLFormElement>; + eventName: string; + setEventToken: (eventToken: string) => void; + }) => { + event.preventDefault(); + + await postEvent(eventName, setEventToken); + }; + + const getPasswordWithPad = () => { + return String(password).padStart(4, '0'); + }; + + const postEvent = async (eventName: string, updateEventToken: (eventToken: string) => void) => { + await requestPostEvent( + {eventName, password: getPasswordWithPad()}, + { + onSuccess: ({eventId}) => { + updateEventToken(eventId); + }, + }, + ); + }; + + const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const newValue = event.target.value; + const validation = validateEventPassword(newValue); + + setCanSubmit(newValue.length === RULE.maxEventPasswordLength); + + if (validation.isValid) { + setPassword(newValue); + setErrorMessage(''); + } else { + event.target.value = password; + setErrorMessage(validation.errorMessage ?? ''); + } + }; + + return { + submitDataForPostEvent, + errorMessage, + handleChange, + canSubmit, + isPostEventPending, + password, + }; +}; + +export default useSetEventPasswordStep; diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx similarity index 78% rename from client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx rename to client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx index 385d8c968..a2e19b5f7 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventPage.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx @@ -8,12 +8,12 @@ import {FixedButton, MainLayout, Title, TopNav} from '@HDesign/index'; import {ROUTER_URLS} from '@constants/routerUrls'; -const CompleteCreateEventPage = () => { - const navigate = useNavigate(); - const location = useLocation(); +type CompleteCreateEventStepProps = { + eventToken: string; +}; - const params = new URLSearchParams(location.search); - const eventId = params.get('eventId'); +const CompleteCreateEventStep = ({eventToken}: CompleteCreateEventStepProps) => { + const navigate = useNavigate(); return ( <MainLayout backgroundColor="white"> @@ -32,9 +32,9 @@ const CompleteCreateEventPage = () => { </Top> <RunningDog /> </div> - <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventId}/admin`)}>관리 페이지로 이동</FixedButton> + <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventToken}/admin`)}>관리 페이지로 이동</FixedButton> </MainLayout> ); }; -export default CompleteCreateEventPage; +export default CompleteCreateEventStep; diff --git a/client/src/pages/CreateEventPage/CreateEventFunnel.tsx b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx new file mode 100644 index 000000000..d9347a389 --- /dev/null +++ b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx @@ -0,0 +1,56 @@ +import {useNavigate} from 'react-router-dom'; + +import useFunnel from '@hooks/useFunnel'; +import useCreateEventData from '@hooks/useCreateEventData'; + +import {Back, MainLayout, TopNav} from '@components/Design'; + +import SetEventNameStep from './SetEventNameStep'; +import SetEventPasswordStep from './SetEventPasswordStep'; +import CompleteCreateEventStep from './CompleteCreateEventStep'; + +type CreateEventStep = 'eventName' | 'eventPassword' | 'complete'; +const STEP_SEQUENCE: CreateEventStep[] = ['eventName', 'eventPassword', 'complete']; + +const CreateEventFunnel = () => { + const navigate = useNavigate(); + const {moveToNextStep, moveToPrevStep, Step, Funnel, step} = useFunnel({ + defaultStep: 'eventName', + stepList: STEP_SEQUENCE, + }); + + const {eventNameProps, eventToken, setEventToken} = useCreateEventData(); + + const handleBack = () => { + if (step === STEP_SEQUENCE[0]) { + navigate('/'); + } else { + moveToPrevStep(); + } + }; + + return ( + <MainLayout backgroundColor="white"> + <TopNav>{step !== STEP_SEQUENCE[STEP_SEQUENCE.length - 1] && <Back onClick={handleBack} />}</TopNav> + <Funnel> + <Step name="eventName"> + <SetEventNameStep moveToNextStep={moveToNextStep} {...eventNameProps} /> + </Step> + + <Step name="eventPassword"> + <SetEventPasswordStep + moveToNextStep={moveToNextStep} + eventName={eventNameProps.eventName} + setEventToken={setEventToken} + /> + </Step> + + <Step name="complete"> + <CompleteCreateEventStep eventToken={eventToken} /> + </Step> + </Funnel> + </MainLayout> + ); +}; + +export default CreateEventFunnel; diff --git a/client/src/pages/CreateEventPage/SetEventNamePage.tsx b/client/src/pages/CreateEventPage/SetEventNamePage.tsx deleted file mode 100644 index 1f7d0acf6..000000000 --- a/client/src/pages/CreateEventPage/SetEventNamePage.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import {useNavigate} from 'react-router-dom'; -import {css} from '@emotion/react'; - -import Top from '@components/Design/components/Top/Top'; - -import useSetEventNamePage from '@hooks/useSetEventNamePage'; - -import {FixedButton, MainLayout, LabelInput, TopNav, Back} from '@HDesign/index'; - -import {ROUTER_URLS} from '@constants/routerUrls'; - -const SetEventNamePage = () => { - const navigate = useNavigate(); - const {eventName, errorMessage, canSubmit, handleEventNameChange} = useSetEventNamePage(); - - const submitEventName = (event: React.FormEvent<HTMLFormElement>) => { - event.preventDefault(); - - onSuccessSubmint(); - }; - - const onSuccessSubmint = () => { - navigate(ROUTER_URLS.eventCreatePassword, {state: {eventName}}); - }; - - const handleGoNextStep = (event: React.KeyboardEvent<HTMLInputElement>) => { - if (event.key === 'Enter') { - onSuccessSubmint(); - } - }; - - return ( - <MainLayout backgroundColor="white"> - <TopNav> - <Back /> - </TopNav> - <div - css={css` - display: flex; - flex-direction: column; - gap: 1rem; - padding: 1rem; - `} - > - <Top> - <Top.Line text="정산을 시작하려는" /> - <Top.Line text="행사의 이름은 무엇인가요?" emphasize={['행사의 이름']} /> - </Top> - - <form onSubmit={submitEventName}> - <LabelInput - labelText="행사 이름" - errorText={errorMessage ?? ''} - value={eventName} - type="text" - placeholder="행동대장 야유회" - onChange={handleEventNameChange} - isError={!!errorMessage} - autoFocus - onKeyDown={handleGoNextStep} - ></LabelInput> - <FixedButton disabled={!canSubmit}>다음</FixedButton> - </form> - </div> - </MainLayout> - ); -}; - -export default SetEventNamePage; diff --git a/client/src/pages/CreateEventPage/SetEventNameStep.tsx b/client/src/pages/CreateEventPage/SetEventNameStep.tsx new file mode 100644 index 000000000..5653038ff --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventNameStep.tsx @@ -0,0 +1,56 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import {UseSetEventNameStepReturnType} from '@hooks/useSetEventNameStep'; + +import {FixedButton, Flex, LabelInput} from '@HDesign/index'; + +type SetEventNamePageProps = UseSetEventNameStepReturnType & { + moveToNextStep: () => void; +}; + +const SetEventNameStep = ({ + eventName, + moveToNextStep, + errorMessage, + handleEventNameChange, + canSubmit, +}: SetEventNamePageProps) => { + const onSubmit = (event: React.FormEvent<HTMLFormElement>) => { + event.preventDefault(); + + moveToNextStep(); + }; + + return ( + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="정산을 시작하려는" /> + <Top.Line text="행사의 이름은 무엇인가요?" emphasize={['행사의 이름']} /> + </Top> + <form onSubmit={onSubmit}> + <LabelInput + labelText="행사 이름" + errorText={errorMessage ?? ''} + value={eventName} + type="text" + placeholder="행동대장 야유회" + onChange={handleEventNameChange} + isError={!!errorMessage} + autoFocus + ></LabelInput> + <FixedButton disabled={!canSubmit}>다음</FixedButton> + </form> + </div> + ); +}; + +export default SetEventNameStep; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx b/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx deleted file mode 100644 index 4c0b70ad2..000000000 --- a/client/src/pages/CreateEventPage/SetEventPasswordPage.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import {css} from '@emotion/react'; - -import Top from '@components/Design/components/Top/Top'; - -import useSetEventPasswordPage from '@hooks/useSetEventPasswordPage'; - -import {FixedButton, MainLayout, LabelInput, TopNav, Back} from '@HDesign/index'; - -import RULE from '@constants/rule'; - -const SetEventPasswordPage = () => { - const {submitPassword, onSuccess, errorMessage, password, handleChange, canSubmit, isPostEventPending} = - useSetEventPasswordPage(); - - const handleGoNextStep = (event: React.KeyboardEvent<HTMLInputElement>) => { - if (event.key === 'Enter') { - onSuccess(); - } - }; - - return ( - <MainLayout backgroundColor="white"> - <TopNav> - <Back /> - </TopNav> - <div - css={css` - display: flex; - flex-direction: column; - gap: 1rem; - padding: 1rem; - `} - > - <Top> - <Top.Line text="관리에 필요한 네자리 숫자" emphasize={['네자리 숫자']} /> - <Top.Line text="비밀번호는 무엇으로 할까요?" emphasize={['비밀번호']} /> - </Top> - <form onSubmit={submitPassword}> - <LabelInput - labelText="비밀번호" - errorText={errorMessage} - value={password} - type="text" - maxLength={RULE.maxEventPasswordLength} - placeholder="1234" - onChange={handleChange} - isError={!!errorMessage} - autoFocus - onKeyDown={handleGoNextStep} - /> - {/* 가상 키패드 적용 예정 */} - <FixedButton variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> - 행동 개시! - </FixedButton> - </form> - </div> - </MainLayout> - ); -}; - -export default SetEventPasswordPage; diff --git a/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx new file mode 100644 index 000000000..c11c376f2 --- /dev/null +++ b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx @@ -0,0 +1,61 @@ +import {css} from '@emotion/react'; + +import Top from '@components/Design/components/Top/Top'; + +import useSetEventPasswordStep, {UseSetEventPasswordStepReturnType} from '@hooks/useSetEventPasswordStep'; + +import {FixedButton, LabelInput} from '@HDesign/index'; + +import RULE from '@constants/rule'; + +type SetEventPasswordPageProps = { + eventName: string; + moveToNextStep: () => void; + setEventToken: (eventToken: string) => void; +}; + +const SetEventPasswordStep = ({eventName, moveToNextStep, setEventToken}: SetEventPasswordPageProps) => { + const {submitDataForPostEvent, errorMessage, password, handleChange, isPostEventPending, canSubmit} = + useSetEventPasswordStep(); + + const submit = async (event: React.FormEvent<HTMLFormElement>) => { + await submitDataForPostEvent({event, eventName, setEventToken}); + + moveToNextStep(); + }; + + return ( + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="관리에 필요한 네자리 숫자" emphasize={['네자리 숫자']} /> + <Top.Line text="비밀번호는 무엇으로 할까요?" emphasize={['비밀번호']} /> + </Top> + <form onSubmit={submit}> + <LabelInput + labelText="비밀번호" + errorText={errorMessage} + value={password} + type="text" + maxLength={RULE.maxEventPasswordLength} + placeholder="1234" + onChange={handleChange} + isError={!!errorMessage} + autoFocus + /> + {/* 가상 키패드 적용 예정 */} + <FixedButton type="submit" variants={isPostEventPending ? 'loading' : 'primary'} disabled={!canSubmit}> + 행동 개시! + </FixedButton> + </form> + </div> + ); +}; + +export default SetEventPasswordStep; diff --git a/client/src/pages/CreateEventPage/index.ts b/client/src/pages/CreateEventPage/index.ts index 6d3d6c808..8d5867dc6 100644 --- a/client/src/pages/CreateEventPage/index.ts +++ b/client/src/pages/CreateEventPage/index.ts @@ -1,3 +1,3 @@ -export {default as SetEventNamePage} from './SetEventNamePage'; -export {default as SetEventPasswordPage} from './SetEventPasswordPage'; -export {default as CompleteCreateEventPage} from './CompleteCreateEventPage'; +export {default as SetEventNameStep} from './SetEventNameStep'; +export {default as SetEventPasswordStep} from './SetEventPasswordStep'; +export {default as CompleteCreateEventStep} from './CompleteCreateEventStep'; diff --git a/client/src/pages/ErrorPage/ErrorPage.tsx b/client/src/pages/ErrorPage/ErrorPage.tsx index 84f61b2a3..92810e668 100644 --- a/client/src/pages/ErrorPage/ErrorPage.tsx +++ b/client/src/pages/ErrorPage/ErrorPage.tsx @@ -1,9 +1,13 @@ -import {MainLayout, Title} from '@HDesign/index'; +import Top from '@components/Design/components/Top/Top'; + +import {MainLayout} from '@HDesign/index'; const ErrorPage = () => { return ( <MainLayout> - <Title title="알 수 없는 오류입니다." /> + <Top> + <Top.Line text="알 수 없는 오류입니다." emphasize={['알 수 없는 오류입니다.']} /> + </Top> </MainLayout> ); }; diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index 5fd1ba3f8..2a45267cb 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -18,7 +18,7 @@ const Nav = () => { <Text size="subTitle">행동대장</Text> </div> </Flex> - <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.createEvent)}> 정산 시작하기 </Button> </header> diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx index 18f8e9208..5ae1dd8cb 100644 --- a/client/src/pages/MainPage/Section/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -40,7 +40,7 @@ const MainSection = () => { <Text css={animateWithDelay(1)} style={{textAlign: 'center'}} size="title">{`행동대장을 통해 간편하게 정산하세요 `}</Text> - <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.eventCreateName)}> + <Button css={animateWithDelay(2)} size="large" onClick={() => navigate(ROUTER_URLS.createEvent)}> 정산 시작하기 </Button> </div> diff --git a/client/src/router.tsx b/client/src/router.tsx index 0a1372829..566a07b7f 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -5,9 +5,9 @@ import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; +import CreateEventFunnel from '@pages/CreateEventPage/CreateEventFunnel'; import Account from '@pages/AccountPage/Account'; -import {CompleteCreateEventPage, SetEventNamePage, SetEventPasswordPage} from '@pages/CreateEventPage'; import {MainPage} from '@pages/MainPage'; import {EventPage} from '@pages/EventPage'; @@ -20,26 +20,15 @@ const router = createBrowserRouter([ path: '', element: <App />, children: [ - { - path: 'cookie', - element: <Account />, - }, { index: true, path: ROUTER_URLS.main, element: <MainPage />, }, { - path: ROUTER_URLS.eventCreateName, - element: <SetEventNamePage />, - }, - { - path: ROUTER_URLS.eventCreatePassword, - element: <SetEventPasswordPage />, - }, - { - path: ROUTER_URLS.eventCreateComplete, - element: <CompleteCreateEventPage />, + path: ROUTER_URLS.createEvent, + + element: <CreateEventFunnel />, }, { path: ROUTER_URLS.event, diff --git a/client/src/utils/validate/validateEventName.ts b/client/src/utils/validate/validateEventName.ts index 93f4ecef1..1c88fd4b3 100644 --- a/client/src/utils/validate/validateEventName.ts +++ b/client/src/utils/validate/validateEventName.ts @@ -7,6 +7,7 @@ const validateEventName = (name: string): ValidateResult => { if (name.length > RULE.maxEventNameLength) { return {isValid: false, errorMessage: ERROR_MESSAGE.eventName}; } + return {isValid: true, errorMessage: null}; }; From b75943ab878ac37a2e683a6c732c52be459a97fe Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:54:31 +0900 Subject: [PATCH 242/273] =?UTF-8?q?feat:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=88=98=EC=A0=95=ED=95=98=EA=B8=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#594)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: MSW 코드 수정 * feat: BillDetails component 구현 * fix: useRequestGetBillDatails hook return 수정 * fix: ListItem에 OnClick prop을 받을 수 있도록 수정 * fix: FixedButton component 수정 * feat: EditableLine component 구현 * feat: EditBillPage 구현 * test: MSW mock data 수정 * fix: 잘못 적용되어 있던 API 수정 * fix: AmountInput Component prop 및 작동방식 변경 * fix: Amount, EditableAmount css 수정 * fix: NumberKeyboard component 수정 * feat: NumberKeyboardBottomSheet component 구현 * fix: EditableLine component 수정 * fix: BillDetails component 수정 * feat: EditBillPage component 수정 및 계산 로직 추가 * fix: NumberKeyboardBottomSheet component 수정 * fix: useRequestPutBill 수정 * feat: BillDetails 클릭 시 focus 이동 스크롤 및 API 연결 * feat: Button Loading 상태 추가 * remove: 사용하지 않는 코드 삭제 * design: BillDetails 디자인 잘못된 오류 수정 * fix: Bill.price가 0인 경우 수정하지 못하도록 변경 * fix: BillDetail이 최대 금액을 넘어가는 오류 수정 * fix: 사용하지 않는 코드 제거 * fix: useNumberKeyboard Component 오류 수정 * style: lint 적용 * refactor: EditBillPage 로직 hook으로 분리 * fix: export 잘못된 오류 수정 * fix: MSW mocking 해제 * test: Top component storybook 오류 해결 * test: Step.stories.tsx 수정 * style: lint 적용 * style: lint 적용 --- client/src/apis/request/bill.ts | 2 +- client/src/assets/image/editPencil.svg | 3 + .../components/AmountInput/AmountInput.tsx | 18 +- .../components/BillDetails/BillDetails.tsx | 52 ++++++ .../Design/components/Amount/Amount.tsx | 12 +- .../components/Amount/EditableAmount.tsx | 107 ++++++++++++ .../FixedButton/FixedButton.style.ts | 24 ++- .../components/FixedButton/FixedButton.tsx | 7 +- .../Design/components/Icon/Icon.style.ts | 1 + .../Design/components/Icon/Icon.tsx | 2 + .../Design/components/Icon/Icon.type.ts | 3 +- .../Design/components/ListItem/ListItem.tsx | 8 +- .../Design/components/ListItem/Row.tsx | 8 +- .../NumberKeyboard/NumberKeyboard.tsx | 6 +- .../NumberKeyboardBottomSheet.tsx | 43 +++++ .../NumberKeyboard/useNumberKeyboard.tsx | 9 +- .../Design/components/Top/EditableLine.tsx | 78 +++++++++ .../Design/components/Top/Top.stories.tsx | 2 +- .../components/Design/components/Top/Top.tsx | 2 + .../src/components/StepList/Step.stories.tsx | 10 +- client/src/components/StepList/Step.tsx | 14 +- client/src/constants/routerUrls.ts | 1 + .../queries/bill/useRequestGetBillDetails.ts | 2 +- .../hooks/queries/bill/useRequestPutBill.ts | 4 +- .../queries/bill/useRequestPutBillDetails.ts | 2 +- .../useBillDetails/useBillDetailInput.tsx | 90 ---------- .../hooks/useBillDetails/useBillDetails.ts | 157 ------------------ client/src/hooks/useEditBillActions.ts | 78 +++++++++ client/src/hooks/useEditBillKeyboardAction.ts | 43 +++++ client/src/hooks/useEditBillPage.ts | 53 ++++++ client/src/hooks/useEditBillPageScroll.ts | 35 ++++ client/src/hooks/useEditBillState.ts | 90 ++++++++++ client/src/mocks/handlers/billHandler.ts | 2 +- client/src/mocks/sharedState.ts | 34 ++++ .../src/pages/EditBillPage/EditBillPage.tsx | 96 +++++++++++ client/src/router.tsx | 7 +- 36 files changed, 819 insertions(+), 286 deletions(-) create mode 100644 client/src/assets/image/editPencil.svg create mode 100644 client/src/components/BillDetails/BillDetails.tsx create mode 100644 client/src/components/Design/components/Amount/EditableAmount.tsx create mode 100644 client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx create mode 100644 client/src/components/Design/components/Top/EditableLine.tsx delete mode 100644 client/src/hooks/useBillDetails/useBillDetailInput.tsx delete mode 100644 client/src/hooks/useBillDetails/useBillDetails.ts create mode 100644 client/src/hooks/useEditBillActions.ts create mode 100644 client/src/hooks/useEditBillKeyboardAction.ts create mode 100644 client/src/hooks/useEditBillPage.ts create mode 100644 client/src/hooks/useEditBillPageScroll.ts create mode 100644 client/src/hooks/useEditBillState.ts create mode 100644 client/src/pages/EditBillPage/EditBillPage.tsx diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 63173a06f..374a199cf 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -57,7 +57,7 @@ export const requestGetBillDetails = async ({ }); }; -interface PutBillDetail { +export interface PutBillDetail { id: number; price: number; isFixed: boolean; diff --git a/client/src/assets/image/editPencil.svg b/client/src/assets/image/editPencil.svg new file mode 100644 index 000000000..382e8ffd6 --- /dev/null +++ b/client/src/assets/image/editPencil.svg @@ -0,0 +1,3 @@ +<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M12.214 2.98152L13.616 1.58052C13.9877 1.20882 14.4918 1 15.0175 1C15.5432 1 16.0473 1.20882 16.419 1.58052C16.7907 1.95222 16.9995 2.45636 16.9995 2.98202C16.9995 3.50768 16.7907 4.01182 16.419 4.38352L15.018 5.78552M12.214 2.98152L3.98 11.2155C2.935 12.2615 2.412 12.7835 2.056 13.4205C1.7 14.0575 1.342 15.5605 1 16.9995C2.438 16.6575 3.942 16.2995 4.579 15.9435C5.216 15.5875 5.739 15.0645 6.784 14.0195L15.018 5.78552M12.214 2.98152L15.018 5.78552M8 16.9995H14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/client/src/components/AmountInput/AmountInput.tsx b/client/src/components/AmountInput/AmountInput.tsx index c82672956..83ffc9e44 100644 --- a/client/src/components/AmountInput/AmountInput.tsx +++ b/client/src/components/AmountInput/AmountInput.tsx @@ -1,13 +1,17 @@ /** @jsxImportSource @emotion/react */ import {css} from '@emotion/react'; -import {Text} from '@components/Design'; +import {Text, useTheme} from '@components/Design'; interface Props { value: string; + onClick?: () => void; + underlined?: boolean; + activated?: boolean; } -const AmountInput = ({value}: Props) => { +const AmountInput = ({value, onClick, underlined, activated}: Props) => { + const {theme} = useTheme(); return ( <div css={css` @@ -16,10 +20,16 @@ const AmountInput = ({value}: Props) => { justify-content: end; align-items: end; gap: 0.5rem; + transition: 0.2s ease-in-out; + ${underlined && + css` + border-bottom: 1px solid ${activated ? theme.colors.primary : theme.colors.gray}; + `} `} + onClick={onClick} > - <Text size="head" textColor={value ? 'black' : 'gray'}> - {value ? value : '0'} + <Text size="head" textColor={value !== '0' ? 'black' : 'gray'}> + {value} </Text> <Text textColor="gray" diff --git a/client/src/components/BillDetails/BillDetails.tsx b/client/src/components/BillDetails/BillDetails.tsx new file mode 100644 index 000000000..3d9be8461 --- /dev/null +++ b/client/src/components/BillDetails/BillDetails.tsx @@ -0,0 +1,52 @@ +import {css} from '@emotion/react'; +import {forwardRef} from 'react'; + +import EditableAmount from '@components/Design/components/Amount/EditableAmount'; +import {BillDetail} from 'types/serviceType'; + +import {Text} from '@components/Design'; + +interface Props { + billDetails: BillDetail[]; + onClickInput: (id: number) => void; + activatedId: number; +} + +const BillDetails = forwardRef<HTMLDivElement, Props>(({billDetails, onClickInput, activatedId}, ref) => { + return ( + <div + ref={ref} + css={css` + display: flex; + flex-direction: column; + gap: 0.5rem; + padding-inline: 0.5rem; + `} + > + {billDetails.map(billDetail => ( + <div + key={billDetail.id} + data-id={billDetail.id} + css={css` + display: flex; + justify-content: space-between; + align-items: center; + padding-block: 0.5rem; + `} + > + <Text size="bodyBold">{billDetail.memberName}</Text> + + <EditableAmount + value={billDetail.price.toLocaleString('ko-kr')} + onChange={() => {}} + onClick={() => onClickInput(billDetail.id)} + isFixed={billDetail.isFixed} + activated={activatedId === billDetail.id} + /> + </div> + ))} + </div> + ); +}); + +export default BillDetails; diff --git a/client/src/components/Design/components/Amount/Amount.tsx b/client/src/components/Design/components/Amount/Amount.tsx index f491df6ba..c07fe1ae3 100644 --- a/client/src/components/Design/components/Amount/Amount.tsx +++ b/client/src/components/Design/components/Amount/Amount.tsx @@ -1,4 +1,6 @@ /** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; + import Flex from '../Flex/Flex'; import Text from '../Text/Text'; @@ -8,12 +10,18 @@ interface Props { const Amount = ({amount}: Props) => { return ( - <Flex alignItems="center" gap="0.25rem"> + <div + css={css` + display: flex; + align-items: center; + gap: 0.25rem; + `} + > <Text>{amount ? amount.toLocaleString('ko-kr') : 0}</Text> <Text size="tiny" textColor="gray"> 원 </Text> - </Flex> + </div> ); }; diff --git a/client/src/components/Design/components/Amount/EditableAmount.tsx b/client/src/components/Design/components/Amount/EditableAmount.tsx new file mode 100644 index 000000000..c71ed1778 --- /dev/null +++ b/client/src/components/Design/components/Amount/EditableAmount.tsx @@ -0,0 +1,107 @@ +import {css} from '@emotion/react'; +import {useEffect, useRef, useState} from 'react'; + +import {useTheme} from '@components/Design/theme/HDesignProvider'; +import TYPOGRAPHY from '@components/Design/token/typography'; + +import Icon from '../Icon/Icon'; +import Text from '../Text/Text'; + +interface Props { + value: string; + onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void; + onClick?: () => void; + readOnly?: boolean; + isFixed?: boolean; + activated?: boolean; +} + +const EditableAmount = ({value, onChange, onClick, readOnly = true, isFixed = false, activated}: Props) => { + const {theme} = useTheme(); + + const [width, setWidth] = useState(0); + + const spanRef = useRef<HTMLSpanElement | null>(null); + + useEffect(() => { + if (spanRef.current) { + setWidth(spanRef.current.getBoundingClientRect().width); + } + }, [value]); + + return ( + <label onClick={onClick}> + <div + css={css` + display: flex; + gap: 0.5rem; + `} + > + <div + css={css` + display: flex; + align-items: center; + gap: 0.25rem; + `} + > + {isFixed && ( + <Text size="caption" textColor="error"> + * + </Text> + )} + <input + css={css([ + TYPOGRAPHY.body, + css` + text-align: end; + color: ${theme.colors.black}; + width: ${width}px; + + transition: 0.2s ease-in-out; + border-bottom: 1px solid transparent; + ${activated ? `border-bottom-color: ${theme.colors.primary};` : ''}; + + ::placeholder { + color: ${theme.colors.gray}; + } + `, + ])} + readOnly={readOnly} + placeholder="0" + value={value} + onChange={onChange} + /> + <Text size="tiny" textColor="gray"> + 원 + </Text> + </div> + <Icon iconType="editPencil" /> + </div> + + <span + ref={spanRef} + css={[ + TYPOGRAPHY.body, + , + css` + position: absolute; + width: fit-content; + height: 1px; + margin: -1px; + border: 0; + padding: 0; + + white-space: nowrap; + clip-path: inset(100%); + clip: rect(0 0 0 0); + overflow: hidden; + `, + ]} + > + {value === '' ? '0' : value} + </span> + </label> + ); +}; + +export default EditableAmount; diff --git a/client/src/components/Design/components/FixedButton/FixedButton.style.ts b/client/src/components/Design/components/FixedButton/FixedButton.style.ts index 00a7ea255..e93c348f8 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.style.ts +++ b/client/src/components/Design/components/FixedButton/FixedButton.style.ts @@ -35,25 +35,31 @@ const getHoverAndActiveBackground = (color: string) => }, }); -export const deleteButtonStyle = (theme: Theme) => [ +export const deleteButtonStyle = (theme: Theme) => css({ display: 'flex', justifyContent: 'center', - padding: '0.875rem 1rem', - borderRadius: '1.25rem', - backgroundColor: theme.colors.error, - color: theme.colors.white, + padding: '1rem 1.5rem', + borderRadius: '1rem', + width: '100%', fontFamily: 'Pretendard', - fontSize: '1rem', + fontSize: '1.25rem', fontWeight: '700', lineHeight: '1', transition: '0.2s', transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - }), - getHoverAndActiveBackground(theme.colors.error), -]; + + backgroundColor: theme.colors.tertiary, + color: theme.colors.error, + + '&:disabled': { + backgroundColor: theme.colors.grayContainer, + color: theme.colors.onPrimary, + cursor: 'default', + }, + }); export const fixedButtonStyle = (props: Required<FixedButtonStyleProps>) => { return [getFixedButtonDefaultStyle(props.theme), getFixedButtonVariantsStyle(props.variants, props.theme)]; diff --git a/client/src/components/Design/components/FixedButton/FixedButton.tsx b/client/src/components/Design/components/FixedButton/FixedButton.tsx index 62ea0127e..f24120da1 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.tsx +++ b/client/src/components/Design/components/FixedButton/FixedButton.tsx @@ -8,6 +8,7 @@ import { fixedButtonStyle, buttonContainerStyle, cancleButtonStyle, + deleteButtonStyle, } from '@HDcomponents/FixedButton/FixedButton.style'; import {FixedButtonProps} from '@HDcomponents/FixedButton/FixedButton.type'; import IconButton from '@HDcomponents/IconButton/IconButton'; @@ -23,9 +24,9 @@ export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElem <div css={fixedButtonContainerStyle(theme)}> <div css={buttonContainerStyle}> {onDeleteClick && ( - <IconButton type="button" size="large" variants="destructive" onClick={onDeleteClick}> - <Icon iconType="trash" /> - </IconButton> + <button css={deleteButtonStyle(theme)} ref={ref} onClick={onDeleteClick}> + 삭제하기 + </button> )} {onBackClick && ( <button css={cancleButtonStyle(theme)} ref={ref} onClick={onBackClick}> diff --git a/client/src/components/Design/components/Icon/Icon.style.ts b/client/src/components/Design/components/Icon/Icon.style.ts index 8d4d68145..1a8b237e5 100644 --- a/client/src/components/Design/components/Icon/Icon.style.ts +++ b/client/src/components/Design/components/Icon/Icon.style.ts @@ -16,6 +16,7 @@ const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { x: 'gray', toss: 'white', meatballs: 'black', + editPencil: 'gray', }; export const iconStyle = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { diff --git a/client/src/components/Design/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx index da65acf1c..cfda8df8c 100644 --- a/client/src/components/Design/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -11,6 +11,7 @@ import RightChevron from '@assets/image/rightChevron.svg'; import Check from '@assets/image/check.svg'; import X from '@assets/image/x.svg'; import Meatballs from '@assets/image/meatballs.svg'; +import EditPencil from '@assets/image/editPencil.svg'; import {IconProps} from '@HDcomponents/Icon/Icon.type'; import {useTheme} from '@theme/HDesignProvider'; @@ -28,6 +29,7 @@ const ICON = { check: <Check />, x: <X />, meatballs: <Meatballs />, + editPencil: <EditPencil />, }; export const Icon: React.FC<IconProps> = ({iconColor, iconType, ...htmlProps}: IconProps) => { diff --git a/client/src/components/Design/components/Icon/Icon.type.ts b/client/src/components/Design/components/Icon/Icon.type.ts index 1b058c76f..cc1fed148 100644 --- a/client/src/components/Design/components/Icon/Icon.type.ts +++ b/client/src/components/Design/components/Icon/Icon.type.ts @@ -12,7 +12,8 @@ export type IconType = | 'check' | 'x' | 'toss' - | 'meatballs'; + | 'meatballs' + | 'editPencil'; export type IconColor = ColorKeys; diff --git a/client/src/components/Design/components/ListItem/ListItem.tsx b/client/src/components/Design/components/ListItem/ListItem.tsx index fc99b4c1a..261dd1f75 100644 --- a/client/src/components/Design/components/ListItem/ListItem.tsx +++ b/client/src/components/Design/components/ListItem/ListItem.tsx @@ -4,9 +4,13 @@ import {useTheme} from '@components/Design/theme/HDesignProvider'; import {listItemStyle} from './ListItem.style'; import Row from './Row'; -const ListItem = ({children}: React.PropsWithChildren) => { +const ListItem = ({children, ...rest}: React.HTMLAttributes<HTMLDivElement>) => { const {theme} = useTheme(); - return <div css={listItemStyle(theme)}>{children}</div>; + return ( + <div css={listItemStyle(theme)} {...rest}> + {children} + </div> + ); }; ListItem.Row = Row; diff --git a/client/src/components/Design/components/ListItem/Row.tsx b/client/src/components/Design/components/ListItem/Row.tsx index aec6a749d..9cd9a3d1a 100644 --- a/client/src/components/Design/components/ListItem/Row.tsx +++ b/client/src/components/Design/components/ListItem/Row.tsx @@ -3,9 +3,13 @@ import {useTheme} from '@components/Design/theme/HDesignProvider'; import {rowStyle} from './ListItem.style'; -const Row = ({children}: React.PropsWithChildren) => { +const Row = ({children, ...rest}: React.HTMLAttributes<HTMLDivElement>) => { const {theme} = useTheme(); - return <div css={rowStyle(theme)}>{children}</div>; + return ( + <div css={rowStyle(theme)} {...rest}> + {children} + </div> + ); }; export default Row; diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx index 61e36da7d..bc8d499df 100644 --- a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx @@ -8,14 +8,14 @@ import useNumberKeyboard from './useNumberKeyboard'; export type KeyboardType = 'number' | 'string' | 'amount'; -interface Props { +export interface NumberKeyboardProps { type: KeyboardType; maxNumber: number; initialValue?: string; onChange: (value: string) => void; } -export default function NumberKeyboard({type, maxNumber, initialValue, onChange}: Props) { +export default function NumberKeyboard({type, maxNumber, initialValue, onChange}: NumberKeyboardProps) { const {theme} = useTheme(); const amountKeypads = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '00', '0', '<-']; const numberKeypads = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '', '0', '<-']; @@ -35,6 +35,8 @@ export default function NumberKeyboard({type, maxNumber, initialValue, onChange} grid-template-rows: ${type === 'amount' ? 'auto' : null} repeat(4, 1fr); padding: 1rem; gap: 1rem; + width: 100%; + max-width: 768px; background-color: ${theme.colors.white}; `} > diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx new file mode 100644 index 000000000..45b51ba8f --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx @@ -0,0 +1,43 @@ +import {css} from '@emotion/react'; +import {createPortal} from 'react-dom'; + +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import FixedButton from '../FixedButton/FixedButton'; + +import NumberKeyboard, {NumberKeyboardProps} from './NumberKeyboard'; + +interface Props extends NumberKeyboardProps { + isOpened?: boolean; + onClose: () => void; +} + +const NumberKeyboardBottomSheet = ({isOpened, onClose, ...props}: Props) => { + const {theme} = useTheme(); + return createPortal( + <div + css={css` + position: fixed; + padding-bottom: 6.25rem; + width: 100%; + max-width: 768px; + display: flex; + flex-direction: column; + gap: 1rem; + bottom: 0; + background-color: ${theme.colors.white}; + + transform: ${isOpened ? 'translate3d(0, 0, 0)' : 'translate3d(0, 100%, 0)'}; + transition: 0.2s ease-in-out; + `} + > + <NumberKeyboard {...props} /> + <FixedButton variants="tertiary" onClick={onClose}> + 닫기 + </FixedButton> + </div>, + document.body, + ); +}; + +export default NumberKeyboardBottomSheet; diff --git a/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx index 48301ea8e..1c64f61b3 100644 --- a/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx +++ b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboard.tsx @@ -12,6 +12,12 @@ interface Props { const useNumberKeyboard = ({type, maxNumber, initialValue, onChange}: Props) => { const [value, setValue] = useState(initialValue ?? ''); + useEffect(() => { + if (initialValue) { + setValue(initialValue); + } + }, [initialValue]); + const onClickKeypad = (inputValue: string) => { const newValue = (value + inputValue).replace(/,/g, ''); setValueByType(newValue); @@ -35,7 +41,8 @@ const useNumberKeyboard = ({type, maxNumber, initialValue, onChange}: Props) => if (type === 'string') { setValue(value); } else { - const limitedValue = maxNumber && Number(value) > maxNumber ? `${maxNumber}` : value; + const limitedValue = maxNumber !== 0 ? (maxNumber && Number(value) > maxNumber ? `${maxNumber}` : value) : 0; + if (Number(limitedValue) === 0) { setValue(''); } else { diff --git a/client/src/components/Design/components/Top/EditableLine.tsx b/client/src/components/Design/components/Top/EditableLine.tsx new file mode 100644 index 000000000..743fe191e --- /dev/null +++ b/client/src/components/Design/components/Top/EditableLine.tsx @@ -0,0 +1,78 @@ +/** @jsxImportSource @emotion/react */ +import {css} from '@emotion/react'; +import {useEffect, useRef, useState} from 'react'; + +import TYPOGRAPHY from '@components/Design/token/typography'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import Icon from '../Icon/Icon'; + +interface Props { + value: string; + onChange: (event: React.ChangeEvent<HTMLInputElement>) => void; +} + +export default function EditableLine({value, onChange}: Props) { + const {theme} = useTheme(); + const [width, setWidth] = useState(0); + + const spanRef = useRef<HTMLSpanElement | null>(null); + + useEffect(() => { + if (spanRef.current) { + setWidth(spanRef.current.getBoundingClientRect().width); + } + }, [value]); + + return ( + <label> + <div + css={css` + display: flex; + gap: 0.5rem; + `} + > + <input + css={css([ + TYPOGRAPHY.subTitle, + css` + color: ${theme.colors.black}; + width: ${width}px; + + ::placeholder { + color: ${theme.colors.gray}; + } + `, + ])} + placeholder="ex) 뽕쟁이 족발" + value={value} + onChange={onChange} + /> + <Icon iconType="editPencil" /> + </div> + + <span + ref={spanRef} + css={[ + TYPOGRAPHY.subTitle, + , + css` + position: absolute; + width: fit-content; + height: 1px; + margin: -1px; + border: 0; + padding: 0; + + white-space: nowrap; + clip-path: inset(100%); + clip: rect(0 0 0 0); + overflow: hidden; + `, + ]} + > + {value === '' ? 'ex) 뽕쟁이 족발' : value} + </span> + </label> + ); +} diff --git a/client/src/components/Design/components/Top/Top.stories.tsx b/client/src/components/Design/components/Top/Top.stories.tsx index 20aa07b8e..180c360cb 100644 --- a/client/src/components/Design/components/Top/Top.stories.tsx +++ b/client/src/components/Design/components/Top/Top.stories.tsx @@ -19,7 +19,7 @@ export default meta; type Story = StoryObj<typeof meta>; export const Playground: Story = { - render: ({...args}) => { + render: () => { return ( <Top> <Top.Line text="정산을 시작하려는" /> diff --git a/client/src/components/Design/components/Top/Top.tsx b/client/src/components/Design/components/Top/Top.tsx index 9d00801d5..56c41eb6e 100644 --- a/client/src/components/Design/components/Top/Top.tsx +++ b/client/src/components/Design/components/Top/Top.tsx @@ -2,8 +2,10 @@ import {css} from '@emotion/react'; import Line from './Line'; +import EditableLine from './EditableLine'; Top.Line = Line; +Top.EditableLine = EditableLine; export default function Top({children}: React.PropsWithChildren) { return ( diff --git a/client/src/components/StepList/Step.stories.tsx b/client/src/components/StepList/Step.stories.tsx index 076879f6b..f442aad39 100644 --- a/client/src/components/StepList/Step.stories.tsx +++ b/client/src/components/StepList/Step.stories.tsx @@ -1,6 +1,8 @@ /** @jsxImportSource @emotion/react */ import type {Meta, StoryObj} from '@storybook/react'; +import {MemoryRouter} from 'react-router-dom'; + import Step from './Step'; const meta = { @@ -52,9 +54,11 @@ type Story = StoryObj<typeof meta>; export const Playground: Story = { render: ({...args}) => { return ( - <div style={{width: '400px'}}> - <Step {...args} /> - </div> + <MemoryRouter> + <div style={{width: '400px'}}> + <Step {...args} /> + </div> + </MemoryRouter> ); }, }; diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index 1fec736fc..333994f47 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -1,16 +1,26 @@ /** @jsxImportSource @emotion/react */ +import {useNavigate} from 'react-router-dom'; + import Amount from '@components/Design/components/Amount/Amount'; import ChipGroup from '@components/Design/components/ChipGroup/ChipGroup'; import ListItem from '@components/Design/components/ListItem/ListItem'; -import {Step as StepType} from 'types/serviceType'; +import {Bill, Step as StepType} from 'types/serviceType'; import {Text} from '@components/Design'; +import getEventIdByUrl from '@utils/getEventIdByUrl'; + interface Prop { step: StepType; } const Step = ({step}: Prop) => { + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); + const handleClickStep = (bill: Bill) => { + navigate(`/event/${eventId}/edit-bill`, {state: {bill}}); + }; + return ( <ListItem> <ListItem.Row> @@ -21,7 +31,7 @@ const Step = ({step}: Prop) => { </ListItem.Row> {step.bills.map(bill => { return ( - <ListItem.Row> + <ListItem.Row onClick={() => handleClickStep(bill)}> <Text size="bodyBold">{bill.title}</Text> <Amount amount={bill.price} /> </ListItem.Row> diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index de3cc5946..cb5d946b1 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -6,5 +6,6 @@ export const ROUTER_URLS = { eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', addBill: '/event/:eventId/add-bill', + editBill: '/event/:eventId/edit-bill', eventEdit: 'event/:eventId/admin/edit', }; diff --git a/client/src/hooks/queries/bill/useRequestGetBillDetails.ts b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts index 181777011..26dae0c39 100644 --- a/client/src/hooks/queries/bill/useRequestGetBillDetails.ts +++ b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts @@ -20,7 +20,7 @@ const useRequestGetBillDetails = ({billId, ...props}: WithErrorHandlingStrategy< }); return { - reportFromServer: data?.billDetails ?? [], + billDetails: data?.billDetails ?? [], ...rest, }; }; diff --git a/client/src/hooks/queries/bill/useRequestPutBill.ts b/client/src/hooks/queries/bill/useRequestPutBill.ts index 280436f76..88a47f6bf 100644 --- a/client/src/hooks/queries/bill/useRequestPutBill.ts +++ b/client/src/hooks/queries/bill/useRequestPutBill.ts @@ -12,7 +12,7 @@ const useRequestPutBill = () => { const eventId = getEventIdByUrl(); const queryClient = useQueryClient(); - const {mutate, ...rest} = useMutation({ + const {mutate, mutateAsync, ...rest} = useMutation({ mutationFn: ({billId, title, price}: WithBillId<RequestPutBill>) => requestPutBill({eventId, billId, title, price}), onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); @@ -20,7 +20,7 @@ const useRequestPutBill = () => { }, }); - return {pulBill: mutate, ...rest}; + return {putBill: mutate, putBillAsync: mutateAsync, ...rest}; }; export default useRequestPutBill; diff --git a/client/src/hooks/queries/bill/useRequestPutBillDetails.ts b/client/src/hooks/queries/bill/useRequestPutBillDetails.ts index a63c9d967..9e9bb3e0f 100644 --- a/client/src/hooks/queries/bill/useRequestPutBillDetails.ts +++ b/client/src/hooks/queries/bill/useRequestPutBillDetails.ts @@ -8,7 +8,7 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import QUERY_KEYS from '@constants/queryKeys'; -const useRequestPutBillDetails = (billId: number) => { +const useRequestPutBillDetails = ({billId}: WithBillId) => { const eventId = getEventIdByUrl(); const queryClient = useQueryClient(); diff --git a/client/src/hooks/useBillDetails/useBillDetailInput.tsx b/client/src/hooks/useBillDetails/useBillDetailInput.tsx deleted file mode 100644 index 6b3350491..000000000 --- a/client/src/hooks/useBillDetails/useBillDetailInput.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import type {BillDetail} from 'types/serviceType'; - -import {useEffect, useState} from 'react'; - -import validateBillDetails from '@utils/validate/validateBillDetails'; - -type BillDetailInput = BillDetail & { - index: number; -}; - -type UseBillDetailInput = { - data: BillDetail[]; - addAdjustedMember: (billDetails: BillDetail) => void; - getOnlyOneNotAdjustedRemainMemberIndex: () => number | null; - getIsSamePriceStateAndServerState: () => boolean; - totalPrice: number; -}; - -const useBillDetailInput = ({ - data, - addAdjustedMember, - totalPrice, - getOnlyOneNotAdjustedRemainMemberIndex, - getIsSamePriceStateAndServerState, -}: UseBillDetailInput) => { - const [inputList, setInputList] = useState<BillDetailInput[]>(data.map((item, index) => ({...item, index}))); - const [canSubmit, setCanSubmit] = useState<boolean>(false); - - const [canEditList, setCanEditList] = useState<boolean[]>([]); - - const onChange = (event: React.ChangeEvent<HTMLInputElement>, index: number) => { - const {value} = event.target; - - validateAndAddAdjustedMember(value, index); - }; - - const validateAndAddAdjustedMember = (price: string, index: number) => { - const {isValid} = validateBillDetails(price, totalPrice); - - if (isValid) { - const newInputList = [...inputList]; - newInputList[index].price = Number(price); - setInputList(newInputList); - - const reportData: BillDetail = { - ...newInputList[index], - memberName: newInputList[index].memberName, - price: newInputList[index].price, - isFixed: newInputList[index].isFixed, - }; - addAdjustedMember(reportData); - } - }; - - // 서버와 값이 같지 않고 input price의 상태가 모두 valid하다면 can submit true - useEffect(() => { - const isSamePriceState = getIsSamePriceStateAndServerState(); - const isAllValid = inputList.every(input => validateBillDetails(String(input.price), totalPrice)); - - setCanSubmit(!isSamePriceState && isAllValid); - }, [inputList]); - - // addAdjustedMember로 인해 data가 변했을 때 input list의 값을 맞춰주기 위함 - useEffect(() => { - setCanSubmit(!getIsSamePriceStateAndServerState()); - setInputList(data.map((item, index) => ({...item, index}))); - - // 남은 인원이 1명일 때 수정을 불가능하도록 설정 - const onlyOneIndex = getOnlyOneNotAdjustedRemainMemberIndex(); - - if (data.length !== 0) { - setCanEditList(new Array(data.length).fill(true)); - } - - if (onlyOneIndex !== null) { - const newCanEditList = new Array(data.length).fill(true); - newCanEditList[onlyOneIndex] = false; - setCanEditList(newCanEditList); - } - }, [data]); - - return { - inputList, - onChange, - canEditList, - canSubmit, - }; -}; - -export default useBillDetailInput; diff --git a/client/src/hooks/useBillDetails/useBillDetails.ts b/client/src/hooks/useBillDetails/useBillDetails.ts deleted file mode 100644 index e4b7da915..000000000 --- a/client/src/hooks/useBillDetails/useBillDetails.ts +++ /dev/null @@ -1,157 +0,0 @@ -import type {BillDetail} from 'types/serviceType'; - -import {useEffect, useState} from 'react'; - -import useRequestGetBillDetails from '@hooks/queries/bill/useRequestGetBillDetails'; -import useRequestPutBillDetails from '@hooks/queries/bill/useRequestPutBillDetails'; - -const useBillDetails = (billId: number, totalPrice: number, onClose: () => void) => { - const {reportFromServer, isSuccess} = useRequestGetBillDetails({billId}); - const {putBillDetails} = useRequestPutBillDetails(billId); - - const [billDetails, setBillDetails] = useState<BillDetail[]>(reportFromServer); - - // isFixed를 모두 풀고 계산값으로 모두 처리하는 기능 - const reCalculatePriceByTotalPriceChange = () => { - const {divided, remainder} = calculateDividedPrice(billDetails.length, 0); - - const resetBillDetails = [...billDetails]; - resetBillDetails.forEach((member, index) => { - if (index !== resetBillDetails.length - 1) { - member.price = divided; - } else { - member.price = divided + remainder; - } - member.isFixed = false; - }); - - setBillDetails(resetBillDetails); - }; - - // 총 금액이 변동됐을 때 (서버에서 온 값과 다를 때) 재계산 실행 - useEffect(() => { - const totalPriceFromServer = reportFromServer.reduce((acc, cur) => acc + cur.price, 0); - - if (totalPriceFromServer !== totalPrice && totalPriceFromServer !== 0) { - reCalculatePriceByTotalPriceChange(); - } - }, [totalPrice, reportFromServer]); - - useEffect(() => { - if (isSuccess) { - setBillDetails(reportFromServer); - } - }, [reportFromServer, isSuccess]); - - const isExistAdjustedPrice = () => { - return billDetails.some(member => member.isFixed === true); - }; - - // 조정되지 않은 인원이 단 1명인 경우의 index - const getOnlyOneNotAdjustedRemainMemberIndex = (): number | null => { - const adjustedPriceCount = getAdjustedMemberCount(billDetails); - - if (adjustedPriceCount < billDetails.length - 1) return null; - - return billDetails.findIndex(member => member.isFixed === false); - }; - - // 조정값 멤버의 수를 구하는 함수 - const getAdjustedMemberCount = (billDetails: BillDetail[]) => { - return billDetails.filter(member => member.isFixed === true).length; - }; - - const addAdjustedMember = (memberReport: BillDetail) => { - const newBillDetails = billDetails.map(member => - member.memberName === memberReport.memberName ? {...member, price: memberReport.price, isFixed: true} : member, - ); - - calculateAnotherMemberPrice(newBillDetails); - }; - - const calculateDividedPrice = (remainMemberCount: number, totalAdjustedPrice: number) => { - return { - divided: Math.floor((totalPrice - totalAdjustedPrice) / remainMemberCount), - remainder: (totalPrice - totalAdjustedPrice) % remainMemberCount, - }; - }; - - // 계산값으로 값을 변경했을 때 isFixed를 푸는 함수 - // 100 true 33300 true 33300 false 33300 false - const setIsFixedFalseAtResetToDividedPrice = (billDetails: BillDetail[], divided: number) => { - return billDetails.map(bill => { - if (bill.isFixed === true && bill.price === divided) { - return {...bill, isFixed: false}; - } - - return bill; - }); - }; - - const calculateAnotherMemberPrice = (billDetails: BillDetail[]) => { - // 총 조정치 금액 - const totalAdjustedPrice = billDetails - .filter(memberReport => memberReport.isFixed === true) - .reduce((acc, cur) => acc + cur.price, 0); - - const remainMemberCount = billDetails.length - getAdjustedMemberCount(billDetails); - const {divided, remainder} = calculateDividedPrice(remainMemberCount, totalAdjustedPrice); - - const updatedList = billDetails.map(member => (member.isFixed === true ? member : {...member, price: divided})); - - // 나머지를 조정되지 않은 멤버 중 마지막 멤버에게 추가 - if (remainder !== 0) { - const nonAdjustedMembers = updatedList.filter(member => member.isFixed === false); - const lastNonAdjustedMemberIndex = updatedList.findIndex( - member => member.memberName === nonAdjustedMembers[nonAdjustedMembers.length - 1].memberName, - ); - - if (lastNonAdjustedMemberIndex !== -1) { - updatedList[lastNonAdjustedMemberIndex].price += remainder; - } - } - - // 조정됐지만 계산값으로 가격이 변한 경우 fixed 상태를 풀어야한다. - const result = setIsFixedFalseAtResetToDividedPrice(updatedList, divided); - setBillDetails(result); - }; - - const onSubmit = () => { - const withoutMemberName = billDetails.map(billDetail => { - const {memberName, ...rest} = billDetail; - return {...rest}; - }); - - putBillDetails({billId, billDetails: withoutMemberName}); - - onClose(); - }; - - const getIsSamePriceStateAndServerState = () => { - const serverStatePriceList = reportFromServer.map(({price}) => price); - const clientStatePriceList = billDetails.map(({price}) => price); - - let isSame = true; - - // isArrayEqual을 사용하지 않은 이유는 정렬이 영향을 받으면 안 되기 때문입니다 - for (let i = 0; i < serverStatePriceList.length; i++) { - if (serverStatePriceList[i] !== clientStatePriceList[i]) { - isSame = false; - } - } - - return isSame; - }; - - return { - billDetails, - addAdjustedMember, - isExistAdjustedPrice, - onSubmit, - getOnlyOneNotAdjustedRemainMemberIndex, - getIsSamePriceStateAndServerState, - isSuccess, - }; -}; - -export default useBillDetails; diff --git a/client/src/hooks/useEditBillActions.ts b/client/src/hooks/useEditBillActions.ts new file mode 100644 index 000000000..52c925484 --- /dev/null +++ b/client/src/hooks/useEditBillActions.ts @@ -0,0 +1,78 @@ +import {useNavigate} from 'react-router-dom'; +import {useEffect} from 'react'; + +import {Bill, BillDetail} from 'types/serviceType'; +import {RequestPutBill} from '@apis/request/bill'; + +import getEventIdByUrl from '@utils/getEventIdByUrl'; + +import useRequestPutBill from './queries/bill/useRequestPutBill'; +import useRequestDeleteBill from './queries/bill/useRequestDeleteBill'; +import useRequestPutBillDetails from './queries/bill/useRequestPutBillDetails'; + +interface Props { + bill: Bill; + billDetails: BillDetail[]; + newBill: RequestPutBill; + newBillDetails: BillDetail[]; +} + +const useEditBillActions = ({bill, billDetails, newBill, newBillDetails}: Props) => { + const navigate = useNavigate(); + const eventId = getEventIdByUrl(); + + const {putBillAsync, isSuccess: isSuccessPutBill, isPending: isPendingPutBill} = useRequestPutBill(); + const {deleteBill, isSuccess: isSuccessDeleteBill} = useRequestDeleteBill(); + const { + putBillDetails, + isSuccess: isSusseccPutBillDetails, + isPending: isPendingPutBillDetails, + } = useRequestPutBillDetails({billId: bill.id}); + + const handleClickDelete = () => { + deleteBill({billId: bill.id}); + }; + + const isBillChanged = bill.title !== newBill.title || bill.price !== newBill.price; + const isBillDetailsChanged = JSON.stringify(billDetails) !== JSON.stringify(newBillDetails); + const canSubmit = newBill.price !== 0 && (isBillChanged || isBillDetailsChanged); + + const handleClickUpdate = async () => { + if (isBillChanged) { + await putBillAsync({billId: bill.id, price: newBill.price, title: newBill.title}); + } + if (isBillDetailsChanged) { + putBillDetails({ + billId: bill.id, + billDetails: newBillDetails.map(({id, price, isFixed}) => ({ + id, + price, + isFixed, + })), + }); + } + }; + + useEffect(() => { + if (isSuccessDeleteBill || isSusseccPutBillDetails || (isSuccessPutBill && !isBillDetailsChanged)) { + navigate(`/events/${eventId}/admin`); + } + }, [isSuccessDeleteBill, isSusseccPutBillDetails, isSuccessPutBill, isBillDetailsChanged]); + + const isPendingUpdate = () => { + if (!isBillChanged) { + return isPendingPutBill; + } + + return isPendingPutBill || isPendingPutBillDetails; + }; + + return { + handleClickDelete, + handleClickUpdate, + isPendingUpdate, + canSubmit, + }; +}; + +export default useEditBillActions; diff --git a/client/src/hooks/useEditBillKeyboardAction.ts b/client/src/hooks/useEditBillKeyboardAction.ts new file mode 100644 index 000000000..e2a5a6fda --- /dev/null +++ b/client/src/hooks/useEditBillKeyboardAction.ts @@ -0,0 +1,43 @@ +import {useRef, useState} from 'react'; + +import {BillDetail} from 'types/serviceType'; +import {RequestPutBill} from '@apis/request/bill'; + +import useEditBillPageScroll from './useEditBillPageScroll'; + +interface Props { + billDetails: BillDetail[]; + newBill: RequestPutBill; + newBillDetails: BillDetail[]; +} + +const useEditBillKeyboardAction = ({newBill, billDetails, newBillDetails}: Props) => { + const [keyboardTargetId, setKeyboardTargetId] = useState<null | number>(null); + const billDetailsRef = useRef<HTMLDivElement>(null); + const {handleScrollToFocus} = useEditBillPageScroll(); + + const handleClickBillDetailInput = (id: number) => { + setKeyboardTargetId(id); + handleScrollToFocus({id, billDetailsRef}); + }; + + const totalFixedPrice = newBillDetails.reduce( + (sum, detail) => (detail.isFixed && detail.id !== keyboardTargetId ? sum + detail.price : sum), + 0, + ); + const keyboardMaxPrice = keyboardTargetId === 0 ? 10000000 : Math.max(0, newBill.price - totalFixedPrice); + const keyboardInitialValue = + newBillDetails.find(({id}) => id === keyboardTargetId)?.price.toLocaleString('ko-kr') ?? + newBill.price.toLocaleString('ko-kr'); + + return { + handleClickBillDetailInput, + billDetailsRef, + keyboardMaxPrice, + keyboardInitialValue, + keyboardTargetId, + setKeyboardTargetId, + }; +}; + +export default useEditBillKeyboardAction; diff --git a/client/src/hooks/useEditBillPage.ts b/client/src/hooks/useEditBillPage.ts new file mode 100644 index 000000000..397328b7b --- /dev/null +++ b/client/src/hooks/useEditBillPage.ts @@ -0,0 +1,53 @@ +import {useLocation} from 'react-router-dom'; + +import {Bill} from 'types/serviceType'; + +import useRequestGetBillDetails from './queries/bill/useRequestGetBillDetails'; +import useEditBillActions from './useEditBillActions'; +import useEditBillKeyboardAction from './useEditBillKeyboardAction'; +import useEditBillState from './useEditBillState'; + +const useEditBillPage = () => { + const location = useLocation(); + + const bill: Bill = location.state.bill; + const {billDetails} = useRequestGetBillDetails({billId: Number(bill.id)}); + + const {newBill, newBillDetails, handleChangeBillPrice, handleChangeBillTitle, handleChangeBillDetails} = + useEditBillState({bill, billDetails}); + const {handleClickDelete, handleClickUpdate, isPendingUpdate, canSubmit} = useEditBillActions({ + bill, + billDetails, + newBill, + newBillDetails, + }); + + const { + keyboardTargetId, + setKeyboardTargetId, + keyboardMaxPrice, + keyboardInitialValue, + billDetailsRef, + handleClickBillDetailInput, + } = useEditBillKeyboardAction({newBill, newBillDetails, billDetails}); + + return { + newBill, + newBillDetails, + billDetailsRef, + handleChangeBillTitle, + handleChangeBillPrice, + handleChangeBillDetails, + handleClickBillDetailInput, + handleClickDelete, + handleClickUpdate, + isPendingUpdate, + canSubmit, + keyboardInitialValue, + keyboardMaxPrice, + keyboardTargetId, + setKeyboardTargetId, + }; +}; + +export default useEditBillPage; diff --git a/client/src/hooks/useEditBillPageScroll.ts b/client/src/hooks/useEditBillPageScroll.ts new file mode 100644 index 000000000..c2bf905ea --- /dev/null +++ b/client/src/hooks/useEditBillPageScroll.ts @@ -0,0 +1,35 @@ +import {useCallback} from 'react'; + +interface Props { + id: number; + billDetailsRef: React.RefObject<HTMLDivElement>; +} + +const useEditBillPageScroll = () => { + const handleScrollToFocus = useCallback(({id, billDetailsRef}: Props) => { + setTimeout(() => { + if (billDetailsRef.current) { + const selectedItem = billDetailsRef.current.querySelector(`[data-id="${id}"]`) as HTMLElement; + if (selectedItem) { + const screenHeight = window.screen.height; + const keyboardHeight = 416; + const itemTop = selectedItem.offsetTop; + const itemHeight = selectedItem.offsetHeight; + const itemBottom = itemTop + itemHeight; + const visibleY = screenHeight - keyboardHeight; + + const targetScrollTop = itemBottom < visibleY ? 0 : itemTop - (visibleY - itemHeight) / 2; + + window.scrollTo({ + top: targetScrollTop, + behavior: 'smooth', + }); + } + } + }, 100); + }, []); + + return {handleScrollToFocus}; +}; + +export default useEditBillPageScroll; diff --git a/client/src/hooks/useEditBillState.ts b/client/src/hooks/useEditBillState.ts new file mode 100644 index 000000000..e675944a9 --- /dev/null +++ b/client/src/hooks/useEditBillState.ts @@ -0,0 +1,90 @@ +import {useEffect, useState} from 'react'; + +import {RequestPutBill} from '@apis/request/bill'; +import {Bill, BillDetail} from 'types/serviceType'; + +import REGEXP from '@constants/regExp'; + +interface Props { + bill: Bill; + billDetails: BillDetail[]; +} + +interface HandleChangeBillDetailsProps { + value: string; + keyboardTargetId: number; +} + +const useEditBillState = ({bill, billDetails}: Props) => { + const [newBill, setNewBill] = useState<RequestPutBill>({ + title: bill.title, + price: bill.price, + }); + const [newBillDetails, setNewBillDetails] = useState<BillDetail[]>(billDetails); + + useEffect(() => { + if (billDetails) setNewBillDetails(billDetails); + }, [billDetails]); + + const onTitleInputChange = (value: string) => { + if (REGEXP.billTitle.test(value)) { + setNewBill(prev => ({...prev, title: value})); + } + }; + + const handleChangeBillTitle = (event: React.ChangeEvent<HTMLInputElement>) => { + if (event.target.value.length > 12) { + onTitleInputChange(newBill.title.slice(0, 12)); + } else { + onTitleInputChange(event.target.value); + } + }; + + const handleChangeBillPrice = (value: string) => { + if (value === newBill.price.toLocaleString('ko-kr')) return; + + const newPrice = Number(value.replace(/,/g, '')); + setNewBill(prev => ({...prev, price: newPrice})); + + const detailCount = newBillDetails.length; + const basePrice = Math.floor(newPrice / detailCount); + const remainder = newPrice % detailCount; + + setNewBillDetails(prev => + prev.map((detail, index) => ({ + ...detail, + price: index === detailCount - 1 ? basePrice + remainder : basePrice, + isFixed: false, + })), + ); + }; + + const handleChangeBillDetails = ({value, keyboardTargetId}: HandleChangeBillDetailsProps) => { + if (Number(value.replace(/,/g, '')) === newBillDetails.find(({id}) => id === keyboardTargetId)?.price) return; + setNewBillDetails(prev => { + const updatedDetails = prev.map(detail => + detail.id === keyboardTargetId ? {...detail, price: Number(value.replace(/,/g, '')), isFixed: true} : detail, + ); + + const totalFixedPrice = updatedDetails.reduce((sum, detail) => (detail.isFixed ? sum + detail.price : sum), 0); + + const remainingPrice = newBill.price - totalFixedPrice; + const unfixedCount = updatedDetails.filter(detail => !detail.isFixed).length; + + const unfixedPrice = Math.floor(remainingPrice / unfixedCount); + const lastUnfixedIndex = updatedDetails.map(detail => !detail.isFixed).lastIndexOf(true); + + return updatedDetails.map((detail, index) => { + if (detail.isFixed) return detail; + if (index === lastUnfixedIndex) { + return {...detail, price: remainingPrice - unfixedPrice * (unfixedCount - 1)}; + } + return {...detail, price: unfixedPrice}; + }); + }); + }; + + return {newBill, newBillDetails, handleChangeBillPrice, handleChangeBillTitle, handleChangeBillDetails}; +}; + +export default useEditBillState; diff --git a/client/src/mocks/handlers/billHandler.ts b/client/src/mocks/handlers/billHandler.ts index 67a8935b7..597ff3a1e 100644 --- a/client/src/mocks/handlers/billHandler.ts +++ b/client/src/mocks/handlers/billHandler.ts @@ -20,7 +20,7 @@ export const billHandler = [ http.get(`${MOCK_API_PREFIX}${USER_API_PREFIX}/:eventId/bills/:billId/fixed`, ({params}) => { const {billId} = params; const billDetails = (billDetailsData as unknown as BillDetailsData)[billId as keyof BillDetailsData]; - return HttpResponse.json({billDetails}); + return HttpResponse.json(billDetails); }), // POST /api/eventId/bills diff --git a/client/src/mocks/sharedState.ts b/client/src/mocks/sharedState.ts index 444e3c4dc..488cff5aa 100644 --- a/client/src/mocks/sharedState.ts +++ b/client/src/mocks/sharedState.ts @@ -9,6 +9,10 @@ export let memberData = { {id: 1, name: '망쵸', isDeposited: false}, {id: 2, name: '백호', isDeposited: true}, {id: 3, name: '감자', isDeposited: true}, + {id: 4, name: '이상', isDeposited: false}, + {id: 5, name: '소하', isDeposited: false}, + {id: 6, name: '웨디', isDeposited: false}, + {id: 7, name: '쿠키', isDeposited: false}, ], }; @@ -32,6 +36,18 @@ export let billData = { {id: 3, name: '감자'}, ], }, + { + bills: [{id: 4, title: '뽕쟁이족', price: 70000, isFixed: false}], + members: [ + {id: 1, name: '망쵸'}, + {id: 2, name: '백호'}, + {id: 3, name: '감자'}, + {id: 4, name: '이상'}, + {id: 5, name: '소하'}, + {id: 6, name: '웨디'}, + {id: 7, name: '쿠키'}, + ], + }, ], }; @@ -42,11 +58,13 @@ export let billDetailsData = { id: 1, memberName: '망쵸', price: 5000, + isFixed: false, }, { id: 2, memberName: '백호', price: 5000, + isFixed: false, }, ], }, @@ -56,11 +74,13 @@ export let billDetailsData = { id: 1, memberName: '망쵸', price: 10000, + isFixed: false, }, { id: 2, memberName: '백호', price: 10000, + isFixed: false, }, ], }, @@ -70,19 +90,33 @@ export let billDetailsData = { id: 1, memberName: '망쵸', price: 5000, + isFixed: false, }, { id: 2, memberName: '백호', price: 10000, + isFixed: true, }, { id: 2, memberName: '감자', price: 5000, + isFixed: false, }, ], }, + '4': { + billDetails: [ + {id: 1, memberName: '망쵸', price: 10000, isFixed: false}, + {id: 2, memberName: '백호', price: 10000, isFixed: false}, + {id: 3, memberName: '감자', price: 10000, isFixed: false}, + {id: 4, memberName: '이상', price: 10000, isFixed: false}, + {id: 5, memberName: '소하', price: 10000, isFixed: false}, + {id: 6, memberName: '웨디', price: 10000, isFixed: false}, + {id: 7, memberName: '쿠키', price: 10000, isFixed: false}, + ], + }, }; export let reportData = { diff --git a/client/src/pages/EditBillPage/EditBillPage.tsx b/client/src/pages/EditBillPage/EditBillPage.tsx new file mode 100644 index 000000000..c9bf1448d --- /dev/null +++ b/client/src/pages/EditBillPage/EditBillPage.tsx @@ -0,0 +1,96 @@ +import {css} from '@emotion/react'; + +import AmountInput from '@components/AmountInput/AmountInput'; +import BillDetails from '@components/BillDetails/BillDetails'; +import NumberKeyboardBottomSheet from '@components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet'; +import Top from '@components/Design/components/Top/Top'; + +import useEditBillPage from '@hooks/useEditBillPage'; + +import {Back, FixedButton, Flex, MainLayout, TopNav} from '@components/Design'; + +const EditBillPage = () => { + const { + newBill, + newBillDetails, + billDetailsRef, + handleChangeBillTitle, + handleChangeBillPrice, + handleChangeBillDetails, + handleClickBillDetailInput, + handleClickDelete, + handleClickUpdate, + isPendingUpdate, + canSubmit, + keyboardInitialValue, + keyboardMaxPrice, + keyboardTargetId, + setKeyboardTargetId, + } = useEditBillPage(); + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > + <Top> + <Flex justifyContent="spaceBetween"> + <Top.EditableLine value={newBill.title} onChange={handleChangeBillTitle} /> + <Top.Line text="에서" /> + </Flex> + </Top> + <AmountInput + value={newBill.price.toLocaleString('ko-kr')} + onClick={() => handleClickBillDetailInput(0)} + underlined={true} + activated={keyboardTargetId === 0} + /> + + <BillDetails + ref={billDetailsRef} + billDetails={newBillDetails} + onClickInput={handleClickBillDetailInput} + activatedId={keyboardTargetId as number} + /> + </div> + {keyboardTargetId !== null && ( + <div + css={css` + height: 416px; + `} + content=" " + /> + )} + <FixedButton + disabled={!canSubmit} + onClick={handleClickUpdate} + onDeleteClick={handleClickDelete} + variants={isPendingUpdate() ? 'loading' : 'primary'} + > + 수정완료 + </FixedButton> + <NumberKeyboardBottomSheet + type="amount" + maxNumber={keyboardMaxPrice} + initialValue={keyboardInitialValue} + onChange={ + keyboardTargetId === 0 + ? handleChangeBillPrice + : (value: string) => handleChangeBillDetails({value, keyboardTargetId: keyboardTargetId ?? 0}) + } + isOpened={keyboardTargetId !== null} + onClose={() => setKeyboardTargetId(null)} + /> + </MainLayout> + ); +}; + +export default EditBillPage; diff --git a/client/src/router.tsx b/client/src/router.tsx index 566a07b7f..d6f812152 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -1,10 +1,11 @@ import {createBrowserRouter} from 'react-router-dom'; -import AddBillFunnel from '@pages/AddBillFunnel/AddBillFunnel'; import {AdminPage} from '@pages/EventPage/AdminPage'; import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; +import AddBillFunnel from '@pages/AddBillFunnel/AddBillFunnel'; +import EditBillPage from '@pages/EditBillPage/EditBillPage'; import CreateEventFunnel from '@pages/CreateEventPage/CreateEventFunnel'; import Account from '@pages/AccountPage/Account'; @@ -46,6 +47,10 @@ const router = createBrowserRouter([ path: ROUTER_URLS.addBill, element: <AddBillFunnel />, }, + { + path: ROUTER_URLS.editBill, + element: <EditBillPage />, + }, { path: ROUTER_URLS.eventEdit, element: <Account />, From 6afae59f1e9a635c1e7eeab42de4def21c2f355c Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:44:46 +0900 Subject: [PATCH 243/273] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20=EC=B0=B8?= =?UTF-8?q?=EC=97=AC=EC=9E=90=20=EA=B4=80=EB=A6=AC=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=ED=98=84=20(#595)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * design: 변경된 DepositToggle로 수정 * fix: toggle의 넓이가 맞지 않는 문제 해결 (원인: Text의 사이즈가 tiny로 되어있지 않아서) * chore: Design Components를 index.tsx에 추가 및 이에 따른 export/import 수정 * design: Icon 컴포넌트에 pencilMini와 trashMini 타입 추가 * design: DepositToggle height 고정 * design: 전체 참여자 관리 페이지 디자인 구현 * chore: 변경된 api 응답 요청에 맞게 name을 memberName으로 수정 * feat: member의 이름을 변경하는 기능 추가 * feat: member 삭제 기능 추가 * feat: isDeposited 변경 기능 구현 및 PUT 요청 형태에 맞게 changedMembers 상태 추가 * feat: 변경된 값(changedMembers)이 초기 상태와 동일할 경우, Put 요청에서 제외하도록 기능 추가 * feat: memberName의 최대 길이 유효성 검사 및 변경된 값만 저장하는 filteredChangedMembers 상태 추가 * feat: 중복된 이름이 존재할 경우 수정완료 버튼 비활성화 기능 추가 * chore: 불필요한 console.log 삭제 * feat: EventMemberManage 라우터 추가 * feat: memberName이 0일 경우 FixedButton 비활성화 기능 추가 * design: memberName input의 width를 98px로 고정 * design: input에 focus가 되었을 경우 borderBottom의 에 primary 색상으로 변경하기 * design: reports의 데이터가 존재하지 않을 때, 문구 추가 * design: reports의 값이 많아 뷰포트 높이를 넘어갈 경우 overflow 적용을 위해 css 수정 (FixedButton: z-index 추가, DepositToggle: position 변경) * remove: 사용하지 않는 useSetAllMemberList 훅 제거 * style: lint적용 * fix: 충돌 해결 * design: MainLayout 중복으로 padding이 이중으로 생기는 문제 해결 * fix: 변경된 api 구조에 따라 api 관련 코드 수정 * fix: 잘못된 navigate 경로 수정 * style: 사용하지 않는 코드 제거 * feat: dropdown route 적용 --------- Co-authored-by: 이태훈 <rhymint@gmail.com> --- client/src/apis/request/bill.ts | 4 +- client/src/assets/image/pencil_mini.svg | 3 + client/src/assets/image/trash_mini.svg | 3 + .../DepositToggle/DepositToggle.stories.tsx | 2 +- .../DepositToggle/DepositToggle.style.ts | 20 ++- .../DepositToggle/DepositToggle.tsx | 12 +- .../ExpenseList/ExpenseList.stories.tsx | 10 +- .../components/ExpenseList/ExpenseList.tsx | 15 +- .../ExpenseList/ExpenseList.type.ts | 2 +- .../FixedButton/FixedButton.style.ts | 1 + .../Design/components/Icon/Icon.stories.tsx | 14 +- .../Design/components/Icon/Icon.style.ts | 2 + .../Design/components/Icon/Icon.tsx | 6 +- .../Design/components/Icon/Icon.type.ts | 2 + client/src/components/Design/index.tsx | 6 + client/src/components/Reports/Reports.tsx | 9 +- client/src/constants/routerUrls.ts | 1 + .../queries/bill/useRequestGetBillDetails.ts | 2 +- client/src/hooks/useEditBillActions.ts | 2 +- client/src/hooks/useEditBillPage.ts | 2 +- client/src/hooks/useEventMember.ts | 151 ++++++++++++++++++ client/src/hooks/useReportsPage.ts | 8 +- .../useSearchReports/useSearchReports.tsx | 6 +- client/src/hooks/useSetAllMemberList.tsx | 100 ------------ client/src/mocks/sharedState.ts | 6 +- .../CompleteCreateEventStep.tsx | 31 ++-- .../pages/EventPage/AdminPage/AdminPage.tsx | 13 +- .../AdminPage/EventMemberManage.style.ts | 56 +++++++ .../EventPage/AdminPage/EventMemberManage.tsx | 105 ++++++++++++ client/src/router.tsx | 7 +- client/src/types/serviceType.ts | 4 +- .../src/utils/validate/validateMemberName.ts | 10 +- 32 files changed, 439 insertions(+), 176 deletions(-) create mode 100644 client/src/assets/image/pencil_mini.svg create mode 100644 client/src/assets/image/trash_mini.svg create mode 100644 client/src/hooks/useEventMember.ts delete mode 100644 client/src/hooks/useSetAllMemberList.tsx create mode 100644 client/src/pages/EventPage/AdminPage/EventMemberManage.style.ts create mode 100644 client/src/pages/EventPage/AdminPage/EventMemberManage.tsx diff --git a/client/src/apis/request/bill.ts b/client/src/apis/request/bill.ts index 374a199cf..f78a7e6b8 100644 --- a/client/src/apis/request/bill.ts +++ b/client/src/apis/request/bill.ts @@ -52,7 +52,7 @@ export const requestGetBillDetails = async ({ }: WithEventId<WithErrorHandlingStrategy<WithBillId>>) => { return requestGet<BillDetails>({ baseUrl: BASE_URL.HD, - endpoint: `${USER_API_PREFIX}/${eventId}/bills/${billId}/fixed`, + endpoint: `${USER_API_PREFIX}/${eventId}/bills/${billId}/details`, ...props, }); }; @@ -74,7 +74,7 @@ export const requestPutBillDetails = async ({ }: WithEventId<WithBillId<RequestPutBillDetails>>) => { await requestPut({ baseUrl: BASE_URL.HD, - endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills/${billId}/fixed`, + endpoint: `${ADMIN_API_PREFIX}/${eventId}/bills/${billId}/details`, body: {billDetails}, }); }; diff --git a/client/src/assets/image/pencil_mini.svg b/client/src/assets/image/pencil_mini.svg new file mode 100644 index 000000000..11a154e13 --- /dev/null +++ b/client/src/assets/image/pencil_mini.svg @@ -0,0 +1,3 @@ +<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M9.41075 2.48618L10.4623 1.4354C10.7411 1.15662 11.1192 1 11.5134 1C11.9077 1 12.2858 1.15662 12.5646 1.4354C12.8434 1.71419 13 2.0923 13 2.48656C13 2.88082 12.8434 3.25893 12.5646 3.53772L11.5138 4.58925M9.41075 2.48618L3.23507 8.66187C2.45129 9.44639 2.05903 9.8379 1.79202 10.3157C1.52502 10.7934 1.25651 11.9207 1 13C2.07853 12.7435 3.20657 12.475 3.68433 12.208C4.1621 11.941 4.55436 11.5487 5.33813 10.7649L11.5138 4.58925M9.41075 2.48618L11.5138 4.58925M6.25016 13H10.7503" stroke="#B2B1B6" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/client/src/assets/image/trash_mini.svg b/client/src/assets/image/trash_mini.svg new file mode 100644 index 000000000..16436f446 --- /dev/null +++ b/client/src/assets/image/trash_mini.svg @@ -0,0 +1,3 @@ +<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M5.13636 2.33333H7.86364C7.86364 1.94656 7.71997 1.57563 7.46424 1.30214C7.20851 1.02865 6.86166 0.875 6.5 0.875C6.13834 0.875 5.7915 1.02865 5.53576 1.30214C5.28003 1.57563 5.13636 1.94656 5.13636 2.33333ZM4.31818 2.33333C4.31818 1.71449 4.54805 1.121 4.95722 0.683418C5.36639 0.245833 5.92135 0 6.5 0C7.07865 0 7.63361 0.245833 8.04278 0.683418C8.45195 1.121 8.68182 1.71449 8.68182 2.33333H12.0909C12.1994 2.33333 12.3035 2.37943 12.3802 2.46147C12.4569 2.54352 12.5 2.6548 12.5 2.77083C12.5 2.88687 12.4569 2.99815 12.3802 3.08019C12.3035 3.16224 12.1994 3.20833 12.0909 3.20833H11.3764L10.7125 11.7267C10.6643 12.3464 10.4 12.9241 9.97209 13.3452C9.54422 13.7662 8.98401 14 8.40255 14H4.59745C4.016 14 3.45578 13.7662 3.02791 13.3452C2.60004 12.9241 2.33575 12.3464 2.28745 11.7267L1.62364 3.20833H0.909091C0.800593 3.20833 0.696539 3.16224 0.61982 3.08019C0.5431 2.99815 0.5 2.88687 0.5 2.77083C0.5 2.6548 0.5431 2.54352 0.61982 2.46147C0.696539 2.37943 0.800593 2.33333 0.909091 2.33333H4.31818ZM5.68182 5.6875C5.68182 5.57147 5.63872 5.46019 5.562 5.37814C5.48528 5.29609 5.38123 5.25 5.27273 5.25C5.16423 5.25 5.06018 5.29609 4.98346 5.37814C4.90674 5.46019 4.86364 5.57147 4.86364 5.6875V10.6458C4.86364 10.7619 4.90674 10.8731 4.98346 10.9552C5.06018 11.0372 5.16423 11.0833 5.27273 11.0833C5.38123 11.0833 5.48528 11.0372 5.562 10.9552C5.63872 10.8731 5.68182 10.7619 5.68182 10.6458V5.6875ZM7.72727 5.25C7.61878 5.25 7.51472 5.29609 7.438 5.37814C7.36128 5.46019 7.31818 5.57147 7.31818 5.6875V10.6458C7.31818 10.7619 7.36128 10.8731 7.438 10.9552C7.51472 11.0372 7.61878 11.0833 7.72727 11.0833C7.83577 11.0833 7.93982 11.0372 8.01654 10.9552C8.09326 10.8731 8.13636 10.7619 8.13636 10.6458V5.6875C8.13636 5.57147 8.09326 5.46019 8.01654 5.37814C7.93982 5.29609 7.83577 5.25 7.72727 5.25Z" fill="#56555A"/> +</svg> diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx b/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx index a86532eca..49a85d749 100644 --- a/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.stories.tsx @@ -3,7 +3,7 @@ import type {Meta, StoryObj} from '@storybook/react'; import {useEffect, useState} from 'react'; -import {DepositToggle} from './DepositToggle'; +import DepositToggle from './DepositToggle'; const meta = { title: 'Components/DepositToggle', diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts b/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts index a5ebce425..f90ff87ce 100644 --- a/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts @@ -7,31 +7,37 @@ import {DepositToggleStyleProps} from './DepositToggle.type'; export const depositToggleStyle = ({theme, isDeposit}: WithTheme<DepositToggleStyleProps>) => css({ display: `flex`, - flexDirection: 'column', + flexDirection: 'row', + justifyContent: 'center', padding: '0.25rem', borderRadius: '0.75rem', backgroundColor: theme.colors.tertiary, cursor: 'pointer', - width: '4rem', + alignItems: 'center', + width: '4.75rem', + height: '1.4375rem', '.deposit-text': { display: 'flex', justifyContent: 'center', borderRadius: '0.5rem', - padding: ' 0.125rem 0 0 0', + padding: '0 0.25rem', zIndex: '10', + height: '15px', + width: '34px', + paddingTop: '0.05rem', }, '.toggle-background': { - position: 'fixed', - width: '56px', - height: '20px', + position: 'absolute', + width: '34px', + height: '15px', borderRadius: '0.5rem', backgroundColor: theme.colors.white, transition: '0.2s', transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - transform: !isDeposit ? 'translateY(1.25rem)' : '', + transform: !isDeposit ? 'translateX(1.07rem)' : 'translateX(-1.06rem)', }, }); diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.tsx b/client/src/components/Design/components/DepositToggle/DepositToggle.tsx index a5fb4f30e..f68353ce5 100644 --- a/client/src/components/Design/components/DepositToggle/DepositToggle.tsx +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.tsx @@ -7,18 +7,20 @@ import Text from '../Text/Text'; import {DepositToggleProps} from './DepositToggle.type'; import {depositToggleStyle} from './DepositToggle.style'; -export const DepositToggle: React.FC<DepositToggleProps> = ({isDeposit = false, onToggle}: DepositToggleProps) => { +const DepositToggle: React.FC<DepositToggleProps> = ({isDeposit = false, onToggle}: DepositToggleProps) => { const {theme} = useTheme(); return ( <div css={depositToggleStyle({theme, isDeposit})} onClick={onToggle} role="button"> - <div className={'toggle-background'} content="" /> - <Text size="caption" textColor={isDeposit ? `onTertiary` : 'gray'} className="deposit-text"> - 입금 완료 + <div className="toggle-background" content="" /> + <Text size="tiny" textColor={isDeposit ? 'primary' : 'gray'} className="deposit-text"> + 입금 </Text> - <Text size="caption" textColor={isDeposit ? `gray` : 'error'} className="deposit-text"> + <Text size="tiny" textColor={isDeposit ? 'gray' : 'error'} className="deposit-text"> 미입금 </Text> </div> ); }; + +export default DepositToggle; diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx index af2a5af0d..ddaf1d50b 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.stories.tsx @@ -13,14 +13,14 @@ const meta = { }, }, args: { - name: '소하', + memberName: '소하', onSearch: () => console.log('쿠키'), placeholder: '안녕', expenseList: [ { memberId: 1, - name: '소하', + memberName: '소하', price: 2000, isDeposited: true, clipboardText: '토스은행 2000원', @@ -28,7 +28,7 @@ const meta = { }, { memberId: 2, - name: '토다리', + memberName: '토다리', price: 2000, isDeposited: false, clipboardText: '토스은행 2000원', @@ -36,7 +36,7 @@ const meta = { }, { memberId: 3, - name: '웨디', + memberName: '웨디', price: 1080, isDeposited: true, clipboardText: '토스은행 1080원', @@ -44,7 +44,7 @@ const meta = { }, { memberId: 4, - name: '쿠키', + memberName: '쿠키', price: 3020, isDeposited: false, clipboardText: '토스은행 3020원', diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx index 17d7a6ef5..cec6aa473 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx @@ -13,7 +13,14 @@ import DepositCheck from '../DepositCheck/DepositCheck'; import {ExpenseItemProps, ExpenseListProps} from './ExpenseList.type'; -function ExpenseItem({name, price, isDeposited, onBankButtonClick, clipboardText, ...divProps}: ExpenseItemProps) { +function ExpenseItem({ + memberName, + price, + isDeposited, + onBankButtonClick, + clipboardText, + ...divProps +}: ExpenseItemProps) { return ( <Flex justifyContent="spaceBetween" @@ -26,7 +33,7 @@ function ExpenseItem({name, price, isDeposited, onBankButtonClick, clipboardText <Flex gap="0.5rem" alignItems="center"> <DepositCheck isDeposited={isDeposited} /> <Text size="bodyBold" color="onTertiary"> - {name} + {memberName} </Text> </Flex> <Flex alignItems="center" gap="0.5rem"> @@ -47,7 +54,7 @@ function ExpenseItem({name, price, isDeposited, onBankButtonClick, clipboardText ); } -function ExpenseList({name, onSearch, placeholder, expenseList = []}: ExpenseListProps) { +function ExpenseList({memberName, onSearch, placeholder, expenseList = []}: ExpenseListProps) { return ( <Flex flexDirection="column" @@ -59,7 +66,7 @@ function ExpenseList({name, onSearch, placeholder, expenseList = []}: ExpenseLis height="100%" otherStyle={{borderRadius: '1rem'}} > - <Input inputType="search" value={name} onChange={onSearch} placeholder={placeholder} /> + <Input inputType="search" value={memberName} onChange={onSearch} placeholder={placeholder} /> {expenseList.length !== 0 && expenseList.map(expense => <ExpenseItem key={expense.memberId} {...expense} />)} </Flex> ); diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts index 2340e38c1..90a44c842 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.type.ts @@ -8,7 +8,7 @@ export type ExpenseItemCustomProps = Report & { export type ExpenseItemProps = React.ComponentProps<'div'> & ExpenseItemCustomProps; export type ExpenseListProps = { - name: string; + memberName: string; onSearch: ({target}: React.ChangeEvent<HTMLInputElement>) => void; placeholder: string; expenseList: ExpenseItemProps[]; diff --git a/client/src/components/Design/components/FixedButton/FixedButton.style.ts b/client/src/components/Design/components/FixedButton/FixedButton.style.ts index e93c348f8..e5bc5c1e0 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.style.ts +++ b/client/src/components/Design/components/FixedButton/FixedButton.style.ts @@ -14,6 +14,7 @@ export const fixedButtonContainerStyle = (theme: Theme) => margin: '0 auto', backgroundColor: theme.colors.white, boxSizing: 'border-box', + zIndex: '10', }); export const buttonContainerStyle = css({ diff --git a/client/src/components/Design/components/Icon/Icon.stories.tsx b/client/src/components/Design/components/Icon/Icon.stories.tsx index c3763b12d..bed06a579 100644 --- a/client/src/components/Design/components/Icon/Icon.stories.tsx +++ b/client/src/components/Design/components/Icon/Icon.stories.tsx @@ -13,7 +13,19 @@ const meta = { iconType: { description: '', control: {type: 'select'}, - options: ['inputDelete', 'buljusa', 'rightChevron', 'search', 'confirm', 'error', 'trash', 'check', 'x'], + options: [ + 'inputDelete', + 'buljusa', + 'rightChevron', + 'search', + 'confirm', + 'error', + 'trash', + 'trashMini', + 'check', + 'x', + 'pencilMini', + ], }, }, args: { diff --git a/client/src/components/Design/components/Icon/Icon.style.ts b/client/src/components/Design/components/Icon/Icon.style.ts index 1a8b237e5..fa08309ec 100644 --- a/client/src/components/Design/components/Icon/Icon.style.ts +++ b/client/src/components/Design/components/Icon/Icon.style.ts @@ -12,8 +12,10 @@ const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { confirm: 'complete', error: 'warn', trash: 'white', + trashMini: 'onTertiary', check: 'primary', x: 'gray', + pencilMini: 'gray', toss: 'white', meatballs: 'black', editPencil: 'gray', diff --git a/client/src/components/Design/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx index cfda8df8c..ae8f4b36d 100644 --- a/client/src/components/Design/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -6,10 +6,12 @@ import Buljusa from '@assets/image/buljusa.svg'; import Error from '@assets/image/error.svg'; import Confirm from '@assets/image/confirm.svg'; import Trash from '@assets/image/trash.svg'; +import TrashMini from '@assets/image/trash_mini.svg'; import Search from '@assets/image/search.svg'; import RightChevron from '@assets/image/rightChevron.svg'; import Check from '@assets/image/check.svg'; import X from '@assets/image/x.svg'; +import PencilMini from '@assets/image/pencil_mini.svg'; import Meatballs from '@assets/image/meatballs.svg'; import EditPencil from '@assets/image/editPencil.svg'; import {IconProps} from '@HDcomponents/Icon/Icon.type'; @@ -25,9 +27,11 @@ const ICON = { error: <Error />, confirm: <Confirm />, trash: <Trash />, - toss: <img src={Toss} width="16" height="16" alt="toss icon" />, + trashMini: <TrashMini />, check: <Check />, x: <X />, + pencilMini: <PencilMini />, + toss: <img src={Toss} width="16" height="16" alt="toss icon" />, meatballs: <Meatballs />, editPencil: <EditPencil />, }; diff --git a/client/src/components/Design/components/Icon/Icon.type.ts b/client/src/components/Design/components/Icon/Icon.type.ts index cc1fed148..580f0e919 100644 --- a/client/src/components/Design/components/Icon/Icon.type.ts +++ b/client/src/components/Design/components/Icon/Icon.type.ts @@ -9,8 +9,10 @@ export type IconType = | 'error' | 'confirm' | 'trash' + | 'trashMini' | 'check' | 'x' + | 'pencilMini' | 'toss' | 'meatballs' | 'editPencil'; diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx index 8ba2d1d0e..eed1b359e 100644 --- a/client/src/components/Design/index.tsx +++ b/client/src/components/Design/index.tsx @@ -26,6 +26,9 @@ import TextButton from './components/TextButton/TextButton'; import Title from './components/Title/Title'; import Back from './components/TopNav/Back'; import TopNav from './components/TopNav/TopNav'; +import DepositCheck from './components/DepositCheck/DepositCheck'; +import DepositToggle from './components/DepositToggle/DepositToggle'; +import Amount from './components/Amount/Amount'; import Dropdown from './components/Dropdown/Dropdown'; import DropdownButton from './components/Dropdown/DropdownButton'; @@ -59,6 +62,9 @@ export { ContentLayout, HDesignProvider, useTheme, + DepositCheck, + DepositToggle, + Amount, Dropdown, DropdownButton, }; diff --git a/client/src/components/Reports/Reports.tsx b/client/src/components/Reports/Reports.tsx index cdd6d6bea..74b59dbb9 100644 --- a/client/src/components/Reports/Reports.tsx +++ b/client/src/components/Reports/Reports.tsx @@ -5,7 +5,7 @@ import useReportsPage from '@hooks/useReportsPage'; import {ExpenseList, Flex} from '@HDesign/index'; const Reports = () => { - const {isEmpty, expenseListProp, name, changeName} = useReportsPage(); + const {isEmpty, expenseListProp, memberName, changeName} = useReportsPage(); if (isEmpty) { return <BillEmptyFallback />; @@ -13,7 +13,12 @@ const Reports = () => { return ( <Flex flexDirection="column" gap="0.5rem"> - <ExpenseList name={name} onSearch={changeName} placeholder="이름 검색" expenseList={expenseListProp} /> + <ExpenseList + memberName={memberName} + onSearch={changeName} + placeholder="이름 검색" + expenseList={expenseListProp} + /> </Flex> ); }; diff --git a/client/src/constants/routerUrls.ts b/client/src/constants/routerUrls.ts index cb5d946b1..6be509841 100644 --- a/client/src/constants/routerUrls.ts +++ b/client/src/constants/routerUrls.ts @@ -5,6 +5,7 @@ export const ROUTER_URLS = { eventLogin: '/event/:eventId/login', eventManage: '/event/:eventId/admin', home: '/event/:eventId/home', + member: '/event/:eventId/admin/member', addBill: '/event/:eventId/add-bill', editBill: '/event/:eventId/edit-bill', eventEdit: 'event/:eventId/admin/edit', diff --git a/client/src/hooks/queries/bill/useRequestGetBillDetails.ts b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts index 26dae0c39..e59b10437 100644 --- a/client/src/hooks/queries/bill/useRequestGetBillDetails.ts +++ b/client/src/hooks/queries/bill/useRequestGetBillDetails.ts @@ -20,7 +20,7 @@ const useRequestGetBillDetails = ({billId, ...props}: WithErrorHandlingStrategy< }); return { - billDetails: data?.billDetails ?? [], + members: data?.members ?? [], ...rest, }; }; diff --git a/client/src/hooks/useEditBillActions.ts b/client/src/hooks/useEditBillActions.ts index 52c925484..2b8ba9418 100644 --- a/client/src/hooks/useEditBillActions.ts +++ b/client/src/hooks/useEditBillActions.ts @@ -55,7 +55,7 @@ const useEditBillActions = ({bill, billDetails, newBill, newBillDetails}: Props) useEffect(() => { if (isSuccessDeleteBill || isSusseccPutBillDetails || (isSuccessPutBill && !isBillDetailsChanged)) { - navigate(`/events/${eventId}/admin`); + navigate(`/event/${eventId}/admin`); } }, [isSuccessDeleteBill, isSusseccPutBillDetails, isSuccessPutBill, isBillDetailsChanged]); diff --git a/client/src/hooks/useEditBillPage.ts b/client/src/hooks/useEditBillPage.ts index 397328b7b..96d9bf25e 100644 --- a/client/src/hooks/useEditBillPage.ts +++ b/client/src/hooks/useEditBillPage.ts @@ -11,7 +11,7 @@ const useEditBillPage = () => { const location = useLocation(); const bill: Bill = location.state.bill; - const {billDetails} = useRequestGetBillDetails({billId: Number(bill.id)}); + const {members: billDetails} = useRequestGetBillDetails({billId: bill.id}); const {newBill, newBillDetails, handleChangeBillPrice, handleChangeBillTitle, handleChangeBillDetails} = useEditBillState({bill, billDetails}); diff --git a/client/src/hooks/useEventMember.ts b/client/src/hooks/useEventMember.ts new file mode 100644 index 000000000..7cde434a8 --- /dev/null +++ b/client/src/hooks/useEventMember.ts @@ -0,0 +1,151 @@ +import {useEffect, useState} from 'react'; + +import {Reports, Report, AllMembers, MemberWithDeposited} from 'types/serviceType'; +import validateMemberName from '@utils/validate/validateMemberName'; + +import useRequestDeleteMember from './queries/member/useRequestDeleteMember'; +import useRequestPutMembers from './queries/member/useRequestPutMembers'; +import useRequestGetReports from './queries/report/useRequestGetReports'; + +interface ReturnUseEventMember { + reports: Report[]; + isCanRequest: boolean; + changeMemberName: (memberId: number, newName: string) => void; + toggleDepositStatus: (memberId: number) => void; + handleDeleteMember: (memberId: number) => void; + updateMembersOnServer: () => void; +} + +const useEventMember = (): ReturnUseEventMember => { + const {reports: initialReports} = useRequestGetReports(); + const {deleteMember} = useRequestDeleteMember(); + const {putMember} = useRequestPutMembers(); + + const [reports, setReports] = useState<Report[]>(initialReports); + const [deleteMembers, setDeleteMembers] = useState<number[]>([]); + const [changedMembers, setChangedMembers] = useState<MemberWithDeposited[]>([]); + const [isCanRequest, setIsCanRequest] = useState<boolean>(false); + const [filteredChangedMembers, setFilteredChangedMembers] = useState<MemberWithDeposited[]>([]); + + useEffect(() => { + setReports(initialReports); + }, [initialReports]); + + useEffect(() => { + const changedMembers = getChangedMembers(); + + // 중복된 이름이 존재할 경우 isCanRequest를 false로 변경 + if (hasDuplicateMemberName()) { + setIsCanRequest(false); + } else { + // 변경된 사항이 존재하거나 삭제한 member가 존재한다면 isCanRequest를 true로 변경 + setIsCanRequest(changedMembers.length > 0 || deleteMembers.length > 0); + } + + // memberName 유효성 검사 (0글자) + const hasEmptyName = changedMembers.some(member => member.name.trim().length === 0); + if (hasEmptyName) setIsCanRequest(false); + + setFilteredChangedMembers(changedMembers); + }, [reports, changedMembers, deleteMembers]); + + const changeMemberName = (memberId: number, newName: string) => { + // 유효성 검사 (4글자) + if (!validateMemberName(newName).isValid) { + return; + } + + setReports(prevReports => + prevReports.map(report => (report.memberId === memberId ? {...report, memberName: newName} : report)), + ); + + setChangedMembers(prev => { + const existing = prev.find(member => member.id === memberId); + const isDeposited = reports.find(report => report.memberId === memberId)?.isDeposited ?? false; // 기본값 제공 + + if (existing) { + return prev.map(member => (member.id === memberId ? {...member, name: newName, isDeposited} : member)); + } + return [...prev, {id: memberId, name: newName, isDeposited}]; + }); + + setIsCanRequest(true); + }; + + const toggleDepositStatus = (memberId: number) => { + setReports(prevReports => + prevReports.map(report => + report.memberId === memberId ? {...report, isDeposited: !report.isDeposited} : report, + ), + ); + + setChangedMembers(prev => { + const existing = prev.find(member => member.id === memberId); + const name = reports.find(report => report.memberId === memberId)?.memberName ?? ''; // 기본값 제공 + const newIsDeposited = !reports.find(report => report.memberId === memberId)?.isDeposited ?? false; + + if (existing) { + return prev.map(member => (member.id === memberId ? {...member, isDeposited: newIsDeposited} : member)); + } + return [...prev, {id: memberId, name, isDeposited: newIsDeposited}]; + }); + + setIsCanRequest(true); + }; + + const handleDeleteMember = (memberId: number) => { + setDeleteMembers(prev => [memberId, ...prev]); + setReports(prevReports => prevReports.filter(report => report.memberId !== memberId)); + setChangedMembers(prev => prev.filter(member => member.id !== memberId)); + }; + + const updateMembersOnServer = () => { + // 삭제할 member(deleteMembers)가 존재한다면 Delete 요청 실행 + if (deleteMembers.length > 0) { + for (const id of deleteMembers) { + deleteMember({memberId: id}); + } + } + + // 변경된 값(filteredChangedMembers)이 존재한다면 PUT 요청 실행 + if (filteredChangedMembers.length > 0) { + putMember({members: filteredChangedMembers}); + } + }; + + const getChangedMembers = () => { + // 초기 상태에서 변경된 값이 존재하는 것만 filtering하여 return 한다. + + // 초기 상태에서 memberId를 키로 갖는 맵 생성 + const initialReportsMap = new Map(initialReports.map(report => [report.memberId, report])); + + // 변경된 값(changedMembers)에서 초기 상태와 동일한 값을 삭제 + const filteredChangedMembers = changedMembers.filter(changedMember => { + const initialMember = initialReportsMap.get(changedMember.id); + return ( + !initialMember || + initialMember.memberName !== changedMember.name || + initialMember.isDeposited !== changedMember.isDeposited + ); + }); + + return filteredChangedMembers; + }; + + const hasDuplicateMemberName = (): boolean => { + const nameCount: {[key: string]: number} = {}; + + for (const member of reports) { + if (nameCount[member.memberName]) { + return true; // 중복된 이름이 존재하면 즉시 true 반환 + } + nameCount[member.memberName] = 1; + } + + return false; // 중복된 이름이 없으면 false 반환 + }; + + return {reports, isCanRequest, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus}; +}; + +export default useEventMember; diff --git a/client/src/hooks/useReportsPage.ts b/client/src/hooks/useReportsPage.ts index 7dc7e2726..711027cf0 100644 --- a/client/src/hooks/useReportsPage.ts +++ b/client/src/hooks/useReportsPage.ts @@ -9,12 +9,12 @@ import {useSearchReports} from './useSearchReports'; import toast from './useToast/toast'; const useReportsPage = () => { - const [name, setName] = useState(''); + const [memberName, setMemberName] = useState(''); const {bankName, accountNumber} = useOutletContext<EventPageContextProps>(); - const {matchedReports, reports} = useSearchReports({name}); + const {matchedReports, reports} = useSearchReports({memberName}); const changeName = ({target}: React.ChangeEvent<HTMLInputElement>) => { - setName(target.value); + setMemberName(target.value); }; const onBankButtonClick = () => { @@ -41,7 +41,7 @@ const useReportsPage = () => { return { isEmpty, expenseListProp, - name, + memberName, changeName, }; }; diff --git a/client/src/hooks/useSearchReports/useSearchReports.tsx b/client/src/hooks/useSearchReports/useSearchReports.tsx index 3387c2303..25ce95cca 100644 --- a/client/src/hooks/useSearchReports/useSearchReports.tsx +++ b/client/src/hooks/useSearchReports/useSearchReports.tsx @@ -1,14 +1,14 @@ import useRequestGetReports from '@hooks/queries/report/useRequestGetReports'; type UseSearchReportsParams = { - name: string; + memberName: string; }; -const useSearchReports = ({name}: UseSearchReportsParams) => { +const useSearchReports = ({memberName}: UseSearchReportsParams) => { const {reports} = useRequestGetReports(); return { - matchedReports: reports.filter(memberReport => memberReport.name.includes(name)), + matchedReports: reports.filter(memberReport => memberReport.memberName.includes(memberName)), reports, }; }; diff --git a/client/src/hooks/useSetAllMemberList.tsx b/client/src/hooks/useSetAllMemberList.tsx deleted file mode 100644 index bf5580dd9..000000000 --- a/client/src/hooks/useSetAllMemberList.tsx +++ /dev/null @@ -1,100 +0,0 @@ -// import {useEffect, useState} from 'react'; - -// import {ValidateResult} from '@utils/validate/type'; -// import {MemberChange} from '@apis/request/member'; - -// import isArraysEqual from '@utils/isArraysEqual'; - -// import useDeleteAllMemberList from './queries/useRequestDeleteMember'; -// import usePutAllMemberList from './queries/useRequestPutMember'; -// import useInput from './useInput'; - -// interface UseSetAllMemberListProps { -// validateFunc: (name: string) => ValidateResult; -// allMemberList: string[]; -// handleCloseAllMemberListModal: () => void; -// } - -// interface UseSetAllMemberListReturns { -// editedAllMemberList: string[]; -// canSubmit: boolean; -// errorMessage: string; -// errorIndexList: number[]; -// handleNameChange: (index: number, event: React.ChangeEvent<HTMLInputElement>) => void; -// handleClickDeleteButton: (index: number) => Promise<void>; -// handlePutAllMemberList: () => Promise<void>; -// } - -// const useSetAllMemberList = ({ -// validateFunc, -// allMemberList, -// handleCloseAllMemberListModal, -// }: UseSetAllMemberListProps): UseSetAllMemberListReturns => { -// const initialInputList = allMemberList.map((name, index) => ({index, value: name})); -// const { -// inputList, -// errorMessage, -// errorIndexList, -// canSubmit, -// handleChange, -// setInputList: setEditedAllMemberList, -// setCanSubmit, -// } = useInput({validateFunc, initialInputList}); - -// const [deleteInOriginal, setDeleteInOriginal] = useState<string[]>(allMemberList); -// const [deleteMemberList, setDeleteMemberList] = useState<string[]>([]); - -// const {mutateAsync: deleteAllMemberList} = useDeleteAllMemberList(); -// const {mutate: putAllMemberList} = usePutAllMemberList(); - -// const editedAllMemberList = inputList.map(input => input.value); - -// useEffect(() => { -// setCanSubmit(!isArraysEqual(editedAllMemberList, allMemberList)); -// }, [editedAllMemberList]); - -// const handleNameChange = (index: number, event: React.ChangeEvent<HTMLInputElement>) => { -// const {value} = event.target; - -// handleChange(index, value); -// }; - -// const handleClickDeleteButton = async (index: number) => { -// const memberToDelete = editedAllMemberList[index]; - -// setDeleteMemberList(prev => [...prev, memberToDelete]); -// setDeleteInOriginal(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); -// setEditedAllMemberList(prev => [...prev.slice(0, index), ...prev.slice(index + 1)]); -// }; - -// const handlePutAllMemberList = async () => { -// // deleteMemberList가 비어있지 않은 경우에만 반복문 실행 (삭제 api 요청) -// if (deleteMemberList.length > 0) { -// for (const deleteMember of deleteMemberList) { -// await deleteAllMemberList({memberName: deleteMember}); -// } -// } - -// const editedMemberName: MemberChange[] = deleteInOriginal -// .map((originalName, index) => { -// if (editedAllMemberList[index] !== originalName) { -// return {before: originalName, after: editedAllMemberList[index]}; -// } -// return null; // 조건에 맞지 않으면 null을 반환 -// }) -// .filter(item => item !== null); // null인 항목을 필터링하여 제거 -// if (!isArraysEqual(editedAllMemberList, deleteInOriginal)) putAllMemberList({members: editedMemberName}); -// handleCloseAllMemberListModal(); -// }; - -// return { -// editedAllMemberList, -// canSubmit, -// errorMessage, -// errorIndexList, -// handleNameChange, -// handleClickDeleteButton, -// handlePutAllMemberList, -// }; -// }; -// export default useSetAllMemberList; diff --git a/client/src/mocks/sharedState.ts b/client/src/mocks/sharedState.ts index 488cff5aa..5f584092d 100644 --- a/client/src/mocks/sharedState.ts +++ b/client/src/mocks/sharedState.ts @@ -123,19 +123,19 @@ export let reportData = { reports: [ { memberId: 1, - name: '망쵸', + memberName: '망쵸', price: 20000, isDeposited: false, }, { memberId: 2, - name: '백호', + memberName: '백호', price: 25000, isDeposited: true, }, { memberId: 3, - name: '감자', + memberName: '감자', price: 5000, isDeposited: true, }, diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx index a2e19b5f7..7c2415c67 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx @@ -16,24 +16,21 @@ const CompleteCreateEventStep = ({eventToken}: CompleteCreateEventStepProps) => const navigate = useNavigate(); return ( - <MainLayout backgroundColor="white"> - <TopNav /> - <div - css={css` - display: flex; - flex-direction: column; - gap: 3rem; - padding: 1rem; - `} - > - <Top> - <Top.Line text="행사가 생성되었어요!" emphasize={['행사가 생성되었어요!']} /> - <Top.Line text="관리 페이지에서 정산을 시작하세요" emphasize={['정산을 시작하세요']} /> - </Top> - <RunningDog /> - </div> + <div + css={css` + display: flex; + flex-direction: column; + gap: 3rem; + padding: 1rem; + `} + > + <Top> + <Top.Line text="행사가 생성되었어요!" emphasize={['행사가 생성되었어요!']} /> + <Top.Line text="관리 페이지에서 정산을 시작하세요" emphasize={['정산을 시작하세요']} /> + </Top> + <RunningDog /> <FixedButton onClick={() => navigate(`${ROUTER_URLS.event}/${eventToken}/admin`)}>관리 페이지로 이동</FixedButton> - </MainLayout> + </div> ); }; diff --git a/client/src/pages/EventPage/AdminPage/AdminPage.tsx b/client/src/pages/EventPage/AdminPage/AdminPage.tsx index 24d9cfde0..c69170897 100644 --- a/client/src/pages/EventPage/AdminPage/AdminPage.tsx +++ b/client/src/pages/EventPage/AdminPage/AdminPage.tsx @@ -30,8 +30,11 @@ const AdminPage = () => { }, [postAuthenticate]); const navigateAccountInputPage = () => { - // TODO:(@cookie) 569 브랜치가 머지된 후에 작업 가능합니다. - navigate('/'); + navigate(`/event/${eventId}/admin/edit`); + }; + + const navigateEventMemberManage = () => { + navigate(`/event/${eventId}/admin/member`); }; return ( @@ -41,13 +44,13 @@ const AdminPage = () => { amount={totalExpenseAmount} dropdown={ <Dropdown> - <DropdownButton text="전체 참여자 관리" /> - <DropdownButton text="계좌번호 입력하기" /> + <DropdownButton text="전체 참여자 관리" onClick={navigateEventMemberManage} /> + <DropdownButton text="계좌번호 입력하기" onClick={navigateAccountInputPage} /> </Dropdown> } /> <StepList data={steps ?? []} isAdmin={isAdmin} /> - <Button size="medium" onClick={() => navigate(`/event/${eventId}/addBill`)} style={{width: '100%'}}> + <Button size="medium" onClick={() => navigate(`/event/${eventId}/add-bill`)} style={{width: '100%'}}> 지출내역 추가하기 </Button> </section> diff --git a/client/src/pages/EventPage/AdminPage/EventMemberManage.style.ts b/client/src/pages/EventPage/AdminPage/EventMemberManage.style.ts new file mode 100644 index 000000000..1fcbc3fd3 --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/EventMemberManage.style.ts @@ -0,0 +1,56 @@ +import {css} from '@emotion/react'; + +import {Theme} from '@components/Design/theme/theme.type'; +import TYPOGRAPHY from '@components/Design/token/typography'; + +export const eventMemberMangeStyle = () => + css({ + padding: '0 1rem', + }); + +export const memberList = () => + css({ + display: 'flex', + flexDirection: 'column', + gap: '0.5rem', + padding: '0 0.5rem', + marginTop: '1rem', + height: 'inherit', + marginBottom: '100px', + }); + +export const noneReports = () => + css({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + height: 'inherit', + }); + +export const eventMember = () => + css({ + display: 'flex', + alignItems: 'center', + gap: '0.5rem', + padding: '0.5rem 0', + width: 'inherit', + justifyContent: 'space-between', + }); + +export const memberEditInput = (theme: Theme) => + css({ + input: { + width: '100%', + }, + width: '6.125rem', + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + borderBottom: `1px solid ${theme.colors.tertiary}`, + ...TYPOGRAPHY.bodyBold, + + '&:has(input:focus)': { + borderBottom: `1px solid ${theme.colors.primary}`, + }, + }); diff --git a/client/src/pages/EventPage/AdminPage/EventMemberManage.tsx b/client/src/pages/EventPage/AdminPage/EventMemberManage.tsx new file mode 100644 index 000000000..3be8dcf88 --- /dev/null +++ b/client/src/pages/EventPage/AdminPage/EventMemberManage.tsx @@ -0,0 +1,105 @@ +/** @jsxImportSource @emotion/react */ +import {Report} from 'types/serviceType'; + +import useEventMember from '@hooks/useEventMember'; + +import { + Back, + MainLayout, + TopNav, + Top, + Amount, + DepositToggle, + Icon, + IconButton, + FixedButton, + Text, +} from '@components/Design'; +import {useTheme} from '@components/Design'; + +import {eventMemberMangeStyle, memberList, eventMember, memberEditInput, noneReports} from './EventMemberManage.style'; + +const EventMemberManage = () => { + const {reports, isCanRequest, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus} = + useEventMember(); + + return ( + <MainLayout backgroundColor="white"> + <TopNav> + <Back /> + </TopNav> + <section css={eventMemberMangeStyle}> + <Top> + <Top.Line text="전체 참여자 관리" emphasize={['전체 참여자 관리']}></Top.Line> + </Top> + <div css={memberList}> + {reports.length === 0 ? ( + <div css={noneReports}> + <Text size="bodyBold">참여자가 존재하지 않아요!</Text> + <Text size="body" textColor="gray"> + 지출내역을 추가하면 참여자가 생성돼요. + </Text> + </div> + ) : ( + reports.map(member => { + return ( + <EventMember + key={member.memberId} + member={member} + changeMemberName={changeMemberName} + handleDeleteMember={handleDeleteMember} + toggleDepositStatus={toggleDepositStatus} + /> + ); + }) + )} + </div> + {reports.length === 0 ? ( + <></> + ) : ( + <FixedButton disabled={!isCanRequest} onClick={updateMembersOnServer} style={{zIndex: '100'}}> + 수정완료 + </FixedButton> + )} + </section> + </MainLayout> + ); +}; + +interface EventMemberProps { + member: Report; + changeMemberName: (memberId: number, newName: string) => void; + handleDeleteMember: (memberId: number) => void; + toggleDepositStatus: (memberId: number) => void; +} + +const EventMember = ({member, changeMemberName, handleDeleteMember, toggleDepositStatus}: EventMemberProps) => { + const {theme} = useTheme(); + + const handleChangeName = (e: React.ChangeEvent<HTMLInputElement>) => { + changeMemberName(member.memberId, e.target.value); + }; + + return ( + <div css={eventMember} id={`${member.memberId}`}> + <div css={memberEditInput(theme)}> + <input type="text" value={member.memberName} onChange={e => handleChangeName(e)} /> + <Icon iconType="pencilMini" /> + </div> + <div style={{display: 'flex', flexDirection: 'row', gap: '0.5rem'}}> + <Amount amount={member.price} /> + <DepositToggle isDeposit={member.isDeposited} onToggle={() => toggleDepositStatus(member.memberId)} /> + <IconButton + size="small" + variants="tertiary" + css={{width: '23px', height: '23px', borderRadius: '0.375rem'}} + onClick={() => handleDeleteMember(member.memberId)} + > + <Icon iconType="trashMini" /> + </IconButton> + </div> + </div> + ); +}; + +export default EventMemberManage; diff --git a/client/src/router.tsx b/client/src/router.tsx index d6f812152..56a4a006a 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -5,8 +5,9 @@ import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; import AddBillFunnel from '@pages/AddBillFunnel/AddBillFunnel'; -import EditBillPage from '@pages/EditBillPage/EditBillPage'; import CreateEventFunnel from '@pages/CreateEventPage/CreateEventFunnel'; +import EventMemberManage from '@pages/EventPage/AdminPage/EventMemberManage'; +import EditBillPage from '@pages/EditBillPage/EditBillPage'; import Account from '@pages/AccountPage/Account'; import {MainPage} from '@pages/MainPage'; @@ -47,6 +48,10 @@ const router = createBrowserRouter([ path: ROUTER_URLS.addBill, element: <AddBillFunnel />, }, + { + path: ROUTER_URLS.member, + element: <EventMemberManage />, + }, { path: ROUTER_URLS.editBill, element: <EditBillPage />, diff --git a/client/src/types/serviceType.ts b/client/src/types/serviceType.ts index 39fa19957..a2ecca3aa 100644 --- a/client/src/types/serviceType.ts +++ b/client/src/types/serviceType.ts @@ -26,7 +26,7 @@ export interface BillDetail { } export interface BillDetails { - billDetails: BillDetail[]; + members: BillDetail[]; } export interface Member { @@ -57,7 +57,7 @@ export interface Event { export interface Report { memberId: number; - name: string; + memberName: string; isDeposited: boolean; price: number; } diff --git a/client/src/utils/validate/validateMemberName.ts b/client/src/utils/validate/validateMemberName.ts index bb87122a2..b23ca74f2 100644 --- a/client/src/utils/validate/validateMemberName.ts +++ b/client/src/utils/validate/validateMemberName.ts @@ -16,15 +16,7 @@ const validateMemberName = (name: string): ValidateResult => { return true; }; - const validateEmpty = () => { - if (!name.trim().length) { - errorMessage = ERROR_MESSAGE.preventEmpty; - return false; - } - return true; - }; - - if (validateOnlyString() && validateLength() && validateEmpty()) { + if (validateOnlyString() && validateLength()) { return {isValid: true, errorMessage: null}; } From ef24cea8bb8f934a164e9c571439d96d767d4213 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:05:12 +0900 Subject: [PATCH 244/273] =?UTF-8?q?fix:=20=EA=B3=84=EC=A2=8C=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=20=ED=99=95=EC=9D=B8=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=ED=99=9C=EC=84=B1=ED=99=94=EA=B0=80=20=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B2=84=EA=B7=B8,=20?= =?UTF-8?q?=EB=B9=88=20=EA=B0=92=EC=9D=BC=20=EB=95=8C=20=EC=83=88=EB=A1=9C?= =?UTF-8?q?=EC=9A=B4=20=EA=B0=92=EC=9D=B4=20=EB=B0=98=EC=98=81=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B2=84=EA=B7=B8=20(#602)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: can submit 조건이 잘못됐던 버그 수정 * fix: 새로운 데이터가 빈 값인지를 체크하는 것으로 변경 --- client/src/hooks/useAccount.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/hooks/useAccount.ts b/client/src/hooks/useAccount.ts index 4e3e83dfc..288432800 100644 --- a/client/src/hooks/useAccount.ts +++ b/client/src/hooks/useAccount.ts @@ -30,11 +30,11 @@ const useAccount = () => { const getChangedField = () => { const changedField: Partial<Event> = {}; - if (bankName.trim() !== '' && bankName !== bankNameState) { + if (bankNameState.trim() !== '' && bankName !== bankNameState) { changedField.bankName = bankNameState; } - if (accountNumber.trim() !== '' && accountNumber !== accountNumberState) { + if (accountNumberState.trim() !== '' && accountNumber !== accountNumberState) { changedField.accountNumber = accountNumberState; } @@ -46,11 +46,11 @@ const useAccount = () => { }; useEffect(() => { - const existEmptyField = bankName.trim() === '' && accountNumber.trim() === ''; + const existEmptyField = bankNameState.trim() === '' || accountNumberState.trim() === ''; const isChanged = bankName !== bankNameState || accountNumber !== accountNumberState; setCanSubmit(!existEmptyField && isChanged); - }, [bankName, accountNumber, bankNameState, accountNumberState]); + }, [bankNameState, accountNumberState]); return { bankName: bankNameState, From 4a9e9a6ba784d989406afcca8d330e02659508ab Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:06:15 +0900 Subject: [PATCH 245/273] =?UTF-8?q?fix:=20=ED=99=88=EC=97=90=EC=84=9C?= =?UTF-8?q?=EB=8A=94=20=EC=A7=80=EC=B6=9C=20=EC=83=81=EC=84=B8=EB=A1=9C=20?= =?UTF-8?q?=EB=93=A4=EC=96=B4=EA=B0=80=EC=A7=80=20=EC=95=8A=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=84=A4=EC=A0=95=20(#604)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/StepList/Step.stories.tsx | 5 +++++ client/src/components/StepList/Step.tsx | 5 +++-- client/src/components/StepList/Steps.tsx | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/client/src/components/StepList/Step.stories.tsx b/client/src/components/StepList/Step.stories.tsx index f442aad39..0d2b64bb2 100644 --- a/client/src/components/StepList/Step.stories.tsx +++ b/client/src/components/StepList/Step.stories.tsx @@ -16,6 +16,10 @@ const meta = { step: { description: '', }, + isAdmin: { + description: '', + control: {type: 'boolean'}, + }, }, args: { step: { @@ -44,6 +48,7 @@ const meta = { }, ], }, + isAdmin: false, }, } satisfies Meta<typeof Step>; diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index 333994f47..6d719f2e7 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -12,13 +12,14 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; interface Prop { step: StepType; + isAdmin: boolean; } -const Step = ({step}: Prop) => { +const Step = ({step, isAdmin}: Prop) => { const navigate = useNavigate(); const eventId = getEventIdByUrl(); const handleClickStep = (bill: Bill) => { - navigate(`/event/${eventId}/edit-bill`, {state: {bill}}); + if (isAdmin) navigate(`/event/${eventId}/edit-bill`, {state: {bill}}); }; return ( diff --git a/client/src/components/StepList/Steps.tsx b/client/src/components/StepList/Steps.tsx index 0f1a525ad..308f9fda6 100644 --- a/client/src/components/StepList/Steps.tsx +++ b/client/src/components/StepList/Steps.tsx @@ -18,7 +18,7 @@ const Steps = ({data, isAdmin}: Props) => { return ( <Flex flexDirection="column" gap="0.5rem"> {data.map((step, index) => ( - <Step key={index} step={step} /> + <Step key={index} step={step} isAdmin={isAdmin} /> ))} </Flex> ); From 17337486da65b268eaa77e54916c217a19ec1e5c Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:06:47 +0900 Subject: [PATCH 246/273] =?UTF-8?q?fix:=20=EC=9E=85=EA=B8=88=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EB=A5=BC=20=EB=B3=80=EA=B2=BD=ED=95=98=EA=B3=A0=20'?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=99=84=EB=A3=8C'=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=20=EC=8B=9C,=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B2=84=EA=B7=B8=20=EB=B0=9C=EC=83=9D=20?= =?UTF-8?q?(#611)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 전체 참여자 delete,put 요청 mutate대신 mutateAsync를 사용하여 요청 순서 보장하기 * chore: mutateAsync를 사용한 곳 이름에 Async 추가하기 --- client/src/hooks/queries/member/useRequestDeleteMember.ts | 4 ++-- client/src/hooks/queries/member/useRequestPutMembers.ts | 4 ++-- client/src/hooks/useEventMember.ts | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/hooks/queries/member/useRequestDeleteMember.ts b/client/src/hooks/queries/member/useRequestDeleteMember.ts index ed3b191ba..770218e6b 100644 --- a/client/src/hooks/queries/member/useRequestDeleteMember.ts +++ b/client/src/hooks/queries/member/useRequestDeleteMember.ts @@ -10,7 +10,7 @@ const useRequestDeleteMember = () => { const eventId = getEventIdByUrl(); const queryClient = useQueryClient(); - const {mutate, ...rest} = useMutation({ + const {mutateAsync, ...rest} = useMutation({ mutationFn: ({memberId}: RequestDeleteMember) => requestDeleteMember({eventId, memberId}), onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); @@ -20,7 +20,7 @@ const useRequestDeleteMember = () => { }, }); - return {deleteMember: mutate, ...rest}; + return {deleteAsyncMember: mutateAsync, ...rest}; }; export default useRequestDeleteMember; diff --git a/client/src/hooks/queries/member/useRequestPutMembers.ts b/client/src/hooks/queries/member/useRequestPutMembers.ts index 656866a38..69df92c4c 100644 --- a/client/src/hooks/queries/member/useRequestPutMembers.ts +++ b/client/src/hooks/queries/member/useRequestPutMembers.ts @@ -10,7 +10,7 @@ const useRequestPutMembers = () => { const eventId = getEventIdByUrl(); const queryClient = useQueryClient(); - const {mutate, ...rest} = useMutation({ + const {mutateAsync, ...rest} = useMutation({ mutationFn: ({members}: RequestPutMembers) => requestPutMembers({eventId, members}), onSuccess: () => { queryClient.invalidateQueries({queryKey: [QUERY_KEYS.steps]}); @@ -20,7 +20,7 @@ const useRequestPutMembers = () => { }, }); - return {putMember: mutate, ...rest}; + return {putAsyncMember: mutateAsync, ...rest}; }; export default useRequestPutMembers; diff --git a/client/src/hooks/useEventMember.ts b/client/src/hooks/useEventMember.ts index 7cde434a8..54214723e 100644 --- a/client/src/hooks/useEventMember.ts +++ b/client/src/hooks/useEventMember.ts @@ -18,8 +18,8 @@ interface ReturnUseEventMember { const useEventMember = (): ReturnUseEventMember => { const {reports: initialReports} = useRequestGetReports(); - const {deleteMember} = useRequestDeleteMember(); - const {putMember} = useRequestPutMembers(); + const {deleteAsyncMember} = useRequestDeleteMember(); + const {putAsyncMember} = useRequestPutMembers(); const [reports, setReports] = useState<Report[]>(initialReports); const [deleteMembers, setDeleteMembers] = useState<number[]>([]); @@ -103,13 +103,13 @@ const useEventMember = (): ReturnUseEventMember => { // 삭제할 member(deleteMembers)가 존재한다면 Delete 요청 실행 if (deleteMembers.length > 0) { for (const id of deleteMembers) { - deleteMember({memberId: id}); + deleteAsyncMember({memberId: id}); } } // 변경된 값(filteredChangedMembers)이 존재한다면 PUT 요청 실행 if (filteredChangedMembers.length > 0) { - putMember({members: filteredChangedMembers}); + putAsyncMember({members: filteredChangedMembers}); } }; From 67532d80d2a808e06a5b770472cd84fa8de669cc Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:14:32 +0900 Subject: [PATCH 247/273] =?UTF-8?q?refactor:=20useEventMember=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=83=81=ED=83=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=8F=20=EB=A0=8C=EB=8D=94=EB=A7=81=20=EC=84=B1?= =?UTF-8?q?=EB=8A=A5=20=EA=B0=9C=EC=84=A0=20(#613)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 불필요한 상태(changedMembers) 제거 및 렌더링 성능 개선 * refactor: isCanRequest의 이름을 isCanSubmit으로 변경 * rename: EventMemberManage의 파일 이름을 EventMember로 변경 * refactor: delete와 put 요청에 await 추가 * refactor: 중복 이름 확인 로직을 set.length를 활용하여 간단하게 수정 * refactor: useCallback에 의존성 추가 --- client/src/hooks/useEventMember.ts | 146 +++++++----------- ...erManage.style.ts => EventMember.style.ts} | 2 +- ...{EventMemberManage.tsx => EventMember.tsx} | 18 +-- client/src/router.tsx | 4 +- 4 files changed, 66 insertions(+), 104 deletions(-) rename client/src/pages/EventPage/AdminPage/{EventMemberManage.style.ts => EventMember.style.ts} (96%) rename client/src/pages/EventPage/AdminPage/{EventMemberManage.tsx => EventMember.tsx} (80%) diff --git a/client/src/hooks/useEventMember.ts b/client/src/hooks/useEventMember.ts index 54214723e..617022db5 100644 --- a/client/src/hooks/useEventMember.ts +++ b/client/src/hooks/useEventMember.ts @@ -1,6 +1,6 @@ -import {useEffect, useState} from 'react'; +import {useEffect, useState, useCallback, useMemo} from 'react'; -import {Reports, Report, AllMembers, MemberWithDeposited} from 'types/serviceType'; +import {Report} from 'types/serviceType'; import validateMemberName from '@utils/validate/validateMemberName'; import useRequestDeleteMember from './queries/member/useRequestDeleteMember'; @@ -9,7 +9,7 @@ import useRequestGetReports from './queries/report/useRequestGetReports'; interface ReturnUseEventMember { reports: Report[]; - isCanRequest: boolean; + isCanSubmit: boolean; changeMemberName: (memberId: number, newName: string) => void; toggleDepositStatus: (memberId: number) => void; handleDeleteMember: (memberId: number) => void; @@ -23,84 +23,72 @@ const useEventMember = (): ReturnUseEventMember => { const [reports, setReports] = useState<Report[]>(initialReports); const [deleteMembers, setDeleteMembers] = useState<number[]>([]); - const [changedMembers, setChangedMembers] = useState<MemberWithDeposited[]>([]); - const [isCanRequest, setIsCanRequest] = useState<boolean>(false); - const [filteredChangedMembers, setFilteredChangedMembers] = useState<MemberWithDeposited[]>([]); useEffect(() => { setReports(initialReports); }, [initialReports]); - useEffect(() => { - const changedMembers = getChangedMembers(); + const isCanSubmit = useMemo(() => { + // 중복되는 이름이 존재하는지 확인 + const hasDuplicateMemberName = (): boolean => { + const nameSet = new Set(reports.map(member => member.memberName)); + return nameSet.size !== reports.length; + }; - // 중복된 이름이 존재할 경우 isCanRequest를 false로 변경 if (hasDuplicateMemberName()) { - setIsCanRequest(false); - } else { - // 변경된 사항이 존재하거나 삭제한 member가 존재한다면 isCanRequest를 true로 변경 - setIsCanRequest(changedMembers.length > 0 || deleteMembers.length > 0); + // 중복 이름이라면 false + return false; } - // memberName 유효성 검사 (0글자) - const hasEmptyName = changedMembers.some(member => member.name.trim().length === 0); - if (hasEmptyName) setIsCanRequest(false); - - setFilteredChangedMembers(changedMembers); - }, [reports, changedMembers, deleteMembers]); - - const changeMemberName = (memberId: number, newName: string) => { - // 유효성 검사 (4글자) - if (!validateMemberName(newName).isValid) { - return; - } + // 이름이 공백이라면 false + const hasEmptyName = reports.some(report => report.memberName.trim().length === 0); + if (hasEmptyName) return false; - setReports(prevReports => - prevReports.map(report => (report.memberId === memberId ? {...report, memberName: newName} : report)), + // 초기 값과 비교하여 변경된 사항이 존재하는지 확인 + const hasChanges = reports.some(report => + initialReports.find( + initial => + initial.memberId === report.memberId && + (initial.memberName !== report.memberName || initial.isDeposited !== report.isDeposited), + ), ); - setChangedMembers(prev => { - const existing = prev.find(member => member.id === memberId); - const isDeposited = reports.find(report => report.memberId === memberId)?.isDeposited ?? false; // 기본값 제공 + // 변경된 사항이 존재 혹은 삭제된 member가 존재한다면 true + return hasChanges || deleteMembers.length > 0; + }, [reports, initialReports, deleteMembers]); - if (existing) { - return prev.map(member => (member.id === memberId ? {...member, name: newName, isDeposited} : member)); + const changeMemberName = useCallback( + (memberId: number, newName: string) => { + // 유효성 검사 (4자 이하) + if (!validateMemberName(newName).isValid) { + return; } - return [...prev, {id: memberId, name: newName, isDeposited}]; - }); - setIsCanRequest(true); - }; + setReports(prevReports => + prevReports.map(report => (report.memberId === memberId ? {...report, memberName: newName} : report)), + ); + }, + [setReports, validateMemberName], + ); - const toggleDepositStatus = (memberId: number) => { + const toggleDepositStatus = useCallback((memberId: number) => { setReports(prevReports => prevReports.map(report => report.memberId === memberId ? {...report, isDeposited: !report.isDeposited} : report, ), ); + }, []); - setChangedMembers(prev => { - const existing = prev.find(member => member.id === memberId); - const name = reports.find(report => report.memberId === memberId)?.memberName ?? ''; // 기본값 제공 - const newIsDeposited = !reports.find(report => report.memberId === memberId)?.isDeposited ?? false; - - if (existing) { - return prev.map(member => (member.id === memberId ? {...member, isDeposited: newIsDeposited} : member)); - } - return [...prev, {id: memberId, name, isDeposited: newIsDeposited}]; - }); - - setIsCanRequest(true); - }; - - const handleDeleteMember = (memberId: number) => { + // 삭제할 member를 따로 deleteMembers 상태에서 id만 저장 + const handleDeleteMember = useCallback((memberId: number) => { setDeleteMembers(prev => [memberId, ...prev]); + // 삭제할 member들의 데이터를 reports에서 제거 setReports(prevReports => prevReports.filter(report => report.memberId !== memberId)); - setChangedMembers(prev => prev.filter(member => member.id !== memberId)); - }; + }, []); - const updateMembersOnServer = () => { - // 삭제할 member(deleteMembers)가 존재한다면 Delete 요청 실행 + const updateMembersOnServer = useCallback(async () => { + // DELETE 요청 선행 + // deleteMembers에 값이 하나라도 전재하면 반복문을 통해 DELETE api 요청 if (deleteMembers.length > 0) { for (const id of deleteMembers) { deleteAsyncMember({memberId: id}); @@ -108,44 +96,18 @@ const useEventMember = (): ReturnUseEventMember => { } // 변경된 값(filteredChangedMembers)이 존재한다면 PUT 요청 실행 - if (filteredChangedMembers.length > 0) { - putAsyncMember({members: filteredChangedMembers}); + if (reports.length > 0) { + putAsyncMember({ + members: reports.map(report => ({ + id: report.memberId, + name: report.memberName, + isDeposited: report.isDeposited, + })), + }); } - }; - - const getChangedMembers = () => { - // 초기 상태에서 변경된 값이 존재하는 것만 filtering하여 return 한다. - - // 초기 상태에서 memberId를 키로 갖는 맵 생성 - const initialReportsMap = new Map(initialReports.map(report => [report.memberId, report])); - - // 변경된 값(changedMembers)에서 초기 상태와 동일한 값을 삭제 - const filteredChangedMembers = changedMembers.filter(changedMember => { - const initialMember = initialReportsMap.get(changedMember.id); - return ( - !initialMember || - initialMember.memberName !== changedMember.name || - initialMember.isDeposited !== changedMember.isDeposited - ); - }); - - return filteredChangedMembers; - }; - - const hasDuplicateMemberName = (): boolean => { - const nameCount: {[key: string]: number} = {}; - - for (const member of reports) { - if (nameCount[member.memberName]) { - return true; // 중복된 이름이 존재하면 즉시 true 반환 - } - nameCount[member.memberName] = 1; - } - - return false; // 중복된 이름이 없으면 false 반환 - }; + }, [deleteMembers, reports, initialReports, deleteAsyncMember, putAsyncMember]); - return {reports, isCanRequest, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus}; + return {reports, isCanSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus}; }; export default useEventMember; diff --git a/client/src/pages/EventPage/AdminPage/EventMemberManage.style.ts b/client/src/pages/EventPage/AdminPage/EventMember.style.ts similarity index 96% rename from client/src/pages/EventPage/AdminPage/EventMemberManage.style.ts rename to client/src/pages/EventPage/AdminPage/EventMember.style.ts index 1fcbc3fd3..f59f288bd 100644 --- a/client/src/pages/EventPage/AdminPage/EventMemberManage.style.ts +++ b/client/src/pages/EventPage/AdminPage/EventMember.style.ts @@ -3,7 +3,7 @@ import {css} from '@emotion/react'; import {Theme} from '@components/Design/theme/theme.type'; import TYPOGRAPHY from '@components/Design/token/typography'; -export const eventMemberMangeStyle = () => +export const eventMemberStyle = () => css({ padding: '0 1rem', }); diff --git a/client/src/pages/EventPage/AdminPage/EventMemberManage.tsx b/client/src/pages/EventPage/AdminPage/EventMember.tsx similarity index 80% rename from client/src/pages/EventPage/AdminPage/EventMemberManage.tsx rename to client/src/pages/EventPage/AdminPage/EventMember.tsx index 3be8dcf88..a59f124f8 100644 --- a/client/src/pages/EventPage/AdminPage/EventMemberManage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventMember.tsx @@ -17,10 +17,10 @@ import { } from '@components/Design'; import {useTheme} from '@components/Design'; -import {eventMemberMangeStyle, memberList, eventMember, memberEditInput, noneReports} from './EventMemberManage.style'; +import {eventMemberStyle, memberList, eventMember, memberEditInput, noneReports} from './EventMember.style'; -const EventMemberManage = () => { - const {reports, isCanRequest, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus} = +const EventMember = () => { + const {reports, isCanSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus} = useEventMember(); return ( @@ -28,7 +28,7 @@ const EventMemberManage = () => { <TopNav> <Back /> </TopNav> - <section css={eventMemberMangeStyle}> + <section css={eventMemberStyle}> <Top> <Top.Line text="전체 참여자 관리" emphasize={['전체 참여자 관리']}></Top.Line> </Top> @@ -43,7 +43,7 @@ const EventMemberManage = () => { ) : ( reports.map(member => { return ( - <EventMember + <Member key={member.memberId} member={member} changeMemberName={changeMemberName} @@ -57,7 +57,7 @@ const EventMemberManage = () => { {reports.length === 0 ? ( <></> ) : ( - <FixedButton disabled={!isCanRequest} onClick={updateMembersOnServer} style={{zIndex: '100'}}> + <FixedButton disabled={!isCanSubmit} onClick={updateMembersOnServer} style={{zIndex: '100'}}> 수정완료 </FixedButton> )} @@ -66,14 +66,14 @@ const EventMemberManage = () => { ); }; -interface EventMemberProps { +interface MemberProps { member: Report; changeMemberName: (memberId: number, newName: string) => void; handleDeleteMember: (memberId: number) => void; toggleDepositStatus: (memberId: number) => void; } -const EventMember = ({member, changeMemberName, handleDeleteMember, toggleDepositStatus}: EventMemberProps) => { +const Member = ({member, changeMemberName, handleDeleteMember, toggleDepositStatus}: MemberProps) => { const {theme} = useTheme(); const handleChangeName = (e: React.ChangeEvent<HTMLInputElement>) => { @@ -102,4 +102,4 @@ const EventMember = ({member, changeMemberName, handleDeleteMember, toggleDeposi ); }; -export default EventMemberManage; +export default EventMember; diff --git a/client/src/router.tsx b/client/src/router.tsx index 56a4a006a..735b09786 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -6,7 +6,7 @@ import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; import AddBillFunnel from '@pages/AddBillFunnel/AddBillFunnel'; import CreateEventFunnel from '@pages/CreateEventPage/CreateEventFunnel'; -import EventMemberManage from '@pages/EventPage/AdminPage/EventMemberManage'; +import EventMember from '@pages/EventPage/AdminPage/EventMember'; import EditBillPage from '@pages/EditBillPage/EditBillPage'; import Account from '@pages/AccountPage/Account'; @@ -50,7 +50,7 @@ const router = createBrowserRouter([ }, { path: ROUTER_URLS.member, - element: <EventMemberManage />, + element: <EventMember />, }, { path: ROUTER_URLS.editBill, From 7fe6b20bec72f2d976b1bc299dcc16e3dbe9e018 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:14:50 +0900 Subject: [PATCH 248/273] =?UTF-8?q?fix:=20FixedButton=20loading=20button?= =?UTF-8?q?=20layout=20=EA=B9=A8=EC=A7=80=EB=8A=94=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#624)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Design/components/FixedButton/FixedButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Design/components/FixedButton/FixedButton.tsx b/client/src/components/Design/components/FixedButton/FixedButton.tsx index f24120da1..28192cd33 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.tsx +++ b/client/src/components/Design/components/FixedButton/FixedButton.tsx @@ -40,7 +40,7 @@ export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElem {...htmlProps} > {variants === 'loading' ? ( - <Lottie animationData={loadingAnimation} loop={true} style={{width: 240, height: 20}} /> + <Lottie animationData={loadingAnimation} loop={true} style={{height: '1.25rem'}} /> ) : ( children )} From d5126ea07ab188b47a4cf9b0066d977a41ef28b1 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:19:56 +0900 Subject: [PATCH 249/273] =?UTF-8?q?refactor:=20=ED=99=88=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98?= =?UTF-8?q?=EC=97=90=20=EB=9E=9C=EB=94=A9=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99=ED=95=98=EB=8A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20TopNav=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EA=B0=9C=EC=84=A0=20(#627)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: 불필요한 directory 구조 한 단계 제거 (Common) * style: 행동디자인에서 Switch 바깥으로 분리 * refactor: TopNav 자유롭게 사용할 수 있도록 변경 * style: 디렉토리 구조 변하면서 생긴 import 수정 * style: 사용하지 않는 import 문 제거 * design: TextButton color onTertiary 추가 * remove: 사용하지 않게된 Switch 제거 * remove: 사용하지 않는 Back 컴포넌트 제거 * feat: 흔듯콘 아이콘 추가 * refactor: TopNav, NavElement를 사용해 navigate 책임 이동 * refactor: 변경된 TopNav 적용 * style: 콘솔 경고창 에러를 방지하기 위해 변경 * feat: noEmphasis prop 추가 (true일 때 강조되지 않음) * design: 마진 맞춰줌 * remove: navigate 기능이 들어오면서 스토리북에서 변경되는 것을 보여줄 수 없어서 스토리북에서 제거 * style: emotion css를 위한 추가 * style: NavElement -> NavItem으로 이름 변경 * Merge branch 'fe-dev' into feature/#614 --------- Co-authored-by: Soyeon Choe <soy2302ten@gmail.com> --- .../Design/components/Icon/Icon.style.ts | 1 + .../Design/components/Icon/Icon.tsx | 2 + .../Design/components/Icon/Icon.type.ts | 3 +- .../components/Switch/Switch.stories.tsx | 35 ------------ .../Design/components/Switch/Switch.style.ts | 6 -- .../Design/components/Switch/Switch.tsx | 24 -------- .../Design/components/Switch/Switch.type.ts | 5 -- .../components/TextButton/TextButton.tsx | 4 -- .../components/TextButton/TextButton.type.ts | 2 +- .../Design/components/TopNav/Back.tsx | 20 ------- .../Design/components/TopNav/NavItem.style.ts | 9 +++ .../Design/components/TopNav/NavItem.tsx | 55 +++++++++++++++++++ .../Design/components/TopNav/NavItem.type.ts | 14 +++++ .../components/TopNav/TopNav.stories.tsx | 50 ----------------- .../Design/components/TopNav/TopNav.style.ts | 9 --- .../Design/components/TopNav/TopNav.tsx | 25 ++++----- client/src/components/Design/index.tsx | 4 -- .../{Common => }/Logo/Logo.style.ts | 0 .../{Common => }/Logo/RunningDogLogo.tsx | 0 .../{Common => }/Logo/StandingDogLogo.tsx | 0 .../src/components/{Common => }/Logo/index.ts | 0 client/src/hooks/useEventPageLayout.ts | 3 - client/src/hooks/useNavSwitch.tsx | 42 -------------- client/src/pages/AccountPage/Account.tsx | 4 +- .../src/pages/AddBillFunnel/AddBillFunnel.tsx | 4 +- .../CompleteCreateEventStep.tsx | 7 ++- .../CreateEventPage/CreateEventFunnel.tsx | 8 ++- .../src/pages/EditBillPage/EditBillPage.tsx | 4 +- .../pages/EventPage/AdminPage/EventMember.tsx | 15 +---- .../src/pages/EventPage/EventPageLayout.tsx | 19 +++++-- .../pages/MainPage/Section/MainSection.tsx | 3 +- 31 files changed, 129 insertions(+), 248 deletions(-) delete mode 100644 client/src/components/Design/components/Switch/Switch.stories.tsx delete mode 100644 client/src/components/Design/components/Switch/Switch.style.ts delete mode 100644 client/src/components/Design/components/Switch/Switch.tsx delete mode 100644 client/src/components/Design/components/Switch/Switch.type.ts delete mode 100644 client/src/components/Design/components/TopNav/Back.tsx create mode 100644 client/src/components/Design/components/TopNav/NavItem.style.ts create mode 100644 client/src/components/Design/components/TopNav/NavItem.tsx create mode 100644 client/src/components/Design/components/TopNav/NavItem.type.ts delete mode 100644 client/src/components/Design/components/TopNav/TopNav.stories.tsx rename client/src/components/{Common => }/Logo/Logo.style.ts (100%) rename client/src/components/{Common => }/Logo/RunningDogLogo.tsx (100%) rename client/src/components/{Common => }/Logo/StandingDogLogo.tsx (100%) rename client/src/components/{Common => }/Logo/index.ts (100%) delete mode 100644 client/src/hooks/useNavSwitch.tsx diff --git a/client/src/components/Design/components/Icon/Icon.style.ts b/client/src/components/Design/components/Icon/Icon.style.ts index fa08309ec..43620715b 100644 --- a/client/src/components/Design/components/Icon/Icon.style.ts +++ b/client/src/components/Design/components/Icon/Icon.style.ts @@ -19,6 +19,7 @@ const ICON_DEFAULT_COLOR: Record<IconType, IconColor> = { toss: 'white', meatballs: 'black', editPencil: 'gray', + heundeut: 'gray', }; export const iconStyle = ({iconType, theme, iconColor}: IconStylePropsWithTheme) => { diff --git a/client/src/components/Design/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx index ae8f4b36d..d59a08bc4 100644 --- a/client/src/components/Design/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -14,6 +14,7 @@ import X from '@assets/image/x.svg'; import PencilMini from '@assets/image/pencil_mini.svg'; import Meatballs from '@assets/image/meatballs.svg'; import EditPencil from '@assets/image/editPencil.svg'; +import Heundeut from '@assets/image/heundeut.svg'; import {IconProps} from '@HDcomponents/Icon/Icon.type'; import {useTheme} from '@theme/HDesignProvider'; @@ -34,6 +35,7 @@ const ICON = { toss: <img src={Toss} width="16" height="16" alt="toss icon" />, meatballs: <Meatballs />, editPencil: <EditPencil />, + heundeut: <Heundeut />, }; export const Icon: React.FC<IconProps> = ({iconColor, iconType, ...htmlProps}: IconProps) => { diff --git a/client/src/components/Design/components/Icon/Icon.type.ts b/client/src/components/Design/components/Icon/Icon.type.ts index 580f0e919..4d92e73b5 100644 --- a/client/src/components/Design/components/Icon/Icon.type.ts +++ b/client/src/components/Design/components/Icon/Icon.type.ts @@ -15,7 +15,8 @@ export type IconType = | 'pencilMini' | 'toss' | 'meatballs' - | 'editPencil'; + | 'editPencil' + | 'heundeut'; export type IconColor = ColorKeys; diff --git a/client/src/components/Design/components/Switch/Switch.stories.tsx b/client/src/components/Design/components/Switch/Switch.stories.tsx deleted file mode 100644 index 870783682..000000000 --- a/client/src/components/Design/components/Switch/Switch.stories.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import type {Meta, StoryObj} from '@storybook/react'; - -import Switch from '@HDcomponents/Switch/Switch'; - -const meta = { - title: 'Components/Switch', - component: Switch, - tags: ['autodocs'], - parameters: { - layout: 'centered', - }, - argTypes: { - value: { - description: '', - control: {type: 'select', options: ['홈', '관리']}, - }, - values: { - description: '', - }, - onChange: { - description: '', - }, - }, - args: { - value: '홈', - values: ['홈', '관리'], - onChange: value => alert(`${value} 선택됨`), - }, -} satisfies Meta<typeof Switch>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = {}; diff --git a/client/src/components/Design/components/Switch/Switch.style.ts b/client/src/components/Design/components/Switch/Switch.style.ts deleted file mode 100644 index d88c18748..000000000 --- a/client/src/components/Design/components/Switch/Switch.style.ts +++ /dev/null @@ -1,6 +0,0 @@ -import {css} from '@emotion/react'; - -export const switchContainerStyle = css({ - display: 'flex', - gap: '0.75rem', -}); diff --git a/client/src/components/Design/components/Switch/Switch.tsx b/client/src/components/Design/components/Switch/Switch.tsx deleted file mode 100644 index 4a1275185..000000000 --- a/client/src/components/Design/components/Switch/Switch.tsx +++ /dev/null @@ -1,24 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import TextButton from '../TextButton/TextButton'; - -import {switchContainerStyle} from './Switch.style'; -import {SwitchProps} from './Switch.type'; - -function Switch({value, values, onChange}: SwitchProps) { - return ( - <div css={switchContainerStyle}> - {values.map((item, index) => ( - <TextButton - key={`${index}_${item}`} - textColor={value === item ? 'black' : 'gray'} - textSize="bodyBold" - onClick={() => onChange(values[index])} - > - {item} - </TextButton> - ))} - </div> - ); -} - -export default Switch; diff --git a/client/src/components/Design/components/Switch/Switch.type.ts b/client/src/components/Design/components/Switch/Switch.type.ts deleted file mode 100644 index 7e0d31d0f..000000000 --- a/client/src/components/Design/components/Switch/Switch.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface SwitchProps { - value: string; - values: string[]; - onChange: (value: string) => void; -} diff --git a/client/src/components/Design/components/TextButton/TextButton.tsx b/client/src/components/Design/components/TextButton/TextButton.tsx index 9e73667d5..f21fd6549 100644 --- a/client/src/components/Design/components/TextButton/TextButton.tsx +++ b/client/src/components/Design/components/TextButton/TextButton.tsx @@ -1,8 +1,6 @@ /** @jsxImportSource @emotion/react */ import {forwardRef} from 'react'; -import {useTheme} from '@theme/HDesignProvider'; - import Text from '../Text/Text'; import {TextButtonProps} from './TextButton.type'; @@ -11,8 +9,6 @@ export const TextButton: React.FC<TextButtonProps> = forwardRef<HTMLButtonElemen {textColor, textSize, children, ...htmlProps}: TextButtonProps, ref, ) { - const {theme} = useTheme(); - return ( <button ref={ref} {...htmlProps}> <Text size={textSize} textColor={textColor}> diff --git a/client/src/components/Design/components/TextButton/TextButton.type.ts b/client/src/components/Design/components/TextButton/TextButton.type.ts index 0299d89b9..5a1287734 100644 --- a/client/src/components/Design/components/TextButton/TextButton.type.ts +++ b/client/src/components/Design/components/TextButton/TextButton.type.ts @@ -1,6 +1,6 @@ import {TextSize} from '../Text/Text.type'; -export type TextColor = 'black' | 'gray'; +export type TextColor = 'black' | 'gray' | 'onTertiary'; export interface TextButtonStyleProps { textColor: TextColor; diff --git a/client/src/components/Design/components/TopNav/Back.tsx b/client/src/components/Design/components/TopNav/Back.tsx deleted file mode 100644 index 5bbd83618..000000000 --- a/client/src/components/Design/components/TopNav/Back.tsx +++ /dev/null @@ -1,20 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import {useNavigate} from 'react-router-dom'; - -import TextButton from '@HDcomponents/TextButton/TextButton'; - -type BackProps = { - onClick?: () => void; -}; - -function Back({onClick}: BackProps) { - const navigate = useNavigate(); - - return ( - <TextButton onClick={() => (onClick ? onClick() : navigate(-1))} textSize="bodyBold" textColor="gray"> - 뒤로가기 - </TextButton> - ); -} - -export default Back; diff --git a/client/src/components/Design/components/TopNav/NavItem.style.ts b/client/src/components/Design/components/TopNav/NavItem.style.ts new file mode 100644 index 000000000..eb65ca32f --- /dev/null +++ b/client/src/components/Design/components/TopNav/NavItem.style.ts @@ -0,0 +1,9 @@ +import {css} from '@emotion/react'; + +export const navItemStyle = css({ + padding: '0 0.5rem', + + ':first-of-type': { + paddingLeft: 0, + }, +}); diff --git a/client/src/components/Design/components/TopNav/NavItem.tsx b/client/src/components/Design/components/TopNav/NavItem.tsx new file mode 100644 index 000000000..41c38a150 --- /dev/null +++ b/client/src/components/Design/components/TopNav/NavItem.tsx @@ -0,0 +1,55 @@ +/** @jsxImportSource @emotion/react */ +import type {NavItemProps} from './NavItem.type'; + +import {useLocation, useNavigate} from 'react-router-dom'; + +import getDeletedLastPath from '@utils/getDeletedLastPath'; + +import TextButton from '../TextButton/TextButton'; + +import {navItemStyle} from './NavItem.style'; + +const NavItem = ({displayName, routePath, onHandleRouteInFunnel, noEmphasis = false, children}: NavItemProps) => { + const navigate = useNavigate(); + const location = useLocation(); + const matchPath = location.pathname.includes(routePath); + + const handleNavigation = () => { + if (onHandleRouteInFunnel) { + onHandleRouteInFunnel(); + return; + } + + switch (routePath) { + case '/': + navigate('/'); + break; + case '-1': + navigate(-1); + break; + default: + navigate(`${getDeletedLastPath(location.pathname)}${routePath}`); + break; + } + }; + + const getTextColor = () => { + if (noEmphasis) return 'gray'; + + return matchPath ? 'onTertiary' : 'gray'; + }; + + return ( + <li css={navItemStyle} onClick={handleNavigation}> + {children ? ( + children + ) : ( + <TextButton textColor={getTextColor()} textSize="bodyBold"> + {displayName} + </TextButton> + )} + </li> + ); +}; + +export default NavItem; diff --git a/client/src/components/Design/components/TopNav/NavItem.type.ts b/client/src/components/Design/components/TopNav/NavItem.type.ts new file mode 100644 index 000000000..d5b302468 --- /dev/null +++ b/client/src/components/Design/components/TopNav/NavItem.type.ts @@ -0,0 +1,14 @@ +export type NavItemOptionProps = { + displayName?: string; + onHandleRouteInFunnel?: () => void; +}; + +export type NavItemRequireProps = { + routePath: string; +}; + +export type NavItemStyleProps = { + noEmphasis?: boolean; +}; + +export type NavItemProps = NavItemRequireProps & NavItemOptionProps & NavItemStyleProps & React.PropsWithChildren; diff --git a/client/src/components/Design/components/TopNav/TopNav.stories.tsx b/client/src/components/Design/components/TopNav/TopNav.stories.tsx deleted file mode 100644 index 885ed4f5b..000000000 --- a/client/src/components/Design/components/TopNav/TopNav.stories.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import React from 'react'; -import {reactRouterParameters, withRouter} from 'storybook-addon-react-router-v6'; - -import TopNav from '@HDcomponents/TopNav/TopNav'; - -import Switch from '../Switch/Switch'; - -import Back from './Back'; - -const meta = { - title: 'Components/TopNav', - component: TopNav, - tags: ['autodocs'], - decorators: [withRouter], - parameters: { - reactRouter: reactRouterParameters({ - location: { - pathParams: { - eventId: '123123', - }, - }, - routing: {path: '/event/:eventId/home'}, - }), - // layout: 'centered', - }, - argTypes: { - children: { - description: '', - control: {type: 'select'}, - options: ['Back', 'Switch', 'Any'], - mapping: { - Back: <Back />, - Switch: <Switch values={['홈', '관리']} value="홈" onChange={value => console.log(value)} />, - Any: <div />, - }, - }, - }, - args: { - children: 'Back', - }, -} satisfies Meta<typeof TopNav>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = {}; diff --git a/client/src/components/Design/components/TopNav/TopNav.style.ts b/client/src/components/Design/components/TopNav/TopNav.style.ts index 9ca69c7b0..b0efc6695 100644 --- a/client/src/components/Design/components/TopNav/TopNav.style.ts +++ b/client/src/components/Design/components/TopNav/TopNav.style.ts @@ -7,12 +7,3 @@ export const topNavStyle = css({ padding: '0 1rem', width: '100%', }); - -export const topNavNonStyle = css({ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - padding: '0 1rem', - width: '100%', - height: '1.5rem', -}); diff --git a/client/src/components/Design/components/TopNav/TopNav.tsx b/client/src/components/Design/components/TopNav/TopNav.tsx index 1530322e9..91f0eba07 100644 --- a/client/src/components/Design/components/TopNav/TopNav.tsx +++ b/client/src/components/Design/components/TopNav/TopNav.tsx @@ -1,20 +1,19 @@ /** @jsxImportSource @emotion/react */ -import React from 'react'; +import NavItem from './NavItem'; +import {topNavStyle} from './TopNav.style'; -import Switch from '@HDcomponents/Switch/Switch'; - -import {topNavNonStyle, topNavStyle} from './TopNav.style'; -import Back from './Back'; +type TopNavProps = React.PropsWithChildren & { + Element?: React.ReactNode; +}; -const TopNav: React.FC<React.PropsWithChildren> = ({children}) => { - const hasBack = React.Children.toArray(children).some(child => React.isValidElement(child) && child.type === Back); - const hasSwitch = React.Children.toArray(children).some( - child => React.isValidElement(child) && child.type === Switch, +const TopNav = ({children}: TopNavProps) => { + return ( + <nav> + <ul css={topNavStyle}>{children}</ul> + </nav> ); - - const isExistNav = hasBack || hasSwitch; - - return <div css={isExistNav ? topNavStyle : topNavNonStyle}>{children}</div>; }; +TopNav.Item = NavItem; + export default TopNav; diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx index eed1b359e..a75245994 100644 --- a/client/src/components/Design/index.tsx +++ b/client/src/components/Design/index.tsx @@ -17,14 +17,12 @@ import Input from './components/Input/Input'; import LabelInput from './components/LabelInput/LabelInput'; import ListButton from './components/ListButton/ListButton'; import LabelGroupInput from './components/LabelGroupInput/LabelGroupInput'; -import Switch from './components/Switch/Switch'; import Top from './components/Top/Top'; import Tab from './components/Tabs/Tab'; import Tabs from './components/Tabs/Tabs'; import Text from './components/Text/Text'; import TextButton from './components/TextButton/TextButton'; import Title from './components/Title/Title'; -import Back from './components/TopNav/Back'; import TopNav from './components/TopNav/TopNav'; import DepositCheck from './components/DepositCheck/DepositCheck'; import DepositToggle from './components/DepositToggle/DepositToggle'; @@ -48,7 +46,6 @@ export { LabelInput, ListButton, LabelGroupInput, - Switch, Top, Tab, Tabs, @@ -56,7 +53,6 @@ export { TextButton, Title, TopNav, - Back, MainLayout, FunnelLayout, ContentLayout, diff --git a/client/src/components/Common/Logo/Logo.style.ts b/client/src/components/Logo/Logo.style.ts similarity index 100% rename from client/src/components/Common/Logo/Logo.style.ts rename to client/src/components/Logo/Logo.style.ts diff --git a/client/src/components/Common/Logo/RunningDogLogo.tsx b/client/src/components/Logo/RunningDogLogo.tsx similarity index 100% rename from client/src/components/Common/Logo/RunningDogLogo.tsx rename to client/src/components/Logo/RunningDogLogo.tsx diff --git a/client/src/components/Common/Logo/StandingDogLogo.tsx b/client/src/components/Logo/StandingDogLogo.tsx similarity index 100% rename from client/src/components/Common/Logo/StandingDogLogo.tsx rename to client/src/components/Logo/StandingDogLogo.tsx diff --git a/client/src/components/Common/Logo/index.ts b/client/src/components/Logo/index.ts similarity index 100% rename from client/src/components/Common/Logo/index.ts rename to client/src/components/Logo/index.ts diff --git a/client/src/hooks/useEventPageLayout.ts b/client/src/hooks/useEventPageLayout.ts index 4322d5c4c..57fea80d2 100644 --- a/client/src/hooks/useEventPageLayout.ts +++ b/client/src/hooks/useEventPageLayout.ts @@ -4,11 +4,9 @@ import getEventIdByUrl from '@utils/getEventIdByUrl'; import {ROUTER_URLS} from '@constants/routerUrls'; -import useNavSwitch from './useNavSwitch'; import useRequestGetEvent from './queries/event/useRequestGetEvent'; const useEventPageLayout = () => { - const navProps = useNavSwitch(); const eventId = getEventIdByUrl(); const {eventName, bankName, accountNumber} = useRequestGetEvent(); @@ -23,7 +21,6 @@ const useEventPageLayout = () => { return { eventId, - navProps, isAdmin, isLoginPage, eventOutline, diff --git a/client/src/hooks/useNavSwitch.tsx b/client/src/hooks/useNavSwitch.tsx deleted file mode 100644 index a622a7a30..000000000 --- a/client/src/hooks/useNavSwitch.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import {useEffect, useState} from 'react'; -import {useLocation, useNavigate} from 'react-router-dom'; - -const PATH_TABLE: Record<string, string> = { - 홈: 'home', - 관리: 'admin', -}; - -const PATH_DISPLAY_TABLE: Record<string, string> = { - home: '홈', - admin: '관리', -}; - -const useNavSwitch = () => { - const paths = ['홈', '관리']; - const location = useLocation(); - const navigate = useNavigate(); - - const pathArray = location.pathname.split('/'); - const basePath = pathArray.slice(0, -1).join('/'); - const lastPath = pathArray[pathArray.length - 1]; - - const [nav, setNav] = useState(PATH_DISPLAY_TABLE[lastPath]); - - useEffect(() => { - const isLogin = lastPath === 'login'; - setNav(isLogin ? '관리' : PATH_DISPLAY_TABLE[lastPath]); - }, [location]); - - const onChange = (displayName: string) => { - setNav(displayName); - navigate(`${basePath}/${PATH_TABLE[displayName]}`); - }; - - return { - nav, - paths, - onChange, - }; -}; - -export default useNavSwitch; diff --git a/client/src/pages/AccountPage/Account.tsx b/client/src/pages/AccountPage/Account.tsx index 1b7d685ff..29e389fe6 100644 --- a/client/src/pages/AccountPage/Account.tsx +++ b/client/src/pages/AccountPage/Account.tsx @@ -5,7 +5,7 @@ import BankSelectModal from '@components/Modal/BankSelectModal/BankSelectModal'; import useAccount from '@hooks/useAccount'; -import {Back, FixedButton, Flex, FunnelLayout, LabelInput, MainLayout, Top, TopNav} from '@components/Design'; +import {FixedButton, Flex, FunnelLayout, LabelInput, MainLayout, Top, TopNav} from '@components/Design'; import getDeletedLastPath from '@utils/getDeletedLastPath'; @@ -25,7 +25,7 @@ const Account = () => { return ( <MainLayout backgroundColor="white"> <TopNav> - <Back /> + <TopNav.Item displayName="뒤로가기" noEmphasis routePath="-1" /> </TopNav> <FunnelLayout> <Top> diff --git a/client/src/pages/AddBillFunnel/AddBillFunnel.tsx b/client/src/pages/AddBillFunnel/AddBillFunnel.tsx index a98b60919..acb13d698 100644 --- a/client/src/pages/AddBillFunnel/AddBillFunnel.tsx +++ b/client/src/pages/AddBillFunnel/AddBillFunnel.tsx @@ -2,7 +2,7 @@ import {Member} from 'types/serviceType'; import useAddBillFunnel from '@hooks/useAddBillFunnel'; -import {Back, MainLayout, TopNav} from '@components/Design'; +import {MainLayout, TopNav} from '@components/Design'; import PriceStep from './steps/PriceStep'; import {TitleStep} from './steps/TitleStep'; @@ -20,7 +20,7 @@ const AddBillFunnel = () => { return ( <MainLayout backgroundColor="white"> <TopNav> - <Back /> + <TopNav.Item displayName="뒤로가기" noEmphasis routePath="-1" /> </TopNav> {step === 'price' && <PriceStep billInfo={billInfo} setBillInfo={setBillInfo} setStep={setStep} />} {step === 'title' && <TitleStep billInfo={billInfo} setBillInfo={setBillInfo} setStep={setStep} />} diff --git a/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx index 7c2415c67..34ee64661 100644 --- a/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx +++ b/client/src/pages/CreateEventPage/CompleteCreateEventStep.tsx @@ -1,10 +1,11 @@ -import {useLocation, useNavigate} from 'react-router-dom'; +import {useNavigate} from 'react-router-dom'; import {css} from '@emotion/react'; -import {RunningDog} from '@components/Common/Logo'; import Top from '@components/Design/components/Top/Top'; -import {FixedButton, MainLayout, Title, TopNav} from '@HDesign/index'; +import {RunningDog} from '@components/Logo'; + +import {FixedButton} from '@HDesign/index'; import {ROUTER_URLS} from '@constants/routerUrls'; diff --git a/client/src/pages/CreateEventPage/CreateEventFunnel.tsx b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx index d9347a389..0b1bdf914 100644 --- a/client/src/pages/CreateEventPage/CreateEventFunnel.tsx +++ b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx @@ -3,7 +3,7 @@ import {useNavigate} from 'react-router-dom'; import useFunnel from '@hooks/useFunnel'; import useCreateEventData from '@hooks/useCreateEventData'; -import {Back, MainLayout, TopNav} from '@components/Design'; +import {MainLayout, TopNav} from '@components/Design'; import SetEventNameStep from './SetEventNameStep'; import SetEventPasswordStep from './SetEventPasswordStep'; @@ -31,7 +31,11 @@ const CreateEventFunnel = () => { return ( <MainLayout backgroundColor="white"> - <TopNav>{step !== STEP_SEQUENCE[STEP_SEQUENCE.length - 1] && <Back onClick={handleBack} />}</TopNav> + <TopNav> + {step !== STEP_SEQUENCE[STEP_SEQUENCE.length - 1] && ( + <TopNav.Item displayName="뒤로가기" noEmphasis routePath="" onHandleRouteInFunnel={handleBack} /> + )} + </TopNav> <Funnel> <Step name="eventName"> <SetEventNameStep moveToNextStep={moveToNextStep} {...eventNameProps} /> diff --git a/client/src/pages/EditBillPage/EditBillPage.tsx b/client/src/pages/EditBillPage/EditBillPage.tsx index c9bf1448d..75a02d755 100644 --- a/client/src/pages/EditBillPage/EditBillPage.tsx +++ b/client/src/pages/EditBillPage/EditBillPage.tsx @@ -7,7 +7,7 @@ import Top from '@components/Design/components/Top/Top'; import useEditBillPage from '@hooks/useEditBillPage'; -import {Back, FixedButton, Flex, MainLayout, TopNav} from '@components/Design'; +import {FixedButton, Flex, MainLayout, TopNav} from '@components/Design'; const EditBillPage = () => { const { @@ -31,7 +31,7 @@ const EditBillPage = () => { return ( <MainLayout backgroundColor="white"> <TopNav> - <Back /> + <TopNav.Item displayName="뒤로가기" noEmphasis routePath="-1" /> </TopNav> <div css={css` diff --git a/client/src/pages/EventPage/AdminPage/EventMember.tsx b/client/src/pages/EventPage/AdminPage/EventMember.tsx index a59f124f8..91fb8b276 100644 --- a/client/src/pages/EventPage/AdminPage/EventMember.tsx +++ b/client/src/pages/EventPage/AdminPage/EventMember.tsx @@ -3,18 +3,7 @@ import {Report} from 'types/serviceType'; import useEventMember from '@hooks/useEventMember'; -import { - Back, - MainLayout, - TopNav, - Top, - Amount, - DepositToggle, - Icon, - IconButton, - FixedButton, - Text, -} from '@components/Design'; +import {MainLayout, TopNav, Top, Amount, DepositToggle, Icon, IconButton, FixedButton, Text} from '@components/Design'; import {useTheme} from '@components/Design'; import {eventMemberStyle, memberList, eventMember, memberEditInput, noneReports} from './EventMember.style'; @@ -26,7 +15,7 @@ const EventMember = () => { return ( <MainLayout backgroundColor="white"> <TopNav> - <Back /> + <TopNav.Item displayName="뒤로가기" noEmphasis routePath="-1" /> </TopNav> <section css={eventMemberStyle}> <Top> diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index 3e33fedde..c0747a727 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -6,15 +6,14 @@ import useEventPageLayout from '@hooks/useEventPageLayout'; import {ShareEventButton} from '@components/ShareEventButton'; -import {MainLayout, TopNav, Switch} from '@HDesign/index'; +import {Flex, Icon, IconButton, MainLayout, TopNav} from '@HDesign/index'; export type EventPageContextProps = Event & { isAdmin: boolean; }; const EventPageLayout = () => { - const {navProps, isAdmin, isLoginPage, eventOutline} = useEventPageLayout(); - const {nav, paths, onChange} = navProps; + const {isAdmin, isLoginPage, eventOutline} = useEventPageLayout(); const outletContext: EventPageContextProps = { isAdmin, @@ -23,10 +22,18 @@ const EventPageLayout = () => { return ( <MainLayout backgroundColor="gray"> - <TopNav> - <Switch value={nav} values={paths} onChange={onChange} /> + <Flex justifyContent="spaceBetween" alignItems="center" margin="0 1rem 0 0"> + <TopNav> + <TopNav.Item routePath="/"> + <IconButton variants="none"> + <Icon iconType="heundeut" /> + </IconButton> + </TopNav.Item> + <TopNav.Item displayName="홈" routePath="/home" /> + <TopNav.Item displayName="관리" routePath="/admin" /> + </TopNav> {!isLoginPage && <ShareEventButton eventOutline={eventOutline} />} - </TopNav> + </Flex> <Outlet context={outletContext} /> </MainLayout> ); diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx index 5ae1dd8cb..3be031978 100644 --- a/client/src/pages/MainPage/Section/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -1,9 +1,10 @@ import {css, keyframes} from '@emotion/react'; import {useNavigate} from 'react-router-dom'; -import {StandingDog} from '@components/Common/Logo'; import ChevronDown from '@assets/image/chevronDownLarge.svg'; +import {StandingDog} from '@components/Logo'; + import {Button, Text} from '@HDesign/index'; import {ROUTER_URLS} from '@constants/routerUrls'; From bcae9bc4b3f5bba5240f50c6cbe3ea7498227c88 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:20:19 +0900 Subject: [PATCH 250/273] =?UTF-8?q?fix:=20=20=EC=B0=B8=EC=97=AC=EC=9D=B8?= =?UTF-8?q?=EC=9B=90=EC=9D=B4=20=EB=A7=8E=EC=9D=84=20=EB=95=8C,=20?= =?UTF-8?q?=EC=A7=80=EC=B6=9C=20=EB=82=B4=EC=97=AD=20=EC=B9=B4=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=A9=A4=EB=B2=84=20=EC=B9=A9=EC=9D=98=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=EC=9D=B4=20=EA=B9=A8?= =?UTF-8?q?=EC=A7=80=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20(#628)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 참여인원 많은 경우 멤버 칩 레이아웃 깨지는 문제 수정 * fix: step의 멤버 수가 많을 때 member ChipGroup 레이아웃 깨지던 문제 해결 * style: lint 적용 --- .../Design/components/ChipGroup/ChipGroup.style.ts | 2 ++ client/src/components/StepList/Step.tsx | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts b/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts index f85afd3af..fcd3433ee 100644 --- a/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts +++ b/client/src/components/Design/components/ChipGroup/ChipGroup.style.ts @@ -3,4 +3,6 @@ import {css} from '@emotion/react'; export const chipGroupStyle = css({ display: 'flex', gap: '0.25rem', + flexWrap: 'wrap', + overflow: 'hidden', }); diff --git a/client/src/components/StepList/Step.tsx b/client/src/components/StepList/Step.tsx index 6d719f2e7..997cf03c7 100644 --- a/client/src/components/StepList/Step.tsx +++ b/client/src/components/StepList/Step.tsx @@ -1,5 +1,6 @@ /** @jsxImportSource @emotion/react */ import {useNavigate} from 'react-router-dom'; +import {css} from '@emotion/react'; import Amount from '@components/Design/components/Amount/Amount'; import ChipGroup from '@components/Design/components/ChipGroup/ChipGroup'; @@ -26,7 +27,17 @@ const Step = ({step, isAdmin}: Prop) => { <ListItem> <ListItem.Row> <ChipGroup color="gray" texts={step.members.map(member => member.name)} /> - <Text size="caption" textColor="gray"> + + <Text + size="caption" + textColor="gray" + css={css` + flex-shrink: 0; + width: 2rem; + text-align: end; + margin-left: 0.5rem; + `} + > {step.members.length}명 </Text> </ListItem.Row> From feebdcad92277ddf62c760a95fed3cf88fc9d0c4 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:20:33 +0900 Subject: [PATCH 251/273] =?UTF-8?q?fix:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=B6=94=EA=B0=80=20=EB=8B=A8=EA=B3=84=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EA=B0=92=EC=9D=B4=200=EC=9D=BC=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=EC=9D=B4=20?= =?UTF-8?q?=EA=B9=A8=EC=A7=80=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#631)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/AmountInput/AmountInput.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/AmountInput/AmountInput.tsx b/client/src/components/AmountInput/AmountInput.tsx index 83ffc9e44..1169e6c4b 100644 --- a/client/src/components/AmountInput/AmountInput.tsx +++ b/client/src/components/AmountInput/AmountInput.tsx @@ -28,8 +28,8 @@ const AmountInput = ({value, onClick, underlined, activated}: Props) => { `} onClick={onClick} > - <Text size="head" textColor={value !== '0' ? 'black' : 'gray'}> - {value} + <Text size="head" textColor={value !== '' && value !== '0' ? 'black' : 'gray'}> + {value === '' ? '0' : value} </Text> <Text textColor="gray" From dff7f4f273b34e09472a9132fb7022c916fb313a Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:21:08 +0900 Subject: [PATCH 252/273] =?UTF-8?q?fix:=20NumberKeyboardBottomSheet=20?= =?UTF-8?q?=EC=98=81=EC=97=AD=EC=9D=84=20=EB=93=9C=EB=9E=98=EA=B7=B8=20?= =?UTF-8?q?=ED=96=88=EC=9D=84=20=EB=95=8C,=20=EB=92=B7=20=EC=98=81?= =?UTF-8?q?=EC=97=AD=EC=9D=B4=20=EC=8A=A4=ED=81=AC=EB=A1=A4=EB=90=98?= =?UTF-8?q?=EB=8D=98=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20(#633)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NumberKeyboardBottomSheet.tsx | 9 +++++- .../useNumberKeyboardBottomSheet.ts | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 client/src/components/Design/components/NumberKeyboard/useNumberKeyboardBottomSheet.ts diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx index 45b51ba8f..404a53d2b 100644 --- a/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx @@ -1,21 +1,26 @@ import {css} from '@emotion/react'; import {createPortal} from 'react-dom'; +import {useEffect, useRef} from 'react'; import {useTheme} from '@components/Design/theme/HDesignProvider'; import FixedButton from '../FixedButton/FixedButton'; import NumberKeyboard, {NumberKeyboardProps} from './NumberKeyboard'; +import useNumberKeyboardBottomSheet from './useNumberKeyboardBottomSheet'; interface Props extends NumberKeyboardProps { - isOpened?: boolean; + isOpened: boolean; onClose: () => void; } const NumberKeyboardBottomSheet = ({isOpened, onClose, ...props}: Props) => { const {theme} = useTheme(); + const {bottomSheetRef} = useNumberKeyboardBottomSheet({isOpened}); + return createPortal( <div + ref={bottomSheetRef} css={css` position: fixed; padding-bottom: 6.25rem; @@ -26,6 +31,8 @@ const NumberKeyboardBottomSheet = ({isOpened, onClose, ...props}: Props) => { gap: 1rem; bottom: 0; background-color: ${theme.colors.white}; + z-index: 20; + touch-action: none; transform: ${isOpened ? 'translate3d(0, 0, 0)' : 'translate3d(0, 100%, 0)'}; transition: 0.2s ease-in-out; diff --git a/client/src/components/Design/components/NumberKeyboard/useNumberKeyboardBottomSheet.ts b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboardBottomSheet.ts new file mode 100644 index 000000000..28e5cc6a3 --- /dev/null +++ b/client/src/components/Design/components/NumberKeyboard/useNumberKeyboardBottomSheet.ts @@ -0,0 +1,32 @@ +import {useEffect, useRef} from 'react'; + +interface Props { + isOpened: boolean; +} + +const useNumberKeyboardBottomSheet = ({isOpened}: Props) => { + const bottomSheetRef = useRef<HTMLDivElement>(null); + + useEffect(() => { + const bottomSheet = bottomSheetRef.current; + if (!bottomSheet) return; + + const preventScroll = (e: TouchEvent) => { + if (bottomSheet.contains(e.target as Node)) { + e.preventDefault(); + } + }; + + if (isOpened) { + document.addEventListener('touchmove', preventScroll, {passive: false}); + } + + return () => { + document.removeEventListener('touchmove', preventScroll); + }; + }, [isOpened]); + + return {bottomSheetRef}; +}; + +export default useNumberKeyboardBottomSheet; From 19b91a532d8da13b3e3cb07cfa79dea0a09a59d0 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:22:03 +0900 Subject: [PATCH 253/273] =?UTF-8?q?feat:=20=EA=B3=84=EC=A2=8C=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=20=EC=A0=9C=ED=95=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#634)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 계좌번호 입력 유효성 기능 추가 * feat: 계좌번호 유효성을 검증하고 input을 컨트롤하는 기능 추가 * style: console.log 제거 * feat: 계좌번호 정규표현식 수정 --------- Co-authored-by: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> --- client/src/constants/errorMessage.ts | 1 + client/src/constants/regExp.ts | 1 + client/src/constants/rule.ts | 2 + client/src/hooks/useAccount.ts | 42 ++++++++++++++++--- client/src/pages/AccountPage/Account.tsx | 19 ++++++--- .../utils/validate/validateAccountNumber.ts | 23 ++++++++++ 6 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 client/src/utils/validate/validateAccountNumber.ts diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index b33c12d5a..af59ee50d 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -45,6 +45,7 @@ export const ERROR_MESSAGE = { preventEmpty: '값은 비어있을 수 없어요', invalidInput: '올바르지 않은 입력이에요.', emptyBank: '계좌번호가 입력되지 않아서\n토스 송금 기능을 사용할 수 없어요', + invalidAccountNumber: '계좌번호는 8자에서 30자 사이로 입력 가능해요', }; export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; diff --git a/client/src/constants/regExp.ts b/client/src/constants/regExp.ts index d235c1f11..8a32f3755 100644 --- a/client/src/constants/regExp.ts +++ b/client/src/constants/regExp.ts @@ -3,6 +3,7 @@ const REGEXP = { eventUrl: /\/event\/([a-zA-Z0-9-]+)\//, billTitle: /^([ㄱ-ㅎ가-힣a-zA-Z0-9ㆍᆢ]\s?)*$/, memberName: /^([ㄱ-ㅎ가-힣a-zA-Zㆍᆢ]\s?)*$/, + accountNumber: /^\d+([\s\-]\d+)*[\s\-]?$/, }; export default REGEXP; diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts index 4b78031b9..f311dedea 100644 --- a/client/src/constants/rule.ts +++ b/client/src/constants/rule.ts @@ -3,6 +3,8 @@ const RULE = { maxEventPasswordLength: 4, maxMemberNameLength: 4, maxPrice: 10000000, + minAccountNumberLength: 8, + maxAccountNumberLength: 30, }; export default RULE; diff --git a/client/src/hooks/useAccount.ts b/client/src/hooks/useAccount.ts index 288432800..0c6ed13b3 100644 --- a/client/src/hooks/useAccount.ts +++ b/client/src/hooks/useAccount.ts @@ -2,15 +2,20 @@ import type {Event} from 'types/serviceType'; import {useEffect, useState} from 'react'; +import validateAccountNumber from '@utils/validate/validateAccountNumber'; + +import RULE from '@constants/rule'; + import useRequestPatchEvent from './queries/event/useRequestPatchEvent'; import useRequestGetEvent from './queries/event/useRequestGetEvent'; const useAccount = () => { const {bankName, accountNumber} = useRequestGetEvent(); - const [bankNameState, setBankName] = useState(bankName); const [accountNumberState, setAccountNumber] = useState(accountNumber); + const [accountNumberErrorMessage, setAccountNumberErrorMessage] = useState<string | null>(null); const [canSubmit, setCanSubmit] = useState(false); + const [isPasting, setIsPasting] = useState(false); useEffect(() => { setBankName(bankName); @@ -24,7 +29,32 @@ const useAccount = () => { }; const handleAccount = (event: React.ChangeEvent<HTMLInputElement>) => { - setAccountNumber(event.target.value); + if (isPasting) return; + + const newValue = event.target.value; + const {isValid, errorMessage} = validateAccountNumber(newValue); + setAccountNumberErrorMessage(errorMessage); + + const isValidMinLength = newValue.length >= RULE.minAccountNumberLength; + + if (isValid) { + setAccountNumber(event.target.value); + } else if (!isValid && !isValidMinLength) { + setAccountNumber(event.target.value.replace(/[^0-9\s\-]/g, '').trim()); + } + }; + + const handleAccountOnPaste = (event: React.ClipboardEvent<HTMLInputElement>) => { + setIsPasting(true); + + const value = `${accountNumberState}${event.clipboardData.getData('text')}`; + const newValue = value.replace(/[^0-9\s\-]/g, '').trim(); + const {isValid, errorMessage} = validateAccountNumber(newValue); + + setAccountNumberErrorMessage(errorMessage); + if (isValid) setAccountNumber(newValue); + + setTimeout(() => setIsPasting(false), 0); }; const getChangedField = () => { @@ -49,15 +79,17 @@ const useAccount = () => { const existEmptyField = bankNameState.trim() === '' || accountNumberState.trim() === ''; const isChanged = bankName !== bankNameState || accountNumber !== accountNumberState; - setCanSubmit(!existEmptyField && isChanged); - }, [bankNameState, accountNumberState]); - + setCanSubmit(!existEmptyField && isChanged && accountNumberErrorMessage === null); + }, [bankName, accountNumber, bankNameState, accountNumberState, accountNumberErrorMessage]); + return { bankName: bankNameState, accountNumber: accountNumberState, + accountNumberErrorMessage, canSubmit, selectBank, handleAccount, + handleAccountOnPaste, enrollAccount, }; }; diff --git a/client/src/pages/AccountPage/Account.tsx b/client/src/pages/AccountPage/Account.tsx index 29e389fe6..0490ead31 100644 --- a/client/src/pages/AccountPage/Account.tsx +++ b/client/src/pages/AccountPage/Account.tsx @@ -15,7 +15,16 @@ const Account = () => { const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false); - const {bankName, accountNumber, canSubmit, selectBank, handleAccount, enrollAccount} = useAccount(); + const { + bankName, + accountNumber, + accountNumberErrorMessage, + canSubmit, + selectBank, + handleAccount, + handleAccountOnPaste, + enrollAccount, + } = useAccount(); const enrollAccountAndNavigateAdmin = async () => { await enrollAccount(); @@ -40,19 +49,19 @@ const Account = () => { errorText={null} autoFocus={false} isAlwaysOnLabel - isAlwaysOnInputBorder readOnly onClick={() => setIsBottomSheetOpen(true)} /> <LabelInput labelText="계좌번호" - placeholder="030302-04-191806" - errorText={null} + placeholder="ex) 030302-04-191806" + errorText={accountNumberErrorMessage} + isError={accountNumberErrorMessage !== null} value={accountNumber ?? ''} onChange={handleAccount} + onPaste={handleAccountOnPaste} autoFocus={false} isAlwaysOnLabel - isAlwaysOnInputBorder /> {isBottomSheetOpen && ( <BankSelectModal diff --git a/client/src/utils/validate/validateAccountNumber.ts b/client/src/utils/validate/validateAccountNumber.ts new file mode 100644 index 000000000..fb100a22b --- /dev/null +++ b/client/src/utils/validate/validateAccountNumber.ts @@ -0,0 +1,23 @@ +import {ERROR_MESSAGE} from '@constants/errorMessage'; +import REGEXP from '@constants/regExp'; +import RULE from '@constants/rule'; + +import {ValidateResult} from './type'; + +const validateAccountNumber = (accountNumber: string): ValidateResult => { + const isValidateType = () => { + return REGEXP.accountNumber.test(accountNumber); + }; + + const isValidateLength = () => { + return accountNumber.length >= RULE.minAccountNumberLength && accountNumber.length <= RULE.maxAccountNumberLength; + }; + + if (isValidateType() && isValidateLength()) { + return {isValid: true, errorMessage: null}; + } + + return {isValid: false, errorMessage: ERROR_MESSAGE.invalidAccountNumber}; +}; + +export default validateAccountNumber; From b771c52645bda832ce05e04def0ffc4c425ef734 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:35:14 +0900 Subject: [PATCH 254/273] =?UTF-8?q?refactor:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=B0=B8=EC=97=AC=EC=9E=90=20=EA=B4=80=EB=A6=AC:=20'=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EC=99=84=EB=A3=8C'=EC=8B=9C,=20Toast=20=EB=9D=84?= =?UTF-8?q?=EC=9A=B0=EA=B8=B0=20(#636)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 불필요한 상태(changedMembers) 제거 및 렌더링 성능 개선 * refactor: isCanRequest의 이름을 isCanSubmit으로 변경 * rename: EventMemberManage의 파일 이름을 EventMember로 변경 * refactor: delete와 put 요청에 await 추가 * refactor: 중복 이름 확인 로직을 set.length를 활용하여 간단하게 수정 * feat: 수정이 완료되었을 경우 수정 완료 toast 띄우기 * fix: 백엔드 api 변경으로 put 요청 변경 * refactor: isCanSubmit 이름을 canSubmit으로 변경 * style: lint 적용 --- client/src/hooks/useAccount.ts | 2 +- client/src/hooks/useEventMember.ts | 24 +++++++++++-------- .../pages/EventPage/AdminPage/EventMember.tsx | 4 ++-- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/client/src/hooks/useAccount.ts b/client/src/hooks/useAccount.ts index 0c6ed13b3..418656cc5 100644 --- a/client/src/hooks/useAccount.ts +++ b/client/src/hooks/useAccount.ts @@ -81,7 +81,7 @@ const useAccount = () => { setCanSubmit(!existEmptyField && isChanged && accountNumberErrorMessage === null); }, [bankName, accountNumber, bankNameState, accountNumberState, accountNumberErrorMessage]); - + return { bankName: bankNameState, accountNumber: accountNumberState, diff --git a/client/src/hooks/useEventMember.ts b/client/src/hooks/useEventMember.ts index 617022db5..20ea319f1 100644 --- a/client/src/hooks/useEventMember.ts +++ b/client/src/hooks/useEventMember.ts @@ -3,13 +3,14 @@ import {useEffect, useState, useCallback, useMemo} from 'react'; import {Report} from 'types/serviceType'; import validateMemberName from '@utils/validate/validateMemberName'; +import toast from './useToast/toast'; import useRequestDeleteMember from './queries/member/useRequestDeleteMember'; import useRequestPutMembers from './queries/member/useRequestPutMembers'; import useRequestGetReports from './queries/report/useRequestGetReports'; interface ReturnUseEventMember { reports: Report[]; - isCanSubmit: boolean; + canSubmit: boolean; changeMemberName: (memberId: number, newName: string) => void; toggleDepositStatus: (memberId: number) => void; handleDeleteMember: (memberId: number) => void; @@ -28,7 +29,7 @@ const useEventMember = (): ReturnUseEventMember => { setReports(initialReports); }, [initialReports]); - const isCanSubmit = useMemo(() => { + const canSubmit = useMemo(() => { // 중복되는 이름이 존재하는지 확인 const hasDuplicateMemberName = (): boolean => { const nameSet = new Set(reports.map(member => member.memberName)); @@ -71,13 +72,16 @@ const useEventMember = (): ReturnUseEventMember => { [setReports, validateMemberName], ); - const toggleDepositStatus = useCallback((memberId: number) => { - setReports(prevReports => - prevReports.map(report => - report.memberId === memberId ? {...report, isDeposited: !report.isDeposited} : report, - ), - ); - }, []); + const toggleDepositStatus = useCallback( + (memberId: number) => { + setReports(prevReports => + prevReports.map(report => + report.memberId === memberId ? {...report, isDeposited: !report.isDeposited} : report, + ), + ); + }, + [setReports], + ); // 삭제할 member를 따로 deleteMembers 상태에서 id만 저장 const handleDeleteMember = useCallback((memberId: number) => { @@ -107,7 +111,7 @@ const useEventMember = (): ReturnUseEventMember => { } }, [deleteMembers, reports, initialReports, deleteAsyncMember, putAsyncMember]); - return {reports, isCanSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus}; + return {reports, canSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus}; }; export default useEventMember; diff --git a/client/src/pages/EventPage/AdminPage/EventMember.tsx b/client/src/pages/EventPage/AdminPage/EventMember.tsx index 91fb8b276..95a7d5482 100644 --- a/client/src/pages/EventPage/AdminPage/EventMember.tsx +++ b/client/src/pages/EventPage/AdminPage/EventMember.tsx @@ -9,7 +9,7 @@ import {useTheme} from '@components/Design'; import {eventMemberStyle, memberList, eventMember, memberEditInput, noneReports} from './EventMember.style'; const EventMember = () => { - const {reports, isCanSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus} = + const {reports, canSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus} = useEventMember(); return ( @@ -46,7 +46,7 @@ const EventMember = () => { {reports.length === 0 ? ( <></> ) : ( - <FixedButton disabled={!isCanSubmit} onClick={updateMembersOnServer} style={{zIndex: '100'}}> + <FixedButton disabled={!canSubmit} onClick={updateMembersOnServer} style={{zIndex: '100'}}> 수정완료 </FixedButton> )} From a930ad1078d2012a036e044b555b99dcd400e6e0 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:37:01 +0900 Subject: [PATCH 255/273] =?UTF-8?q?fix:=20=ED=96=89=EC=82=AC=EC=97=90=20?= =?UTF-8?q?=EB=82=98=EA=B0=94=EB=8D=98=20=EB=A9=A4=EB=B2=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=95=A0=20=EC=88=98=20=EC=97=86=EB=8D=98=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95=20(#637)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useMembersStep.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/hooks/useMembersStep.ts b/client/src/hooks/useMembersStep.ts index 9cd68f2a4..8f8aeb8f0 100644 --- a/client/src/hooks/useMembersStep.ts +++ b/client/src/hooks/useMembersStep.ts @@ -2,7 +2,7 @@ import {useEffect, useState} from 'react'; import {useNavigate} from 'react-router-dom'; import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; -import {Member} from 'types/serviceType'; +import {Member, AllMembers} from 'types/serviceType'; import getEventIdByUrl from '@utils/getEventIdByUrl'; @@ -11,6 +11,7 @@ import REGEXP from '@constants/regExp'; import useRequestPostMembers from './queries/member/useRequestPostMembers'; import useRequestPostBill from './queries/bill/useRequestPostBill'; import {BillStep} from './useAddBillFunnel'; +import useRequestGetAllMembers from './queries/member/useRequestGetAllMembers'; interface Props { billInfo: BillInfo; @@ -23,6 +24,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) const [errorMessage, setErrorMessage] = useState(''); const [nameInput, setNameInput] = useState(''); + const {members: allMembers} = useRequestGetAllMembers(); const {postMembersAsync, isPending: isPendingPostMembers} = useRequestPostMembers(); const {postBill, isSuccess: isSuccessPostBill, isPending: isPendingPostBill} = useRequestPostBill(); @@ -50,7 +52,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) const canSubmitMembers = billInfo.members.length !== 0; const setBillInfoMemberWithId = (name: string) => { - const existingMember = currentMembers.find(currentMember => currentMember.name === name); + const existingMember = allMembers.find(currentMember => currentMember.name === name); if (existingMember) { setBillInfo(prev => ({...prev, members: [...prev.members, {id: existingMember.id, name: name}]})); } else { From 6001f8e984b0b5a473b449e9a91419879976dc7e Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:37:22 +0900 Subject: [PATCH 256/273] =?UTF-8?q?fix:=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=EC=97=90=EC=84=9C=20font=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0=20(#638)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/GlobalStyle.ts | 253 +++++++++--------- .../components/Design/theme/GlobalStyle.ts | 25 ++ 2 files changed, 146 insertions(+), 132 deletions(-) diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index ab16de8e1..26eaea35c 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -2,159 +2,148 @@ import {css} from '@emotion/react'; // reset css -> index css export const GlobalStyle = css` - html, - body, - div, - span, - applet, - object, - iframe, - h1, - h2, - h3, - h4, - h5, - h6, - p, - blockquote, - pre, + @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'); + + *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { + all: unset; + display: revert; + } + + /* Preferred box-sizing value */ + *, + *::before, + *::after { + box-sizing: border-box; + } + + /* Fix mobile Safari increase font-size on landscape mode */ + html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; + } + + /* Reapply the pointer cursor for anchor tags */ a, - abbr, - acronym, - address, - big, - cite, - code, - del, - dfn, - em, - img, - ins, - kbd, - q, - s, - samp, - small, - strike, - strong, - sub, - sup, - tt, - b, - u, - i, - center, - dl, - dt, - dd, - ol, - ul, - li, - fieldset, - form, - label, - legend, - table, - caption, - tbody, - tfoot, - thead, - tr, - th, - td, - article, - aside, - canvas, - details, - embed, - figure, - figcaption, - footer, - header, - hgroup, - menu, - nav, - output, - ruby, - section, - summary, - time, - mark, - audio, - video { - vertical-align: baseline; - margin: 0; - border: 0; - padding: 0; - font-size: 100%; - font: inherit; - } - /* HTML5 display-role reset for older browsers */ - article, - aside, - details, - figcaption, - figure, - footer, - header, - hgroup, - menu, - nav, - section { - display: block; + button { + cursor: revert; + line-height: 0; } - body { - line-height: 1; + + button:disabled { + cursor: default; } + + /* Remove list styles (bullets/numbers) */ ol, - ul { + ul, + menu, + summary { list-style: none; } - blockquote, - q { - quotes: none; - } - blockquote:before, - blockquote:after, - q:before, - q:after { - content: ''; - content: none; - } + + /* Removes spacing between cells in tables */ table { border-collapse: collapse; - border-spacing: 0; } - button { - cursor: pointer; - border: none; - background-color: transparent; + + /* Safari - solving issue when using user-select:none on the <body> text input doesn't working */ + input, + textarea { + -webkit-user-select: auto; } - * { + + /* Revert the 'white-space' property for textarea elements on Safari */ + textarea { + white-space: revert; + } + + /* Minimum style to allow to style meter element */ + meter { + -webkit-appearance: revert; + appearance: revert; + } + + /* Preformatted text - use only for this feature */ + :where(pre) { + all: revert; box-sizing: border-box; } - html { - height: 100%; + /* Fix the feature of 'hidden' attribute. + display: revert; revert to element instead of attribute */ + :where([hidden]) { + display: none; } - body { - max-width: 768px; - height: 100%; - margin: 0 auto; + /* Revert for bug in Chromium browsers + - Fix for the content editable attribute will work properly. + - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element */ + :where([contenteditable]:not([contenteditable='false'])) { + -moz-user-modify: read-write; + -webkit-user-modify: read-write; + overflow-wrap: break-word; + -webkit-line-break: after-white-space; + -webkit-user-select: auto; + } + + /* Apply back the draggable feature - exist only in Chromium and Safari */ + :where([draggable='true']) { + -webkit-user-drag: element; + } + + /* Revert Modal native behavior */ + :where(dialog:modal) { + all: revert; + box-sizing: border-box; + } + + /* Remove details summary webkit styles */ + ::-webkit-details-marker { + display: none; + } - overflow-y: scroll; - &::-webkit-scrollbar { - display: none; - } + /* Chrome, Safari, Edge, Opera */ + input::-webkit-outer-spin-button, + input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; } - section { - width: 100%; + /* Firefox */ + input[type='number'] { + -moz-appearance: textfield; } #root { display: flex; - flex-direction: column; + justify-content: center; + } + + button { + cursor: pointer; + } + + body { + font-family: + 'Pretendard', + -apple-system, + BlinkMacSystemFont, + system-ui, + Roboto, + 'Helvetica Neue', + 'Segoe UI', + 'Apple SD Gothic Neo', + 'Noto Sans KR', + 'Malgun Gothic', + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-feature-settings: 'tnum'; + max-width: 768px; + margin: 0 auto; } `; diff --git a/client/src/components/Design/theme/GlobalStyle.ts b/client/src/components/Design/theme/GlobalStyle.ts index f1b7b699b..b25bb94d1 100644 --- a/client/src/components/Design/theme/GlobalStyle.ts +++ b/client/src/components/Design/theme/GlobalStyle.ts @@ -1,6 +1,9 @@ import {css} from '@emotion/react'; +// reset css -> index css export const GlobalStyle = css` + @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'); + *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { all: unset; display: revert; @@ -120,4 +123,26 @@ export const GlobalStyle = css` button { cursor: pointer; } + + body { + font-family: + 'Pretendard', + -apple-system, + BlinkMacSystemFont, + system-ui, + Roboto, + 'Helvetica Neue', + 'Segoe UI', + 'Apple SD Gothic Neo', + 'Noto Sans KR', + 'Malgun Gothic', + 'Apple Color Emoji', + 'Segoe UI Emoji', + 'Segoe UI Symbol', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + max-width: 768px; + margin: 0 auto; + } `; From 98723d122ade6aeb2446a1cbc351de17ad012841 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:37:40 +0900 Subject: [PATCH 257/273] =?UTF-8?q?fix:=20=EB=AA=A8=EB=B0=94=EC=9D=BC?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EB=A9=A4=EB=B2=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=EA=B0=80=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EB=90=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0=20?= =?UTF-8?q?(#639)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useMembersStep.ts | 15 +++++++++++---- .../src/pages/AddBillFunnel/steps/MembersStep.tsx | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/client/src/hooks/useMembersStep.ts b/client/src/hooks/useMembersStep.ts index 8f8aeb8f0..e58a22be9 100644 --- a/client/src/hooks/useMembersStep.ts +++ b/client/src/hooks/useMembersStep.ts @@ -1,4 +1,4 @@ -import {useEffect, useState} from 'react'; +import {RefObject, useEffect, useRef, useState} from 'react'; import {useNavigate} from 'react-router-dom'; import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; @@ -23,6 +23,7 @@ interface Props { const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => { const [errorMessage, setErrorMessage] = useState(''); const [nameInput, setNameInput] = useState(''); + const inputRef = useRef<HTMLInputElement>(null); const {members: allMembers} = useRequestGetAllMembers(); const {postMembersAsync, isPending: isPendingPostMembers} = useRequestPostMembers(); @@ -61,15 +62,16 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) }; const handleNameInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { - if (event.nativeEvent.isComposing) { - return; - } if (event.key === 'Enter' && canAddMembers) { event.preventDefault(); if (!billInfo.members.map(({name}) => name).includes(nameInput)) { setBillInfoMemberWithId(nameInput); } setNameInput(''); + if (inputRef.current) { + inputRef.current.blur(); + setTimeout(() => inputRef.current?.focus(), 0); + } } }; @@ -104,6 +106,10 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) } }, [isSuccessPostBill]); + useEffect(() => { + console.log(nameInput); + }, [nameInput]); + const handlePrevStep = () => { setStep('title'); }; @@ -111,6 +117,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) return { errorMessage, nameInput, + inputRef, handleNameInputChange, handleNameInputEnter, isPendingPostBill, diff --git a/client/src/pages/AddBillFunnel/steps/MembersStep.tsx b/client/src/pages/AddBillFunnel/steps/MembersStep.tsx index 5d78083a9..fe4052d8e 100644 --- a/client/src/pages/AddBillFunnel/steps/MembersStep.tsx +++ b/client/src/pages/AddBillFunnel/steps/MembersStep.tsx @@ -22,6 +22,7 @@ const MembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => const { errorMessage, nameInput, + inputRef, handleNameInputChange, handleNameInputEnter, isPendingPostBill, @@ -46,6 +47,7 @@ const MembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => <Top.Line text="참여한 사람은 누구인가요?" emphasize={['참여한 사람']} /> </Top> <LabelInput + ref={inputRef} labelText="이름" errorText={errorMessage ?? ''} value={nameInput} From 949ed883b8631dd042aed64dcaf56f68a6d377fa Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:38:29 +0900 Subject: [PATCH 258/273] =?UTF-8?q?fix:=20=EC=A7=80=EC=B6=9C=EC=97=90=20?= =?UTF-8?q?=EB=A9=A4=EB=B2=84=EA=B0=80=201=EB=AA=85=EC=9D=BC=20=EB=95=8C,?= =?UTF-8?q?=20=EA=B8=88=EC=95=A1=EC=9D=B4=20=EC=88=98=EC=A0=95=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A5=98=20(#641)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 고정되지 않은 멤버가 한명일 때, 수정되던 오류 수정 * fix: 잘못 삭제된 코드 복구 --- client/src/hooks/useEditBillState.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/src/hooks/useEditBillState.ts b/client/src/hooks/useEditBillState.ts index e675944a9..cc7a079a7 100644 --- a/client/src/hooks/useEditBillState.ts +++ b/client/src/hooks/useEditBillState.ts @@ -59,7 +59,12 @@ const useEditBillState = ({bill, billDetails}: Props) => { ); }; + const isLastUnfixedMember = (keyboardTargetId: number) => + !newBillDetails.find(({id}) => id === keyboardTargetId)?.isFixed && + newBillDetails.filter(({isFixed}) => isFixed === false).length === 1; + const handleChangeBillDetails = ({value, keyboardTargetId}: HandleChangeBillDetailsProps) => { + if (isLastUnfixedMember(keyboardTargetId)) return; if (Number(value.replace(/,/g, '')) === newBillDetails.find(({id}) => id === keyboardTargetId)?.price) return; setNewBillDetails(prev => { const updatedDetails = prev.map(detail => From 0bbc6e90383d3bea3c85ee060d9dbd57aaeac010 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:44:29 +0900 Subject: [PATCH 259/273] =?UTF-8?q?fix=20=ED=96=89=EC=82=AC=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=ED=95=9C=EA=B8=80=EC=9D=B4=20=EB=91=90=20=EC=9E=90?= =?UTF-8?q?=20=EC=94=A9=20=EC=9E=85=EB=A0=A5=EB=90=98=EB=8A=94=20=EB=B2=84?= =?UTF-8?q?=EA=B7=B8=20(#640)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: handleEventNameChange 유효하지 않은 값이 들어올 경우 로직 수정 * fix: input에 value가 변경될 때마다 컴포넌트가 리렌더링되는 문제 해결 * chore: 사용하지 않는 import 삭제 --- client/src/hooks/useFunnel.tsx | 29 ++++++++++--------- client/src/hooks/useSetEventNameStep.ts | 11 ++++--- .../CreateEventPage/CreateEventFunnel.tsx | 16 +++++----- .../CreateEventPage/SetEventNameStep.tsx | 2 +- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/client/src/hooks/useFunnel.tsx b/client/src/hooks/useFunnel.tsx index 196bb37b4..1347e59e7 100644 --- a/client/src/hooks/useFunnel.tsx +++ b/client/src/hooks/useFunnel.tsx @@ -11,9 +11,25 @@ type StepProps = { }; type FunnelProps = { + step: string; children: React.ReactElement<StepProps>[]; }; +const Step = (stepProps: StepProps) => { + return <>{stepProps.children}</>; +}; + +const Funnel = ({children, step}: FunnelProps) => { + const targetStep = children.find(curStep => curStep.props.name === step); + + if (!targetStep) + throw new Error(`현재 ${step} 단계에 보여줄 컴포넌트가 존재하지 않습니다. Step 컴포넌트를 호출해 사용해주세요.`); + + return <>{targetStep}</>; +}; + +Funnel.Step = Step; + const useFunnel = ({defaultStep, stepList}: UseFunnel) => { const [step, setStep] = useState(defaultStep); @@ -33,19 +49,6 @@ const useFunnel = ({defaultStep, stepList}: UseFunnel) => { setStep(stepList[curStepIndex - 1]); }; - const Step = (stepProps: StepProps) => { - return <>{stepProps.children}</>; - }; - - const Funnel = ({children}: FunnelProps) => { - const targetStep = children.find(curStep => curStep.props.name === step); - - if (!targetStep) - throw new Error(`현재 ${step} 단계에 보여줄 컴포넌트가 존재하지 않습니다. Step 컴포넌트를 호출해 사용해주세요.`); - - return <>{targetStep}</>; - }; - return { Step, step, diff --git a/client/src/hooks/useSetEventNameStep.ts b/client/src/hooks/useSetEventNameStep.ts index cd2a35302..ae087434d 100644 --- a/client/src/hooks/useSetEventNameStep.ts +++ b/client/src/hooks/useSetEventNameStep.ts @@ -13,14 +13,13 @@ const useSetEventNameStep = () => { const newValue = event.target.value; const validation = validateEventName(newValue); - setCanSubmit(newValue.length !== 0); - setErrorMessage(validation.errorMessage); - - if (validation.isValid) { - setEventName(newValue); + if (!validation.isValid) { + setErrorMessage(validation.errorMessage); } else { - event.target.value = eventName; + setErrorMessage(''); + setEventName(newValue); } + setCanSubmit(newValue.length !== 0); }; return { diff --git a/client/src/pages/CreateEventPage/CreateEventFunnel.tsx b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx index 0b1bdf914..f21e62f23 100644 --- a/client/src/pages/CreateEventPage/CreateEventFunnel.tsx +++ b/client/src/pages/CreateEventPage/CreateEventFunnel.tsx @@ -14,7 +14,7 @@ const STEP_SEQUENCE: CreateEventStep[] = ['eventName', 'eventPassword', 'complet const CreateEventFunnel = () => { const navigate = useNavigate(); - const {moveToNextStep, moveToPrevStep, Step, Funnel, step} = useFunnel({ + const {moveToNextStep, moveToPrevStep, Funnel, step} = useFunnel({ defaultStep: 'eventName', stepList: STEP_SEQUENCE, }); @@ -36,22 +36,22 @@ const CreateEventFunnel = () => { <TopNav.Item displayName="뒤로가기" noEmphasis routePath="" onHandleRouteInFunnel={handleBack} /> )} </TopNav> - <Funnel> - <Step name="eventName"> + <Funnel step={step}> + <Funnel.Step name="eventName"> <SetEventNameStep moveToNextStep={moveToNextStep} {...eventNameProps} /> - </Step> + </Funnel.Step> - <Step name="eventPassword"> + <Funnel.Step name="eventPassword"> <SetEventPasswordStep moveToNextStep={moveToNextStep} eventName={eventNameProps.eventName} setEventToken={setEventToken} /> - </Step> + </Funnel.Step> - <Step name="complete"> + <Funnel.Step name="complete"> <CompleteCreateEventStep eventToken={eventToken} /> - </Step> + </Funnel.Step> </Funnel> </MainLayout> ); diff --git a/client/src/pages/CreateEventPage/SetEventNameStep.tsx b/client/src/pages/CreateEventPage/SetEventNameStep.tsx index 5653038ff..924c4b79d 100644 --- a/client/src/pages/CreateEventPage/SetEventNameStep.tsx +++ b/client/src/pages/CreateEventPage/SetEventNameStep.tsx @@ -46,7 +46,7 @@ const SetEventNameStep = ({ onChange={handleEventNameChange} isError={!!errorMessage} autoFocus - ></LabelInput> + /> <FixedButton disabled={!canSubmit}>다음</FixedButton> </form> </div> From 3690b03185fc8230802e026468ffbd25b07515d9 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:44:54 +0900 Subject: [PATCH 260/273] =?UTF-8?q?refactor:=20z-index=EB=A5=BC=20?= =?UTF-8?q?=EC=83=81=EC=88=98=ED=99=94=20(#635)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: z-index 토큰 생성 * chore: 생성된 z-index 토큰에 맞춰 변경 * feat: Toast z-index 추가 --- .../BottomSheet/BottomSheet.style.ts | 4 +- .../DepositToggle/DepositToggle.style.ts | 2 +- .../FixedButton/FixedButton.style.ts | 2 +- .../Design/components/Tabs/Tabs.style.ts | 4 +- client/src/components/Design/token/zIndex.ts | 39 +++++++++++++++++-- client/src/components/Toast/Toast.style.ts | 3 +- client/src/components/Toast/Toast.tsx | 4 +- client/src/pages/MainPage/Nav/Nav.style.ts | 29 +++++++------- client/src/pages/MainPage/Nav/Nav.tsx | 4 +- client/src/types/toastType.ts | 3 ++ 10 files changed, 68 insertions(+), 26 deletions(-) diff --git a/client/src/components/Design/components/BottomSheet/BottomSheet.style.ts b/client/src/components/Design/components/BottomSheet/BottomSheet.style.ts index 08c373835..a15a1a959 100644 --- a/client/src/components/Design/components/BottomSheet/BottomSheet.style.ts +++ b/client/src/components/Design/components/BottomSheet/BottomSheet.style.ts @@ -10,7 +10,7 @@ export const display = (visible: boolean) => export const dimmedLayerStyle = (theme: Theme, isOpened: boolean) => css({ position: 'fixed', - zIndex: '30', + zIndex: theme.zIndex.bottomSheetDimmedLayer, top: '50%', left: '50%', transform: 'translate(-50%, -50%)', @@ -31,7 +31,7 @@ export const bottomSheetContainerStyle = (theme: Theme, isOpened: boolean, isDra flexDirection: 'column', alignItems: 'center', gap: '1.5rem', - zIndex: '50', + zIndex: theme.zIndex.bottomSheetContainer, inset: 'auto 0 0 50%', maxWidth: '768px', width: '100%', diff --git a/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts b/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts index f90ff87ce..fff882251 100644 --- a/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts +++ b/client/src/components/Design/components/DepositToggle/DepositToggle.style.ts @@ -22,7 +22,7 @@ export const depositToggleStyle = ({theme, isDeposit}: WithTheme<DepositToggleSt justifyContent: 'center', borderRadius: '0.5rem', padding: '0 0.25rem', - zIndex: '10', + zIndex: theme.zIndex.depositToggleMovingAnimation, height: '15px', width: '34px', paddingTop: '0.05rem', diff --git a/client/src/components/Design/components/FixedButton/FixedButton.style.ts b/client/src/components/Design/components/FixedButton/FixedButton.style.ts index e5bc5c1e0..3698c2b52 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.style.ts +++ b/client/src/components/Design/components/FixedButton/FixedButton.style.ts @@ -14,7 +14,7 @@ export const fixedButtonContainerStyle = (theme: Theme) => margin: '0 auto', backgroundColor: theme.colors.white, boxSizing: 'border-box', - zIndex: '10', + zIndex: theme.zIndex.fixedButton, }); export const buttonContainerStyle = css({ diff --git a/client/src/components/Design/components/Tabs/Tabs.style.ts b/client/src/components/Design/components/Tabs/Tabs.style.ts index 7c1eb771a..842b34823 100644 --- a/client/src/components/Design/components/Tabs/Tabs.style.ts +++ b/client/src/components/Design/components/Tabs/Tabs.style.ts @@ -40,7 +40,7 @@ export const tabTextStyle = ({theme, selected}: WithSelected) => css({ color: selected ? theme.colors.onTertiary : theme.colors.gray, - zIndex: theme.zIndex.visible, + zIndex: theme.zIndex.tabText, }); export const indicatorStyle = ({theme, tabWidth, activeTabIndex}: IndicatorType) => @@ -59,5 +59,5 @@ export const indicatorStyle = ({theme, tabWidth, activeTabIndex}: IndicatorType) transition: '0.2s', transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - zIndex: theme.zIndex.normal, + zIndex: theme.zIndex.tabIndicator, }); diff --git a/client/src/components/Design/token/zIndex.ts b/client/src/components/Design/token/zIndex.ts index 1a7991b34..60ec5a6cd 100644 --- a/client/src/components/Design/token/zIndex.ts +++ b/client/src/components/Design/token/zIndex.ts @@ -1,8 +1,39 @@ +// Utils +const BASE = 0; +const ABOVE = 1; // use this for all values above the base +const BELOW = -1; // and this for all values below the base + +const NAV_BACKGROUND_COLOR = BASE + ABOVE; +const TAB_INDICATOR = BASE; +const TAB_TEXT = TAB_INDICATOR + ABOVE; +const FIXED_BUTTON = BASE + ABOVE; +const DEPOSIT_TOGGLE_INDICATOR_MOVING_ANIMATION = BASE + ABOVE; +const NUMBER_KEYBOARD_BOTTOM_SHEET = FIXED_BUTTON + ABOVE; +const BOTTOM_SHEET_DIMMED_LAYER = NUMBER_KEYBOARD_BOTTOM_SHEET + ABOVE; +const BOTTOM_SHEET_CONTAINER = BOTTOM_SHEET_DIMMED_LAYER + ABOVE; +const TOAST = BOTTOM_SHEET_CONTAINER + ABOVE; + export const ZINDEX = { - normal: 0, - hidden: -1, - visible: 1, + bottomSheetDimmedLayer: BOTTOM_SHEET_DIMMED_LAYER, + bottomSheetContainer: BOTTOM_SHEET_CONTAINER, + numberKeyboardBottomSheet: NUMBER_KEYBOARD_BOTTOM_SHEET, + depositToggleMovingAnimation: DEPOSIT_TOGGLE_INDICATOR_MOVING_ANIMATION, + fixedButton: FIXED_BUTTON, + navBackgroundColor: NAV_BACKGROUND_COLOR, + tabIndicator: TAB_INDICATOR, + tabText: TAB_TEXT, + toast: TOAST, } as const; -type ZIndexKeys = 'normal' | 'hidden' | 'visible'; +type ZIndexKeys = + | 'bottomSheetDimmedLayer' + | 'bottomSheetContainer' + | 'numberKeyboardBottomSheet' + | 'depositToggleMovingAnimation' + | 'fixedButton' + | 'navBackgroundColor' + | 'tabText' + | 'tabIndicator' + | 'toast'; + export type ZIndexTokens = Record<ZIndexKeys, number>; diff --git a/client/src/components/Toast/Toast.style.ts b/client/src/components/Toast/Toast.style.ts index 510a2275c..d8c4c62f7 100644 --- a/client/src/components/Toast/Toast.style.ts +++ b/client/src/components/Toast/Toast.style.ts @@ -25,13 +25,14 @@ const fadeOutWithTransformY = keyframes` } `; -export const toastMarginStyle = ({position, bottom, top}: ToastOptions) => +export const toastMarginStyle = ({position, bottom, top, theme}: ToastOptions) => css({ position: 'absolute', bottom: position === 'bottom' ? `${bottom}` : 'auto', top: position === 'top' ? `${top}` : 'auto', left: '50%', transform: 'translate(-50%)', + zIndex: theme?.zIndex.toast, width: '100%', maxWidth: '48rem', diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx index 0081f3978..cbc6824f4 100644 --- a/client/src/components/Toast/Toast.tsx +++ b/client/src/components/Toast/Toast.tsx @@ -1,6 +1,7 @@ import {createPortal} from 'react-dom'; import {useState, useEffect} from 'react'; +import {useTheme} from '@HDesign/index'; import {Button, Flex, Icon, Text} from '@HDesign/index'; import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; @@ -27,8 +28,9 @@ const Toast = ({ onClose, ...htmlProps }: ToastProps) => { + const {theme} = useTheme(); const [isVisible, setIsVisible] = useState(true); - const styleProps = {position, top, bottom}; + const styleProps = {position, top, bottom, theme}; const handleClickToClose = () => { if (!isCloseOnClick || !onClose) return; diff --git a/client/src/pages/MainPage/Nav/Nav.style.ts b/client/src/pages/MainPage/Nav/Nav.style.ts index 58cf1cb86..89589e825 100644 --- a/client/src/pages/MainPage/Nav/Nav.style.ts +++ b/client/src/pages/MainPage/Nav/Nav.style.ts @@ -1,19 +1,22 @@ import {css} from '@emotion/react'; -export const navStyle = css({ - position: 'fixed', - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - padding: '1rem', +import {Theme} from '@components/Design/theme/theme.type'; - top: '0', - width: '100%', - maxWidth: '768px', - zIndex: '20', - height: '4rem', - backgroundColor: 'white', -}); +export const navStyle = (theme: Theme) => + css({ + position: 'fixed', + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + padding: '1rem', + + top: '0', + width: '100%', + maxWidth: '768px', + zIndex: theme.zIndex.navBackgroundColor, + height: '4rem', + backgroundColor: 'white', + }); export const logoStyle = css({ display: 'flex', diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index 2a45267cb..7407e0e20 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -1,6 +1,7 @@ import {useNavigate} from 'react-router-dom'; import Heundeut from '@assets/image/heundeut.svg'; +import {useTheme} from '@theme/HDesignProvider'; import {Button, Flex, Text} from '@HDesign/index'; @@ -9,9 +10,10 @@ import {ROUTER_URLS} from '@constants/routerUrls'; import {logoStyle, navStyle} from './Nav.style'; const Nav = () => { + const {theme} = useTheme(); const navigate = useNavigate(); return ( - <header css={navStyle}> + <header css={navStyle(theme)}> <Flex gap="0.5rem"> <Heundeut /> <div css={logoStyle}> diff --git a/client/src/types/toastType.ts b/client/src/types/toastType.ts index 6b165f5ce..d81a20572 100644 --- a/client/src/types/toastType.ts +++ b/client/src/types/toastType.ts @@ -1,3 +1,5 @@ +import {Theme} from '@components/Design/theme/theme.type'; + export type ToastPosition = 'bottom' | 'top'; export type ToastOptions = { @@ -7,6 +9,7 @@ export type ToastOptions = { position?: ToastPosition; bottom?: string; top?: string; + theme?: Theme; }; export type ToastMessage = string; From 3b00b2a3bff6a79a44fad05601f5ee1df5f93fdb Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:45:52 +0900 Subject: [PATCH 261/273] =?UTF-8?q?refactor:=20=EC=B5=9C=EC=8B=A0=EC=9D=98?= =?UTF-8?q?=20=EC=84=9C=EB=B2=84=20=EC=97=90=EB=9F=AC=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=ED=94=84=EB=A1=A0=ED=8A=B8=EC=97=90=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=ED=95=98=EA=B3=A0,=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=EC=97=90=EA=B2=8C=20=EB=B3=B4=EC=97=AC?= =?UTF-8?q?=EC=A7=80=EB=8A=94=20=EC=97=90=EB=9F=AC=20=EB=A9=94=EC=84=B8?= =?UTF-8?q?=EC=A7=80=EB=A5=BC=20=EC=9D=B4=ED=95=B4=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EC=89=BD=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#632)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 서버 에러 코드와 메세지 업데이트, 그리고 상수를 사용하지 않는 부분을 사용하도록 변경 * feat: 지출 내역 이름의 최대 길이 상수를 추가 * fix: 서버 에러 코드가 잘못 입력된 것을 수정 * feat: 로그인 만료 안내에 다시 로그인해달라는 문장 추가 * feat: 상수를 사용하도록 적용 --- client/cypress/e2e/createEvent.cy.ts | 3 +- .../NumberKeyboard/NumberKeyboard.stories.tsx | 4 +- client/src/constants/errorMessage.ts | 86 +++++++++++-------- client/src/constants/rule.ts | 5 +- client/src/hooks/useEditBillKeyboardAction.ts | 4 +- .../pages/AddBillFunnel/steps/PriceStep.tsx | 4 +- .../CreateEventPage/SetEventPasswordStep.tsx | 5 +- .../EventPage/AdminPage/EventLoginPage.tsx | 2 +- 8 files changed, 68 insertions(+), 45 deletions(-) diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts index edd4ddc6d..d5ca6ba11 100644 --- a/client/cypress/e2e/createEvent.cy.ts +++ b/client/cypress/e2e/createEvent.cy.ts @@ -1,5 +1,6 @@ import {ROUTER_URLS} from '@constants/routerUrls'; import CONSTANTS from '../constants/constants'; +import RULE from '@constants/rule'; beforeEach(() => { cy.blockSentry(); @@ -55,7 +56,7 @@ describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 fl cy.get('input').should('have.value', ''); }); - it('행사 비밀번호에 4자리 이상 입력을 할 경우 처음 네 자리만 입력되어야 한다.', () => { + it(`행사 비밀번호에 ${RULE.maxEventPasswordLength}자리 이상 입력을 할 경우 처음 ${RULE.maxEventPasswordLength}자리만 입력되어야 한다.`, () => { cy.get('input').type('12345'); cy.get('input').should('have.value', CONSTANTS.eventPassword); }); diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx index a6a525553..0778c506f 100644 --- a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.stories.tsx @@ -5,6 +5,8 @@ import {useRef, useState} from 'react'; import {Flex, Input} from '@components/Design'; +import RULE from '@constants/rule'; + import NumberKeyboard from './NumberKeyboard'; const meta = { @@ -19,7 +21,7 @@ const meta = { }, args: { type: 'amount', - maxNumber: 10000000, + maxNumber: RULE.maxPrice, onChange: () => {}, }, } satisfies Meta<typeof NumberKeyboard>; diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index af59ee50d..113b7c7e1 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -1,51 +1,61 @@ +import RULE from './rule'; + type ErrorMessage = Record<string, string>; export const SERVER_ERROR_MESSAGES: ErrorMessage = { - EVENT_NOT_FOUND: '존재하지 않는 행사입니다.', - EVENT_NAME_LENGTH_INVALID: '행사 이름은 2자 이상 30자 이하만 입력 가능합니다.', - EVENT_NAME_CONSECUTIVE_SPACES: '행사 이름에는 공백 문자가 연속될 수 없습니다.', - EVENT_PASSWORD_FORMAT_INVALID: '비밀번호는 4자리 숫자만 가능합니다.', - - ACTION_NOT_FOUND: '존재하지 않는 액션입니다.', - - MEMBER_NAME_LENGTH_INVALID: '멤버 이름은 1자 이상 4자 이하만 입력 가능합니다.', - MEMBER_NAME_DUPLICATE: '중복된 행사 참여 인원 이름이 존재합니다.', - MEMBER_NOT_EXIST: '현재 참여하고 있지 않은 인원이 존재합니다.', - MEMBER_ALREADY_EXIST: '현재 참여하고 있는 인원이 존재합니다.', - - MEMBER_ACTION_NOT_FOUND: '존재하지 않는 멤버 액션입니다.', - MEMBER_ACTION_STATUS_INVALID: '유효하지 않은 멤버 액션 상태입니다.', - - BILL_ACTION_NOT_FOUND: '존재하지 않는 지출 액션입니다.', - BILL_ACTION_TITLE_INVALID: '앞뒤 공백을 제거한 지출 내역 제목은 %d자 ~ %d자여야 합니다.', - BILL_ACTION_PRICE_INVALID: '지출 금액은 10,000,000 이하의 자연수여야 합니다.', - - REQUEST_EMPTY: '입력 값은 공백일 수 없습니다.', - MESSAGE_NOT_READABLE: '읽을 수 없는 요청입니다.', - NO_RESOURCE_REQUEST: '존재하지 않는 자원입니다.', - REQUEST_METHOD_NOT_SUPPORTED: '지원하지 않는 요청 메서드입니다.', - + // 행사 관련 에러 코드 + EVENT_NAME_LENGTH_INVALID: `행사 이름의 길이는 2자 이상 ${RULE.maxEventNameLength}자 이하만 가능해요.`, + EVENT_NAME_CONSECUTIVE_SPACES: '행사 이름에는 공백 문자가 연속될 수 없어요.', + EVENT_PASSWORD_FORMAT_INVALID: `비밀번호는 ${RULE.maxEventPasswordLength}자리의 숫자만 가능해요.`, + EVENT_NOT_FOUND: '존재하지 않는 행사에요. 링크가 올바른지 확인해주세요.', + + // 멤버 관련 에러 코드 + MEMBER_NAME_LENGTH_INVALID: `멤버 이름은 한글 ${RULE.maxEventNameLength}자까지, 영어 ${RULE.maxEventNameLength * 2}자까지 입력 가능해요.`, + + MEMBER_NAME_CHANGE_DUPLICATE: '요청 본문에 중복된 이름이 존재해요. \n(ex. [이상, 이상, 감자, 백호])', + MEMBER_NAME_DUPLICATE: '요청 본문에 중복된 이름이 존재해요. \n(ex. [이상, 이상, 감자, 백호])', + MEMBER_ALREADY_EXIST: '이미 행사에 참여중인 인원이에요. \n겹치지 않도록 다른 이름을 사용해주세요.', + + MEMBER_NOT_EXIST: '현재 참여하고 있지 않은 인원이 존재해요', + MEMBER_UPDATE_MISMATCH: '업데이트 요청된 참여자 정보와 기존 행사 참여자 정보가 일치하지 않아요.', + + // 지출 관련 에러 코드 + BILL_NOT_FOUND: '존재하지 않는 지출 액션이에요.', + BILL_TITLE_INVALID: `지출 내역 이름은 1자 이상 ${RULE.maxBillNameLength} 이하여야 해요.`, + BILL_PRICE_INVALID: `지출 금액은 ${RULE.maxPrice.toLocaleString('ko-KR')} 이하의 자연수여야 해요.`, + BILL_DETAIL_NOT_FOUND: '존재하지 않는 참여자 지출입니다.', + BILL_PRICE_NOT_MATCHED: '지출 총액이 일치하지 않아요.', + DIFFERENT_STEP_MEMBERS: '회원 목록이 일치하지 않아요.', + + // 계좌 관련 에러 코드 + BANK_NAME_INVALID: '지원하지 않는 은행이에요. 다른 은행을 입력해주세요.', + ACCOUNT_LENGTH_INVALID: `계좌 번호는 8자 이상 ${RULE.maxAccountNumberLength}자 이하로 입력 가능해요.`, + + // 로그인 관련 에러 코드 + TOKEN_NOT_FOUND: '로그인이 필요한 서비스에요.', + TOKEN_EXPIRED: '로그인이 만료되었어요. 다시 로그인해주세요.', + TOKEN_INVALID: '비밀번호를 올바르게 입력해주세요.', + FORBIDDEN: '접근할 수 없는 행사에요.', + + // 사용자에게 뜨면 안되며 프론트 구현 미스인 에러 코드 + MESSAGE_NOT_READABLE: '읽을 수 없는 요청이에요.', + NO_RESOURCE_REQUEST: '존재하지 않는 자원이에요.', + REQUEST_METHOD_NOT_SUPPORTED: '지원하지 않는 요청 메서드에요.', + REQUEST_EMPTY: '요청 본문에 빈 값이 존재해요', + + // 예측할 수 없는 에러 코드 INTERNAL_SERVER_ERROR: '서버 내부에 에러가 발생했습니다.', - - PASSWORD_INVALID: '비밀번호가 일치하지 않습니다.', - TOKEN_NOT_FOUND: '토큰이 존재하지 않습니다.', - TOKEN_EXPIRED: '만료된 토큰입니다.', - TOKEN_INVALID: '유효하지 않은 토큰입니다.', - FORBIDDEN: '접근할 수 없는 행사입니다.', - UNHANDLED: '알 수 없는 에러입니다.', }; export const ERROR_MESSAGE = { - eventName: '행사 이름은 30자 이하만 가능해요', - eventPasswordType: '비밀번호는 숫자만 입력이 가능해요', - memberName: '참여자 이름은 4자 이하의 한글, 영어만 가능해요', - purchasePrice: '10,000,000원 이하의 숫자만 입력이 가능해요', - purchaseTitle: '지출 이름은 30자 이하의 한글, 영어, 숫자만 가능해요', + eventName: SERVER_ERROR_MESSAGES.EVENT_NAME_LENGTH_INVALID, + eventPasswordType: SERVER_ERROR_MESSAGES.EVENT_PASSWORD_FORMAT_INVALID, + memberName: SERVER_ERROR_MESSAGES.MEMBER_NAME_LENGTH_INVALID, + purchasePrice: `${RULE.maxPrice.toLocaleString('ko-kr')}원 이하의 숫자만 입력이 가능해요`, + purchaseTitle: `지출 이름은 ${RULE.maxBillNameLength}자 이하의 한글, 영어, 숫자만 가능해요`, preventEmpty: '값은 비어있을 수 없어요', invalidInput: '올바르지 않은 입력이에요.', emptyBank: '계좌번호가 입력되지 않아서\n토스 송금 기능을 사용할 수 없어요', invalidAccountNumber: '계좌번호는 8자에서 30자 사이로 입력 가능해요', }; - -export const UNKNOWN_ERROR = 'UNKNOWN_ERROR'; diff --git a/client/src/constants/rule.ts b/client/src/constants/rule.ts index f311dedea..71ac70c58 100644 --- a/client/src/constants/rule.ts +++ b/client/src/constants/rule.ts @@ -1,8 +1,11 @@ +const EVENT_PASSWORD_LENGTH = 4; + const RULE = { maxEventNameLength: 30, - maxEventPasswordLength: 4, + maxEventPasswordLength: EVENT_PASSWORD_LENGTH, maxMemberNameLength: 4, maxPrice: 10000000, + maxBillNameLength: 30, minAccountNumberLength: 8, maxAccountNumberLength: 30, }; diff --git a/client/src/hooks/useEditBillKeyboardAction.ts b/client/src/hooks/useEditBillKeyboardAction.ts index e2a5a6fda..df971c5a8 100644 --- a/client/src/hooks/useEditBillKeyboardAction.ts +++ b/client/src/hooks/useEditBillKeyboardAction.ts @@ -3,6 +3,8 @@ import {useRef, useState} from 'react'; import {BillDetail} from 'types/serviceType'; import {RequestPutBill} from '@apis/request/bill'; +import RULE from '@constants/rule'; + import useEditBillPageScroll from './useEditBillPageScroll'; interface Props { @@ -25,7 +27,7 @@ const useEditBillKeyboardAction = ({newBill, billDetails, newBillDetails}: Props (sum, detail) => (detail.isFixed && detail.id !== keyboardTargetId ? sum + detail.price : sum), 0, ); - const keyboardMaxPrice = keyboardTargetId === 0 ? 10000000 : Math.max(0, newBill.price - totalFixedPrice); + const keyboardMaxPrice = keyboardTargetId === 0 ? RULE.maxPrice : Math.max(0, newBill.price - totalFixedPrice); const keyboardInitialValue = newBillDetails.find(({id}) => id === keyboardTargetId)?.price.toLocaleString('ko-kr') ?? newBill.price.toLocaleString('ko-kr'); diff --git a/client/src/pages/AddBillFunnel/steps/PriceStep.tsx b/client/src/pages/AddBillFunnel/steps/PriceStep.tsx index 260fb5b4a..fea267860 100644 --- a/client/src/pages/AddBillFunnel/steps/PriceStep.tsx +++ b/client/src/pages/AddBillFunnel/steps/PriceStep.tsx @@ -10,6 +10,8 @@ import {BillStep} from '@hooks/useAddBillFunnel'; import {FixedButton} from '@components/Design'; +import RULE from '@constants/rule'; + import {BillInfo} from '../AddBillFunnel'; interface Props { @@ -47,7 +49,7 @@ const PriceStep = ({billInfo, setBillInfo, setStep}: Props) => { > <NumberKeyboard type="amount" - maxNumber={10000000} + maxNumber={RULE.maxPrice} initialValue={billInfo.price} onChange={handleNumberKeyboardChange} /> diff --git a/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx index c11c376f2..45370fd01 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx @@ -34,7 +34,10 @@ const SetEventPasswordStep = ({eventName, moveToNextStep, setEventToken}: SetEve `} > <Top> - <Top.Line text="관리에 필요한 네자리 숫자" emphasize={['네자리 숫자']} /> + <Top.Line + text={`관리에 필요한 ${RULE.maxEventPasswordLength}자리 숫자`} + emphasize={[`${RULE.maxEventPasswordLength}자리 숫자`]} + /> <Top.Line text="비밀번호는 무엇으로 할까요?" emphasize={['비밀번호']} /> </Top> <form onSubmit={submit}> diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index e126d1587..da4603e5f 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -13,7 +13,7 @@ const EventLoginPage = () => { <> <Top> <Top.Line text="행사 생성 시 설정한" /> - <Top.Line text="네자리 숫자 비밀번호를 입력해 주세요." /> + <Top.Line text={`${RULE.maxEventPasswordLength}자리 숫자 비밀번호를 입력해 주세요.`} /> </Top> <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> <LabelInput From 2557ee9c36d083a24e044e1a7fe407ff6c432e25 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:10:00 +0900 Subject: [PATCH 262/273] =?UTF-8?q?fix:=20GlobalStyle=20tnum=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20(#648)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/GlobalStyle.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/GlobalStyle.ts b/client/src/GlobalStyle.ts index 26eaea35c..b25bb94d1 100644 --- a/client/src/GlobalStyle.ts +++ b/client/src/GlobalStyle.ts @@ -142,7 +142,6 @@ export const GlobalStyle = css` sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - font-feature-settings: 'tnum'; max-width: 768px; margin: 0 auto; } From 0e6681957d9212c1ce7ecabe21287facd420c3b9 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:10:19 +0900 Subject: [PATCH 263/273] =?UTF-8?q?feat:=20IOS=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=97=90=EC=84=9C=EB=8F=84=20=ED=86=A0=EC=8A=A4=20=EC=86=A1?= =?UTF-8?q?=EA=B8=88=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20=EB=98=91=EA=B0=99?= =?UTF-8?q?=EC=9D=B4=20=EC=9D=B4=EC=9A=A9=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95=20(#651)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 안드로이드, ios 판별하는 기능 추가 * style: import 방식 변경 반영 * feat: 안드로이드는 그대로, ios는 송금하기로 이동 --- .../components/ExpenseList/ExpenseList.tsx | 2 +- .../ShareEventButton/ShareEventButton.tsx | 2 +- client/src/hooks/useReportsPage.ts | 15 ++++++++++++-- client/src/utils/detectDevice.ts | 20 +++++++++++++++++++ client/src/utils/isMobileDevice.ts | 8 -------- 5 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 client/src/utils/detectDevice.ts delete mode 100644 client/src/utils/isMobileDevice.ts diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx index cec6aa473..f34cc1aaf 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx @@ -1,7 +1,7 @@ /** @jsxImportSource @emotion/react */ import Text from '@HDcomponents/Text/Text'; -import isMobileDevice from '@utils/isMobileDevice'; +import {isMobileDevice} from '@utils/detectDevice'; import BankSendButton from '../BankSendButton/BankSendButton'; import Icon from '../Icon/Icon'; diff --git a/client/src/components/ShareEventButton/ShareEventButton.tsx b/client/src/components/ShareEventButton/ShareEventButton.tsx index 8f9bd6727..13ad9d911 100644 --- a/client/src/components/ShareEventButton/ShareEventButton.tsx +++ b/client/src/components/ShareEventButton/ShareEventButton.tsx @@ -8,7 +8,7 @@ import useShareEvent from '@hooks/useShareEvent'; import {Button} from '@components/Design'; -import isMobileDevice from '@utils/isMobileDevice'; +import {isMobileDevice} from '@utils/detectDevice'; import getDeletedLastPath from '@utils/getDeletedLastPath'; type ShareEventButtonProps = { diff --git a/client/src/hooks/useReportsPage.ts b/client/src/hooks/useReportsPage.ts index 711027cf0..87ab2c59f 100644 --- a/client/src/hooks/useReportsPage.ts +++ b/client/src/hooks/useReportsPage.ts @@ -3,6 +3,8 @@ import {useOutletContext} from 'react-router-dom'; import {EventPageContextProps} from '@pages/EventPage/EventPageLayout'; +import {isAndroid, isIOS} from '@utils/detectDevice'; + import {ERROR_MESSAGE} from '@constants/errorMessage'; import {useSearchReports} from './useSearchReports'; @@ -26,8 +28,17 @@ const useReportsPage = () => { return; } - const url = 'supertoss://'; - window.location.href = url; + if (isAndroid()) { + const url = 'supertoss://'; + window.location.href = url; + return; + } + + if (isIOS()) { + const url = 'supertoss://send'; + window.location.href = url; + return; + } }; const expenseListProp = matchedReports.map(member => ({ diff --git a/client/src/utils/detectDevice.ts b/client/src/utils/detectDevice.ts new file mode 100644 index 000000000..2b1df2ea9 --- /dev/null +++ b/client/src/utils/detectDevice.ts @@ -0,0 +1,20 @@ +export const isMobileDevice = () => { + const userAgent = window.navigator.userAgent; + const mobileRegex = [/Android/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i]; + + return mobileRegex.some(mobile => userAgent.match(mobile)); +}; + +export const isIOS = () => { + const userAgent = window.navigator.userAgent; + const iosRegex = [/iPhone/i, /iPad/i, /iPod/i]; + + return iosRegex.some(device => userAgent.match(device)); +}; + +export const isAndroid = () => { + const userAgent = window.navigator.userAgent; + const androidRegex = [/Android/i, /BlackBerry/i, /Windows Phone/i]; + + return androidRegex.some(device => userAgent.match(device)); +}; diff --git a/client/src/utils/isMobileDevice.ts b/client/src/utils/isMobileDevice.ts deleted file mode 100644 index 56e54f984..000000000 --- a/client/src/utils/isMobileDevice.ts +++ /dev/null @@ -1,8 +0,0 @@ -const isMobileDevice = () => { - const userAgent = window.navigator.userAgent; - const mobileRegex = [/Android/i, /iPhone/i, /iPad/i, /iPod/i, /BlackBerry/i, /Windows Phone/i]; - - return mobileRegex.some(mobile => userAgent.match(mobile)); -}; - -export default isMobileDevice; From 117d2449f2012c3f5b20f9791d9eefe6d32e2097 Mon Sep 17 00:00:00 2001 From: Soyeon Choe <77609591+soi-ha@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:10:35 +0900 Subject: [PATCH 264/273] =?UTF-8?q?fix:=20merge=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=ED=95=98=EB=A9=B4=EC=84=9C=20put,=20delete=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EC=88=9C=EC=84=9C=20=EB=B3=B4=EC=9E=A5=20=EC=82=AC?= =?UTF-8?q?=EB=9D=BC=EC=A7=90=20+=20=EC=88=98=EC=A0=95=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20Toast=20=EC=97=86=EC=96=B4=EC=A7=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#652)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: put, delete 요청 순서 보장 * fix: 정상적으로 수정되었을 경우 '수정완료' 토스트 띄우기 * fix: 랜딩페이지와 메인페이지의 header 디자인이 맞지 않는 에러 해결 * fix: z-index 상수화 미적용 코드 적용 및 불필요한 z-index 삭제 * fix: TopNav를 사용하는 곳에서 기본적으로 margin: 0 1rem이 적용되도록 수정 * fix: cypress에서 header 태그로 '정산시작하기' 버튼을 찾는 코드로 인해 Nav 컴포넌트에서는 Flex 컴포넌트를 사용하지 않고 header 태그 사용으로 변경 * test: 정산 시작하기 버튼에 관한 e2e 테스트 코드 변경 --- client/cypress/e2e/createEvent.cy.ts | 4 +-- .../NumberKeyboardBottomSheet.tsx | 2 +- .../Design/components/TopNav/TopNav.style.ts | 1 - .../Design/components/TopNav/TopNav.tsx | 2 +- .../ShareEventButton/ShareEventButton.tsx | 2 +- client/src/constants/message.ts | 5 ++++ client/src/hooks/useEventMember.ts | 8 ++++-- .../pages/EventPage/AdminPage/EventMember.tsx | 2 +- .../src/pages/EventPage/EventPageLayout.tsx | 2 +- client/src/pages/MainPage/MainPage.tsx | 2 +- client/src/pages/MainPage/Nav/Nav.tsx | 28 +++++++++++-------- 11 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 client/src/constants/message.ts diff --git a/client/cypress/e2e/createEvent.cy.ts b/client/cypress/e2e/createEvent.cy.ts index d5ca6ba11..30e50b4f5 100644 --- a/client/cypress/e2e/createEvent.cy.ts +++ b/client/cypress/e2e/createEvent.cy.ts @@ -8,9 +8,9 @@ beforeEach(() => { }); describe('Flow: 랜딩 페이지에서부터 이벤트를 생성 완료하는 flow', () => { - it('랜딩페이지에서 "행사 생성하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { + it('랜딩페이지에서 "정산 시작하기" 버튼을 눌러 행사 이름 입력 페이지로 이동해야 한다.', () => { cy.visit('/'); - cy.get('header').find('button').click(); + cy.get('button').contains('정산 시작하기').click(); cy.url().should('include', ROUTER_URLS.createEvent); }); diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx index 404a53d2b..cf9b07ada 100644 --- a/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboardBottomSheet.tsx @@ -31,7 +31,7 @@ const NumberKeyboardBottomSheet = ({isOpened, onClose, ...props}: Props) => { gap: 1rem; bottom: 0; background-color: ${theme.colors.white}; - z-index: 20; + z-index: ${theme.zIndex.numberKeyboardBottomSheet}; touch-action: none; transform: ${isOpened ? 'translate3d(0, 0, 0)' : 'translate3d(0, 100%, 0)'}; diff --git a/client/src/components/Design/components/TopNav/TopNav.style.ts b/client/src/components/Design/components/TopNav/TopNav.style.ts index b0efc6695..3c0c29c5e 100644 --- a/client/src/components/Design/components/TopNav/TopNav.style.ts +++ b/client/src/components/Design/components/TopNav/TopNav.style.ts @@ -4,6 +4,5 @@ export const topNavStyle = css({ display: 'flex', justifyContent: 'space-between', alignItems: 'center', - padding: '0 1rem', width: '100%', }); diff --git a/client/src/components/Design/components/TopNav/TopNav.tsx b/client/src/components/Design/components/TopNav/TopNav.tsx index 91f0eba07..84a7f9376 100644 --- a/client/src/components/Design/components/TopNav/TopNav.tsx +++ b/client/src/components/Design/components/TopNav/TopNav.tsx @@ -8,7 +8,7 @@ type TopNavProps = React.PropsWithChildren & { const TopNav = ({children}: TopNavProps) => { return ( - <nav> + <nav style={{margin: '0 1rem'}}> <ul css={topNavStyle}>{children}</ul> </nav> ); diff --git a/client/src/components/ShareEventButton/ShareEventButton.tsx b/client/src/components/ShareEventButton/ShareEventButton.tsx index 13ad9d911..f8a968003 100644 --- a/client/src/components/ShareEventButton/ShareEventButton.tsx +++ b/client/src/components/ShareEventButton/ShareEventButton.tsx @@ -39,7 +39,7 @@ const ShareEventButton = ({eventOutline}: ShareEventButtonProps) => { }; return isMobile ? ( - <Button size="small" variants="tertiary" onClick={induceBankInfoBeforeShare}> + <Button size="small" variants="tertiary" onClick={induceBankInfoBeforeShare} style={{marginRight: '1rem'}}> 카카오톡으로 정산 초대하기 </Button> ) : ( diff --git a/client/src/constants/message.ts b/client/src/constants/message.ts new file mode 100644 index 000000000..d82d48e14 --- /dev/null +++ b/client/src/constants/message.ts @@ -0,0 +1,5 @@ +const MESSAGE = { + confirmEditEventMember: '수정이 완료되었어요 :)', +}; + +export default MESSAGE; diff --git a/client/src/hooks/useEventMember.ts b/client/src/hooks/useEventMember.ts index 20ea319f1..914a39da8 100644 --- a/client/src/hooks/useEventMember.ts +++ b/client/src/hooks/useEventMember.ts @@ -3,6 +3,8 @@ import {useEffect, useState, useCallback, useMemo} from 'react'; import {Report} from 'types/serviceType'; import validateMemberName from '@utils/validate/validateMemberName'; +import MESSAGE from '@constants/message'; + import toast from './useToast/toast'; import useRequestDeleteMember from './queries/member/useRequestDeleteMember'; import useRequestPutMembers from './queries/member/useRequestPutMembers'; @@ -95,13 +97,13 @@ const useEventMember = (): ReturnUseEventMember => { // deleteMembers에 값이 하나라도 전재하면 반복문을 통해 DELETE api 요청 if (deleteMembers.length > 0) { for (const id of deleteMembers) { - deleteAsyncMember({memberId: id}); + await deleteAsyncMember({memberId: id}); } } // 변경된 값(filteredChangedMembers)이 존재한다면 PUT 요청 실행 if (reports.length > 0) { - putAsyncMember({ + await putAsyncMember({ members: reports.map(report => ({ id: report.memberId, name: report.memberName, @@ -109,6 +111,8 @@ const useEventMember = (): ReturnUseEventMember => { })), }); } + + toast.confirm(MESSAGE.confirmEditEventMember); }, [deleteMembers, reports, initialReports, deleteAsyncMember, putAsyncMember]); return {reports, canSubmit, changeMemberName, handleDeleteMember, updateMembersOnServer, toggleDepositStatus}; diff --git a/client/src/pages/EventPage/AdminPage/EventMember.tsx b/client/src/pages/EventPage/AdminPage/EventMember.tsx index 95a7d5482..cdeaa8d40 100644 --- a/client/src/pages/EventPage/AdminPage/EventMember.tsx +++ b/client/src/pages/EventPage/AdminPage/EventMember.tsx @@ -46,7 +46,7 @@ const EventMember = () => { {reports.length === 0 ? ( <></> ) : ( - <FixedButton disabled={!canSubmit} onClick={updateMembersOnServer} style={{zIndex: '100'}}> + <FixedButton disabled={!canSubmit} onClick={updateMembersOnServer}> 수정완료 </FixedButton> )} diff --git a/client/src/pages/EventPage/EventPageLayout.tsx b/client/src/pages/EventPage/EventPageLayout.tsx index c0747a727..2fcf0d682 100644 --- a/client/src/pages/EventPage/EventPageLayout.tsx +++ b/client/src/pages/EventPage/EventPageLayout.tsx @@ -22,7 +22,7 @@ const EventPageLayout = () => { return ( <MainLayout backgroundColor="gray"> - <Flex justifyContent="spaceBetween" alignItems="center" margin="0 1rem 0 0"> + <Flex justifyContent="spaceBetween" alignItems="center"> <TopNav> <TopNav.Item routePath="/"> <IconButton variants="none"> diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index 702972eff..50cae98b8 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -1,4 +1,4 @@ -import {MainLayout} from '@HDesign/index'; +import {Flex, MainLayout} from '@HDesign/index'; import Nav from './Nav/Nav'; import MainSection from './Section/MainSection'; diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index 7407e0e20..2ca0cfb4d 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -1,26 +1,32 @@ import {useNavigate} from 'react-router-dom'; -import Heundeut from '@assets/image/heundeut.svg'; import {useTheme} from '@theme/HDesignProvider'; -import {Button, Flex, Text} from '@HDesign/index'; +import {Button, Flex, Text, Icon, TopNav, IconButton} from '@HDesign/index'; import {ROUTER_URLS} from '@constants/routerUrls'; -import {logoStyle, navStyle} from './Nav.style'; - const Nav = () => { const {theme} = useTheme(); const navigate = useNavigate(); return ( - <header css={navStyle(theme)}> - <Flex gap="0.5rem"> - <Heundeut /> - <div css={logoStyle}> + <header style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', height: '37px'}}> + <TopNav> + <TopNav.Item routePath="/"> + <IconButton variants="none"> + <Icon iconType="heundeut" /> + </IconButton> + </TopNav.Item> + <TopNav.Item routePath="/"> <Text size="subTitle">행동대장</Text> - </div> - </Flex> - <Button size="medium" variants="tertiary" onClick={() => navigate(ROUTER_URLS.createEvent)}> + </TopNav.Item> + </TopNav> + <Button + size="medium" + variants="tertiary" + onClick={() => navigate(ROUTER_URLS.createEvent)} + style={{marginRight: '1rem'}} + > 정산 시작하기 </Button> </header> From df0641046c2d6640ff5ff9ab998707d93ee8d178 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:10:51 +0900 Subject: [PATCH 265/273] =?UTF-8?q?fix:=20=EB=A9=A4=EB=B2=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=8B=9C=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EC=9E=91?= =?UTF-8?q?=EB=8F=99=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95=20(#653)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 지출 생성 시 멤버 추가가 제대로 되지 않던 오류 해결 * style: console.log 제거 --- client/src/hooks/useMembersStep.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/client/src/hooks/useMembersStep.ts b/client/src/hooks/useMembersStep.ts index e58a22be9..86c42b0b6 100644 --- a/client/src/hooks/useMembersStep.ts +++ b/client/src/hooks/useMembersStep.ts @@ -2,7 +2,7 @@ import {RefObject, useEffect, useRef, useState} from 'react'; import {useNavigate} from 'react-router-dom'; import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; -import {Member, AllMembers} from 'types/serviceType'; +import {Member} from 'types/serviceType'; import getEventIdByUrl from '@utils/getEventIdByUrl'; @@ -11,7 +11,6 @@ import REGEXP from '@constants/regExp'; import useRequestPostMembers from './queries/member/useRequestPostMembers'; import useRequestPostBill from './queries/bill/useRequestPostBill'; import {BillStep} from './useAddBillFunnel'; -import useRequestGetAllMembers from './queries/member/useRequestGetAllMembers'; interface Props { billInfo: BillInfo; @@ -25,7 +24,6 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) const [nameInput, setNameInput] = useState(''); const inputRef = useRef<HTMLInputElement>(null); - const {members: allMembers} = useRequestGetAllMembers(); const {postMembersAsync, isPending: isPendingPostMembers} = useRequestPostMembers(); const {postBill, isSuccess: isSuccessPostBill, isPending: isPendingPostBill} = useRequestPostBill(); @@ -48,12 +46,12 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) } }; - const canAddMembers = nameInput && !errorMessage; + const canAddMembers = nameInput && nameInput.length <= 4; const canSubmitMembers = billInfo.members.length !== 0; const setBillInfoMemberWithId = (name: string) => { - const existingMember = allMembers.find(currentMember => currentMember.name === name); + const existingMember = currentMembers.find(currentMember => currentMember.name === name); if (existingMember) { setBillInfo(prev => ({...prev, members: [...prev.members, {id: existingMember.id, name: name}]})); } else { @@ -63,14 +61,18 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) const handleNameInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { if (event.key === 'Enter' && canAddMembers) { - event.preventDefault(); if (!billInfo.members.map(({name}) => name).includes(nameInput)) { setBillInfoMemberWithId(nameInput); } setNameInput(''); if (inputRef.current) { inputRef.current.blur(); - setTimeout(() => inputRef.current?.focus(), 0); + setTimeout(() => { + inputRef.current?.focus(); + }, 0); + } + if (event.nativeEvent.isComposing) { + return; } } }; @@ -106,10 +108,6 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) } }, [isSuccessPostBill]); - useEffect(() => { - console.log(nameInput); - }, [nameInput]); - const handlePrevStep = () => { setStep('title'); }; From 57cb1974ca93e023f1e5cb45ed7ca970269decbd Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 17:11:06 +0900 Subject: [PATCH 266/273] =?UTF-8?q?fix:=20login=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20(#655)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: login 페이지 레이아웃 수정 * style: lint 적용 --- .../EventPage/AdminPage/EventLoginPage.tsx | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index da4603e5f..03e189fc1 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -1,3 +1,5 @@ +import {css} from '@emotion/react'; + import Top from '@components/Design/components/Top/Top'; import useEventLogin from '@hooks/useEventLogin'; @@ -10,12 +12,22 @@ const EventLoginPage = () => { const {password, errorMessage, handleChange, canSubmit, submitPassword} = useEventLogin(); return ( - <> + <div + css={css` + display: flex; + flex-direction: column; + gap: 1rem; + padding: 1rem; + `} + > <Top> - <Top.Line text="행사 생성 시 설정한" /> - <Top.Line text={`${RULE.maxEventPasswordLength}자리 숫자 비밀번호를 입력해 주세요.`} /> + <Top.Line + text={`행사 생성 시 설정한 ${RULE.maxEventPasswordLength}자리`} + emphasize={[`${RULE.maxEventPasswordLength}자리`]} + /> + <Top.Line text="숫자 비밀번호를 입력해 주세요." emphasize={['비밀번호']} /> </Top> - <form onSubmit={submitPassword} style={{padding: '0 1rem'}}> + <form onSubmit={submitPassword}> <LabelInput labelText="비밀번호" errorText={errorMessage} @@ -29,7 +41,7 @@ const EventLoginPage = () => { ></LabelInput> <FixedButton disabled={!canSubmit}>관리 페이지로</FixedButton> </form> - </> + </div> ); }; From 964f94d35f19014d45b52f7b9e8a7ba8a2f679c6 Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Thu, 26 Sep 2024 21:43:02 +0900 Subject: [PATCH 267/273] =?UTF-8?q?fix:=20replace=20','=20->=20/,/g?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=B4=EC=84=9C=20=EB=AA=A8?= =?UTF-8?q?=EB=93=A0=20=EC=BD=A4=EB=A7=88=20=EC=A7=80=EC=9A=B0=EB=8A=94=20?= =?UTF-8?q?=EA=B2=83=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95=20(#670)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useMembersStep.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/hooks/useMembersStep.ts b/client/src/hooks/useMembersStep.ts index 86c42b0b6..002ccf7c4 100644 --- a/client/src/hooks/useMembersStep.ts +++ b/client/src/hooks/useMembersStep.ts @@ -88,7 +88,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) }); postBill({ title: billInfo.title, - price: Number(billInfo.price.replace(',', '')), + price: Number(billInfo.price.replace(/,/g, '')), memberIds: billInfo.members.map(member => member.id === -1 ? newMembers.members.find(m => m.name === member.name)?.id || member.id : member.id, ), @@ -96,7 +96,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) } else { postBill({ title: billInfo.title, - price: Number(billInfo.price.replace(',', '')), + price: Number(billInfo.price.replace(/,/g, '')), memberIds: billInfo.members.map(({id}) => id), }); } From 95dfd301127cdc02579ae3a99c551763220becfa Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Thu, 26 Sep 2024 21:43:16 +0900 Subject: [PATCH 268/273] =?UTF-8?q?fix:=20=EB=A9=A4=EB=B2=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=8B=9C=20=EC=A0=9C=EB=8C=80=EB=A1=9C=20=EC=9E=91?= =?UTF-8?q?=EB=8F=99=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=EC=88=98=EC=A0=95=20(#672)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 멤버 추가 시 제대로 작동하지 않는 문제 수정 * style: lint 적용 --- .../Design/components/Input/Input.style.ts | 42 +++++-- .../Design/components/Input/Input.tsx | 104 +++++++++++------- .../Design/components/Input/Input.type.ts | 6 +- .../components/LabelGroupInput/Element.tsx | 63 ----------- .../LabelGroupInput/Element.type.ts | 10 -- .../LabelGroupInput/GroupInputContext.tsx | 32 ------ .../LabelGroupInput.stories.tsx | 75 ------------- .../LabelGroupInput/LabelGroupInput.style.ts | 25 ----- .../LabelGroupInput/LabelGroupInput.tsx | 47 -------- .../LabelGroupInput/LabelGroupInput.type.ts | 10 -- .../components/LabelGroupInput/index.ts | 3 - .../LabelInput/LabelInput.stories.tsx | 56 ---------- .../components/LabelInput/LabelInput.style.ts | 31 ------ .../components/LabelInput/LabelInput.tsx | 57 ---------- .../components/LabelInput/LabelInput.type.ts | 15 --- .../components/LabelInput/useLabelInput.ts | 26 ----- client/src/components/Design/index.tsx | 4 - client/src/hooks/useMembersStep.ts | 30 ++--- client/src/pages/AccountPage/Account.tsx | 8 +- .../pages/AddBillFunnel/steps/MembersStep.tsx | 27 ++++- .../pages/AddBillFunnel/steps/TitleStep.tsx | 4 +- .../CreateEventPage/SetEventNameStep.tsx | 4 +- .../CreateEventPage/SetEventPasswordStep.tsx | 4 +- .../EventPage/AdminPage/EventLoginPage.tsx | 6 +- 24 files changed, 151 insertions(+), 538 deletions(-) delete mode 100644 client/src/components/Design/components/LabelGroupInput/Element.tsx delete mode 100644 client/src/components/Design/components/LabelGroupInput/Element.type.ts delete mode 100644 client/src/components/Design/components/LabelGroupInput/GroupInputContext.tsx delete mode 100644 client/src/components/Design/components/LabelGroupInput/LabelGroupInput.stories.tsx delete mode 100644 client/src/components/Design/components/LabelGroupInput/LabelGroupInput.style.ts delete mode 100644 client/src/components/Design/components/LabelGroupInput/LabelGroupInput.tsx delete mode 100644 client/src/components/Design/components/LabelGroupInput/LabelGroupInput.type.ts delete mode 100644 client/src/components/Design/components/LabelGroupInput/index.ts delete mode 100644 client/src/components/Design/components/LabelInput/LabelInput.stories.tsx delete mode 100644 client/src/components/Design/components/LabelInput/LabelInput.style.ts delete mode 100644 client/src/components/Design/components/LabelInput/LabelInput.tsx delete mode 100644 client/src/components/Design/components/LabelInput/LabelInput.type.ts delete mode 100644 client/src/components/Design/components/LabelInput/useLabelInput.ts diff --git a/client/src/components/Design/components/Input/Input.style.ts b/client/src/components/Design/components/Input/Input.style.ts index 666508cf8..71b5fc156 100644 --- a/client/src/components/Design/components/Input/Input.style.ts +++ b/client/src/components/Design/components/Input/Input.style.ts @@ -5,12 +5,35 @@ import {Theme} from '@theme/theme.type'; const getBorderStyle = (isFocus: boolean, theme: Theme, isError?: boolean) => isError ? `0 0 0 1px ${theme.colors.error} inset` : isFocus ? `0 0 0 1px ${theme.colors.primary} inset` : 'none'; -export const inputBoxStyle = ( - theme: Theme, - isFocus: boolean, - isError: boolean | undefined, - isAlwaysOnBorder: boolean, -) => +export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => + css([ + { + height: '1.125rem', + color: theme.colors.gray, + }, + labelTextAnimationStyle(hasFocus, hasValue), + ]); + +export const labelTextAnimationStyle = (hasFocus: boolean, hasValue: boolean) => + css({ + opacity: hasFocus || hasValue ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); + +export const errorTextStyle = (theme: Theme, isError: boolean) => + css({ + height: '1.125rem', + color: theme.colors.onErrorContainer, + + opacity: isError ? '1' : '0', + + transition: '0.2s', + transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', + }); + +export const inputBoxStyle = (theme: Theme, isFocus: boolean, isError: boolean | undefined) => css([ { display: 'flex', @@ -22,7 +45,7 @@ export const inputBoxStyle = ( boxSizing: 'border-box', boxShadow: getBorderStyle(isFocus, theme, isError), }, - isAlwaysOnBorder ? inputBoxAlwaysBorderStyle(theme) : inputBoxAnimationStyle(), + inputBoxAnimationStyle(), ]); export const inputBoxAnimationStyle = () => @@ -31,11 +54,6 @@ export const inputBoxAnimationStyle = () => transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', }); -export const inputBoxAlwaysBorderStyle = (theme: Theme) => - css({ - boxShadow: `0 0 0 1px ${theme.colors.primary} inset`, - }); - export const inputStyle = (theme: Theme) => css( { diff --git a/client/src/components/Design/components/Input/Input.tsx b/client/src/components/Design/components/Input/Input.tsx index 08d879c6a..f9cbe0858 100644 --- a/client/src/components/Design/components/Input/Input.tsx +++ b/client/src/components/Design/components/Input/Input.tsx @@ -1,65 +1,87 @@ /** @jsxImportSource @emotion/react */ -import React, {forwardRef, useImperativeHandle, useRef} from 'react'; +import React, {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; import IconButton from '@HDcomponents/IconButton/IconButton'; import {InputProps} from '@HDcomponents/Input/Input.type'; -import {inputBoxStyle, inputStyle} from '@HDcomponents/Input/Input.style'; -import {useInput} from '@HDcomponents/Input/useInput'; import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; +import Flex from '../Flex/Flex'; +import Text from '../Text/Text'; + +import {inputBoxStyle, inputStyle, labelTextStyle, errorTextStyle} from './Input.style'; + export const Input: React.FC<InputProps> = forwardRef<HTMLInputElement, InputProps>(function Input( { - value: propsValue, + value, onChange, - onFocus, - onBlur, - inputType, - isError, + onDelete, placeholder, - autoFocus, - isAlwaysOnBorder = false, + autoFocus = false, + labelText, + errorText = '', + inputType = 'input', + isError, ...htmlProps }: InputProps, ref, ) { const {theme} = useTheme(); const inputRef = useRef<HTMLInputElement>(null); - const {value, handleChange, hasFocus, handleClickDelete, handleBlur, handleFocus, handleKeyDown} = useInput({ - propsValue, - onChange, - onBlur, - onFocus, - inputRef, - autoFocus, - }); + const [hasFocus, setHasFocus] = useState(autoFocus); + const hasValue = !!value; + useImperativeHandle(ref, () => inputRef.current!); + useEffect(() => { + inputRef.current?.addEventListener('focus', () => setHasFocus(true)); + inputRef.current?.addEventListener('blur', () => setHasFocus(false)); + return () => { + inputRef.current?.removeEventListener('focus', () => setHasFocus(true)); + inputRef.current?.removeEventListener('blur', () => setHasFocus(false)); + }; + }, []); + return ( - <div css={inputBoxStyle(theme, hasFocus, isError, isAlwaysOnBorder)}> - <input - css={inputStyle(theme)} - ref={inputRef} - value={value} - onChange={handleChange} - onBlur={handleBlur} - onFocus={handleFocus} - placeholder={value ? '' : placeholder} - onKeyDown={handleKeyDown} - autoFocus={autoFocus} - {...htmlProps} - /> - {inputType === 'input' && value && hasFocus && ( - <IconButton tabIndex={-1} variants="none" onMouseDown={handleClickDelete}> - <Icon iconType="inputDelete" /> - </IconButton> - )} - {inputType === 'search' && ( - <IconButton tabIndex={-1} variants="none"> - <Icon iconType="search" /> - </IconButton> + <Flex flexDirection="column" gap="0.375rem"> + {(labelText || errorText) && ( + <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> + {labelText && ( + <Text size="caption" css={labelTextStyle(theme, hasFocus, hasValue)}> + {labelText} + </Text> + )} + {errorText && ( + <Text size="caption" css={errorTextStyle(theme, isError ?? false)}> + {errorText} + </Text> + )} + </Flex> )} - </div> + <Flex flexDirection="column" gap="0.5rem"> + <div css={inputBoxStyle(theme, hasFocus, isError)}> + <input + css={inputStyle(theme)} + ref={inputRef} + value={value} + onChange={onChange} + placeholder={value ? '' : placeholder} + autoFocus={autoFocus} + {...htmlProps} + /> + {onDelete && value && hasFocus && ( + <IconButton tabIndex={-1} variants="none" onMouseDown={onDelete}> + <Icon iconType="inputDelete" /> + </IconButton> + )} + {inputType === 'search' && ( + <IconButton tabIndex={-1} variants="none"> + <Icon iconType="search" /> + </IconButton> + )} + </div> + </Flex> + </Flex> ); }); diff --git a/client/src/components/Design/components/Input/Input.type.ts b/client/src/components/Design/components/Input/Input.type.ts index 7360c1061..d706b644f 100644 --- a/client/src/components/Design/components/Input/Input.type.ts +++ b/client/src/components/Design/components/Input/Input.type.ts @@ -2,14 +2,16 @@ import {Theme} from '@theme/theme.type'; export interface InputStyleProps { theme?: Theme; - isAlwaysOnBorder?: boolean; + isError?: boolean; } export type InputType = 'input' | 'search'; export interface InputCustomProps { inputType?: InputType; - isError?: boolean; + labelText?: string; + errorText?: string | null; + onDelete?: () => void; } export type InputOptionProps = InputStyleProps & InputCustomProps; diff --git a/client/src/components/Design/components/LabelGroupInput/Element.tsx b/client/src/components/Design/components/LabelGroupInput/Element.tsx deleted file mode 100644 index 5ffd852bd..000000000 --- a/client/src/components/Design/components/LabelGroupInput/Element.tsx +++ /dev/null @@ -1,63 +0,0 @@ -/** @jsxImportSource @emotion/react */ - -import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react'; - -import Input from '../Input/Input'; - -import {ElementProps} from './Element.type'; -import {useGroupInputContext} from './GroupInputContext'; - -const Element: React.FC<ElementProps> = forwardRef<HTMLInputElement, ElementProps>(function Element( - {elementKey, value: propsValue, onChange, onBlur, onFocus, isError, autoFocus, ...htmlProps}: ElementProps, - - ref, -) { - useImperativeHandle(ref, () => inputRef.current!); - const inputRef = useRef<HTMLInputElement>(null); - const {setHasAnyFocus, values, setValues, errors, setErrors} = useGroupInputContext(); - - useEffect(() => { - setValues({...values, [elementKey]: `${propsValue}`}); - }, [propsValue]); - - const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { - const newValue = e.target.value; - setValues({...values, [elementKey]: newValue}); - if (onChange) { - onChange(e); - } - }; - - useEffect(() => { - setErrors({...errors, [elementKey]: isError ?? false}); - }, [isError]); - - const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => { - setHasAnyFocus(false); - if (onBlur) { - onBlur(e); - } - }; - - const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => { - setHasAnyFocus(true); - if (onFocus) { - onFocus(e); - } - }; - - return ( - <Input - ref={inputRef} - isError={isError} - value={propsValue} - onChange={handleChange} - onBlur={handleBlur} - onFocus={handleFocus} - autoFocus={autoFocus} - {...htmlProps} - /> - ); -}); - -export default Element; diff --git a/client/src/components/Design/components/LabelGroupInput/Element.type.ts b/client/src/components/Design/components/LabelGroupInput/Element.type.ts deleted file mode 100644 index 2ec2ef9ed..000000000 --- a/client/src/components/Design/components/LabelGroupInput/Element.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface ElementStyleProps {} - -export interface ElementCustomProps { - elementKey: string; - isError?: boolean; -} - -export type ElementOptionProps = ElementStyleProps & ElementCustomProps; - -export type ElementProps = React.ComponentProps<'input'> & ElementOptionProps; diff --git a/client/src/components/Design/components/LabelGroupInput/GroupInputContext.tsx b/client/src/components/Design/components/LabelGroupInput/GroupInputContext.tsx deleted file mode 100644 index 142183e6b..000000000 --- a/client/src/components/Design/components/LabelGroupInput/GroupInputContext.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, {createContext, PropsWithChildren, useContext, useState} from 'react'; - -interface GroupInputContextProps { - hasAnyFocus: boolean; - setHasAnyFocus: React.Dispatch<React.SetStateAction<boolean>>; - values: {[key: string]: string}; - setValues: React.Dispatch<React.SetStateAction<{[key: string]: string}>>; - errors: {[key: string]: boolean}; - setErrors: React.Dispatch<React.SetStateAction<{[key: string]: boolean}>>; -} - -const GroupInputContext = createContext<GroupInputContextProps | undefined>(undefined); - -export const useGroupInputContext = () => { - const context = useContext(GroupInputContext); - if (!context) { - throw new Error('useGroupInputContext must be used within an GroupInputProvider'); - } - return context; -}; - -export const GroupInputProvider: React.FC<PropsWithChildren> = ({children}: React.PropsWithChildren) => { - const [hasAnyFocus, setHasAnyFocus] = useState(false); - const [values, setValues] = useState<{[key: string]: string}>({}); - const [errors, setErrors] = useState<{[key: string]: boolean}>({}); - - return ( - <GroupInputContext.Provider value={{hasAnyFocus, setHasAnyFocus, values, setValues, errors, setErrors}}> - {children} - </GroupInputContext.Provider> - ); -}; diff --git a/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.stories.tsx b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.stories.tsx deleted file mode 100644 index a2b873060..000000000 --- a/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.stories.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import {useState} from 'react'; - -import LabelGroupInput from '@HDcomponents/LabelGroupInput/LabelGroupInput'; - -const meta = { - title: 'Components/LabelGroupInput', - component: LabelGroupInput, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - argTypes: { - labelText: { - description: 'label에 들어갈 텍스트를 작성', - control: {type: 'text'}, - }, - errorText: { - description: 'error에 들어갈 텍스트를 작성', - control: {type: 'text'}, - }, - }, - args: { - labelText: '지출내역 / 금액', - errorText: 'error가 발생했을 때 나타납니다!', - }, -} satisfies Meta<typeof LabelGroupInput>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = { - render: ({...args}) => { - const [name, setName] = useState(''); - const [price, setPrice] = useState(''); - const [isError, setIsError] = useState(false); - const handleChangeName = (event: React.ChangeEvent<HTMLInputElement>) => { - if (event.target.value.length < 4) { - setName(event.target.value); - setIsError(false); - } else { - event.target.value = name; - setIsError(true); - } - }; - const handleChangePrice = (event: React.ChangeEvent<HTMLInputElement>) => { - setPrice(event.target.value); - }; - return ( - <LabelGroupInput {...args}> - <LabelGroupInput.Element - elementKey="name" - placeholder="지출내역" - value={name} - onChange={e => handleChangeName(e)} - onBlur={() => console.log('!!!')} - isError={isError} - autoFocus - /> - <LabelGroupInput.Element - value={price} - onChange={handleChangePrice} - elementKey="price" - placeholder="금액" - onBlur={() => console.log('!!!')} - isError={false} - autoFocus - /> - </LabelGroupInput> - ); - }, -}; diff --git a/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.style.ts b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.style.ts deleted file mode 100644 index df64636e9..000000000 --- a/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.style.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean) => - css({ - height: '1.125rem', - color: theme.colors.gray, - - opacity: hasFocus || hasValue ? '1' : '0', - - transition: '0.2s', - transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - }); - -export const errorTextStyle = (theme: Theme, isError: boolean) => - css({ - height: '1.125rem', - color: theme.colors.onErrorContainer, - - opacity: isError ? '1' : '0', - - transition: '0.2s', - transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - }); diff --git a/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.tsx b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.tsx deleted file mode 100644 index 3c60e14a6..000000000 --- a/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/** @jsxImportSource @emotion/react */ - -import Text from '@HDcomponents/Text/Text'; -import {useTheme} from '@theme/HDesignProvider'; - -import Flex from '../Flex/Flex'; - -import {LabelGroupInputProps} from './LabelGroupInput.type'; -import {errorTextStyle, labelTextStyle} from './LabelGroupInput.style'; -import Element from './Element'; -import {GroupInputProvider, useGroupInputContext} from './GroupInputContext'; - -const LabelGroupInput: React.FC<LabelGroupInputProps> = ({labelText, errorText, children}: LabelGroupInputProps) => { - const {theme} = useTheme(); - const {hasAnyFocus, values, errors} = useGroupInputContext(); - - const hasAnyValue = !Object.values(values).every(value => value === ''); - const hasAnyError = !Object.values(errors).every(error => !error); - - return ( - <Flex flexDirection="column" gap="0.375rem"> - <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> - <Text size="caption" css={labelTextStyle(theme, hasAnyFocus, hasAnyValue)}> - {labelText} - </Text> - {errorText && ( - <Text size="caption" css={errorTextStyle(theme, hasAnyError)}> - {errorText} - </Text> - )} - </Flex> - <Flex flexDirection="column" gap="0.5rem"> - {children} - </Flex> - </Flex> - ); -}; - -const LabelGroupInputContainer = (props: LabelGroupInputProps) => ( - <GroupInputProvider> - <LabelGroupInput {...props} /> - </GroupInputProvider> -); - -LabelGroupInputContainer.Element = Element; - -export default LabelGroupInputContainer; diff --git a/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.type.ts b/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.type.ts deleted file mode 100644 index 8507311b5..000000000 --- a/client/src/components/Design/components/LabelGroupInput/LabelGroupInput.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -export interface LabelGroupInputStyleProps {} - -export interface LabelGroupInputCustomProps { - labelText: string; - errorText: string | null; -} - -export type LabelGroupInputOptionProps = LabelGroupInputStyleProps & LabelGroupInputCustomProps; - -export type LabelGroupInputProps = React.ComponentProps<'input'> & LabelGroupInputOptionProps; diff --git a/client/src/components/Design/components/LabelGroupInput/index.ts b/client/src/components/Design/components/LabelGroupInput/index.ts deleted file mode 100644 index c31f35eaf..000000000 --- a/client/src/components/Design/components/LabelGroupInput/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import LabelGroupInputContainer from './LabelGroupInput'; - -export {LabelGroupInputContainer as LabelGroupInput}; diff --git a/client/src/components/Design/components/LabelInput/LabelInput.stories.tsx b/client/src/components/Design/components/LabelInput/LabelInput.stories.tsx deleted file mode 100644 index 9bff764ef..000000000 --- a/client/src/components/Design/components/LabelInput/LabelInput.stories.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/** @jsxImportSource @emotion/react */ -import type {Meta, StoryObj} from '@storybook/react'; - -import {useEffect, useState} from 'react'; - -import LabelInput from '@HDcomponents/LabelInput/LabelInput'; - -const meta = { - title: 'Components/LabelInput', - component: LabelInput, - tags: ['autodocs'], - parameters: { - // layout: 'centered', - }, - argTypes: { - labelText: { - description: 'label에 들어갈 텍스트를 작성', - control: {type: 'text'}, - }, - isError: { - description: '', - control: {type: 'boolean'}, - }, - errorText: { - description: 'error에 들어갈 텍스트를 작성', - control: {type: 'text'}, - }, - }, - args: { - // value: '', - labelText: '이름', - errorText: 'error가 발생했을 때 나타납니다!', - autoFocus: true, - }, -} satisfies Meta<typeof LabelInput>; - -export default meta; - -type Story = StoryObj<typeof meta>; - -export const Playground: Story = { - render: ({...args}) => { - const [value, setValue] = useState(''); - const [isError, setIsError] = useState(false); - const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { - if (event.target.value.length < 4) { - setValue(event.target.value); - setIsError(false); - } else { - event.target.value = value; - setIsError(true); - } - }; - return <LabelInput value={value} onChange={e => handleChange(e)} isError={isError} {...args} />; - }, -}; diff --git a/client/src/components/Design/components/LabelInput/LabelInput.style.ts b/client/src/components/Design/components/LabelInput/LabelInput.style.ts deleted file mode 100644 index e6f00284d..000000000 --- a/client/src/components/Design/components/LabelInput/LabelInput.style.ts +++ /dev/null @@ -1,31 +0,0 @@ -import {css} from '@emotion/react'; - -import {Theme} from '@theme/theme.type'; - -export const labelTextStyle = (theme: Theme, hasFocus: boolean, hasValue: boolean, isAlwaysOnLabel: boolean) => - css([ - { - height: '1.125rem', - color: theme.colors.gray, - }, - !isAlwaysOnLabel && labelTextAnimationStyle(hasFocus, hasValue), - ]); - -export const labelTextAnimationStyle = (hasFocus: boolean, hasValue: boolean) => - css({ - opacity: hasFocus || hasValue ? '1' : '0', - - transition: '0.2s', - transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - }); - -export const errorTextStyle = (theme: Theme, isError: boolean) => - css({ - height: '1.125rem', - color: theme.colors.onErrorContainer, - - opacity: isError ? '1' : '0', - - transition: '0.2s', - transitionTimingFunction: 'cubic-bezier(0.7, 0.62, 0.62, 1.16)', - }); diff --git a/client/src/components/Design/components/LabelInput/LabelInput.tsx b/client/src/components/Design/components/LabelInput/LabelInput.tsx deleted file mode 100644 index 8f7b1b5e3..000000000 --- a/client/src/components/Design/components/LabelInput/LabelInput.tsx +++ /dev/null @@ -1,57 +0,0 @@ -/** @jsxImportSource @emotion/react */ - -import {forwardRef, useImperativeHandle, useRef} from 'react'; - -import Text from '@HDcomponents/Text/Text'; -import {useTheme} from '@theme/HDesignProvider'; - -import Input from '../Input/Input'; -import Flex from '../Flex/Flex'; - -import {errorTextStyle, labelTextStyle} from './LabelInput.style'; -import {useLabelInput} from './useLabelInput'; -import {LabelInputProps} from './LabelInput.type'; - -const LabelInput: React.FC<LabelInputProps> = forwardRef<HTMLInputElement, LabelInputProps>(function LabelInput( - { - labelText, - errorText, - isError, - isAlwaysOnLabel = false, - isAlwaysOnInputBorder = false, - ...htmlProps - }: LabelInputProps, - ref, -) { - useImperativeHandle(ref, () => inputRef.current!); - - const {theme} = useTheme(); - const inputRef = useRef<HTMLInputElement>(null); - const {hasFocus} = useLabelInput({inputRef}); - - return ( - <Flex flexDirection="column" gap="0.375rem"> - <Flex justifyContent="spaceBetween" paddingInline="0.5rem" margin="0 0 0.375rem 0"> - <Text size="caption" css={labelTextStyle(theme, hasFocus, !!htmlProps.value, isAlwaysOnLabel)}> - {labelText} - </Text> - {errorText && ( - <Text size="caption" css={errorTextStyle(theme, isError ?? false)}> - {errorText} - </Text> - )} - </Flex> - <Flex flexDirection="column" gap="0.5rem"> - <Input - ref={inputRef} - isError={isError} - placeholder={labelText} - isAlwaysOnBorder={isAlwaysOnInputBorder} - {...htmlProps} - /> - </Flex> - </Flex> - ); -}); - -export default LabelInput; diff --git a/client/src/components/Design/components/LabelInput/LabelInput.type.ts b/client/src/components/Design/components/LabelInput/LabelInput.type.ts deleted file mode 100644 index 84bfc7279..000000000 --- a/client/src/components/Design/components/LabelInput/LabelInput.type.ts +++ /dev/null @@ -1,15 +0,0 @@ -export interface LabelInputStyleProps { - isAlwaysOnLabel?: boolean; - isAlwaysOnInputBorder?: boolean; -} - -export interface LabelInputCustomProps { - labelText: string; - errorText: string | null; - isError?: boolean; - autoFocus: boolean; -} - -export type LabelInputOptionProps = LabelInputCustomProps & LabelInputStyleProps; - -export type LabelInputProps = React.ComponentProps<'input'> & LabelInputOptionProps; diff --git a/client/src/components/Design/components/LabelInput/useLabelInput.ts b/client/src/components/Design/components/LabelInput/useLabelInput.ts deleted file mode 100644 index e967c5f89..000000000 --- a/client/src/components/Design/components/LabelInput/useLabelInput.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {RefObject, useEffect, useState} from 'react'; - -interface UseLabelInput<T> { - inputRef: RefObject<HTMLInputElement>; - autoFocus?: boolean; -} - -export const useLabelInput = <T>({inputRef, autoFocus}: UseLabelInput<T>) => { - const [hasFocus, setHasFocus] = useState(inputRef.current === document.activeElement); - - useEffect(() => { - setHasFocus(inputRef.current === document.activeElement); - }, []); - - useEffect(() => { - inputRef.current?.addEventListener('focus', () => setHasFocus(true)); - inputRef.current?.addEventListener('blur', () => setHasFocus(false)); - - return () => { - inputRef.current?.removeEventListener('focus', () => setHasFocus(true)); - inputRef.current?.removeEventListener('blur', () => setHasFocus(false)); - }; - }, []); - - return {hasFocus}; -}; diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx index a75245994..aaada3e57 100644 --- a/client/src/components/Design/index.tsx +++ b/client/src/components/Design/index.tsx @@ -14,9 +14,7 @@ import Flex from './components/Flex/Flex'; import Icon from './components/Icon/Icon'; import IconButton from './components/IconButton/IconButton'; import Input from './components/Input/Input'; -import LabelInput from './components/LabelInput/LabelInput'; import ListButton from './components/ListButton/ListButton'; -import LabelGroupInput from './components/LabelGroupInput/LabelGroupInput'; import Top from './components/Top/Top'; import Tab from './components/Tabs/Tab'; import Tabs from './components/Tabs/Tabs'; @@ -43,9 +41,7 @@ export { Icon, IconButton, Input, - LabelInput, ListButton, - LabelGroupInput, Top, Tab, Tabs, diff --git a/client/src/hooks/useMembersStep.ts b/client/src/hooks/useMembersStep.ts index 002ccf7c4..b7183124d 100644 --- a/client/src/hooks/useMembersStep.ts +++ b/client/src/hooks/useMembersStep.ts @@ -5,6 +5,7 @@ import {BillInfo} from '@pages/AddBillFunnel/AddBillFunnel'; import {Member} from 'types/serviceType'; import getEventIdByUrl from '@utils/getEventIdByUrl'; +import {isIOS} from '@utils/detectDevice'; import REGEXP from '@constants/regExp'; @@ -23,6 +24,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) const [errorMessage, setErrorMessage] = useState(''); const [nameInput, setNameInput] = useState(''); const inputRef = useRef<HTMLInputElement>(null); + const hiddenRef = useRef<HTMLInputElement>(null); const {postMembersAsync, isPending: isPendingPostMembers} = useRequestPostMembers(); @@ -59,24 +61,25 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) } }; - const handleNameInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { - if (event.key === 'Enter' && canAddMembers) { - if (!billInfo.members.map(({name}) => name).includes(nameInput)) { - setBillInfoMemberWithId(nameInput); - } + const addMembersFromInput = () => { + if (!billInfo.members.map(({name}) => name).includes(nameInput)) { + setBillInfoMemberWithId(nameInput); setNameInput(''); - if (inputRef.current) { - inputRef.current.blur(); - setTimeout(() => { - inputRef.current?.focus(); - }, 0); - } - if (event.nativeEvent.isComposing) { - return; + if (isIOS()) { + hiddenRef.current?.focus(); + inputRef.current?.focus(); } } }; + const handleNameInputEnter = (event: React.KeyboardEvent<HTMLInputElement>) => { + if (event.nativeEvent.isComposing) return; + if (event.key === 'Enter' && canAddMembers && inputRef.current) { + event.preventDefault(); + addMembersFromInput(); + } + }; + const handlePostBill = async () => { if (billInfo.members.map(({id}) => id).includes(-1)) { const newMembers = await postMembersAsync({ @@ -116,6 +119,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) errorMessage, nameInput, inputRef, + hiddenRef, handleNameInputChange, handleNameInputEnter, isPendingPostBill, diff --git a/client/src/pages/AccountPage/Account.tsx b/client/src/pages/AccountPage/Account.tsx index 0490ead31..5939ae364 100644 --- a/client/src/pages/AccountPage/Account.tsx +++ b/client/src/pages/AccountPage/Account.tsx @@ -5,7 +5,7 @@ import BankSelectModal from '@components/Modal/BankSelectModal/BankSelectModal'; import useAccount from '@hooks/useAccount'; -import {FixedButton, Flex, FunnelLayout, LabelInput, MainLayout, Top, TopNav} from '@components/Design'; +import {FixedButton, Flex, FunnelLayout, Input, MainLayout, Top, TopNav} from '@components/Design'; import getDeletedLastPath from '@utils/getDeletedLastPath'; @@ -42,17 +42,16 @@ const Account = () => { <Top.Line text="어떤 계좌로 받을까요?" emphasize={['어떤 계좌']} /> </Top> <Flex flexDirection="column" gap="1rem"> - <LabelInput + <Input labelText="은행" placeholder="은행을 선택해주세요" value={bankName ?? ''} errorText={null} autoFocus={false} - isAlwaysOnLabel readOnly onClick={() => setIsBottomSheetOpen(true)} /> - <LabelInput + <Input labelText="계좌번호" placeholder="ex) 030302-04-191806" errorText={accountNumberErrorMessage} @@ -61,7 +60,6 @@ const Account = () => { onChange={handleAccount} onPaste={handleAccountOnPaste} autoFocus={false} - isAlwaysOnLabel /> {isBottomSheetOpen && ( <BankSelectModal diff --git a/client/src/pages/AddBillFunnel/steps/MembersStep.tsx b/client/src/pages/AddBillFunnel/steps/MembersStep.tsx index fe4052d8e..5baf92ecf 100644 --- a/client/src/pages/AddBillFunnel/steps/MembersStep.tsx +++ b/client/src/pages/AddBillFunnel/steps/MembersStep.tsx @@ -1,4 +1,5 @@ import {css} from '@emotion/react'; +import {useRef} from 'react'; import Top from '@components/Design/components/Top/Top'; import ChipButton from '@components/Design/components/ChipButton/ChipButton'; @@ -7,7 +8,9 @@ import {Member} from 'types/serviceType'; import useMembersStep from '@hooks/useMembersStep'; import {BillStep} from '@hooks/useAddBillFunnel'; -import {FixedButton, Flex, LabelInput, Text} from '@components/Design'; +import {FixedButton, Flex, Input, Text} from '@components/Design'; + +import {isIOS} from '@utils/detectDevice'; import {BillInfo} from '../AddBillFunnel'; @@ -23,6 +26,7 @@ const MembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => errorMessage, nameInput, inputRef, + hiddenRef, handleNameInputChange, handleNameInputEnter, isPendingPostBill, @@ -46,7 +50,8 @@ const MembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => <Top.Line text={`${billInfo.title}에`} /> <Top.Line text="참여한 사람은 누구인가요?" emphasize={['참여한 사람']} /> </Top> - <LabelInput + + <Input ref={inputRef} labelText="이름" errorText={errorMessage ?? ''} @@ -89,6 +94,24 @@ const MembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) => </div> </div> </div> + {isIOS() && ( + <input + ref={hiddenRef} + css={css` + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + border: 0; + padding: 0; + + white-space: nowrap; + clip-path: inset(100%); + clip: rect(0 0 0 0); + overflow: hidden; + `} + /> + )} <FixedButton variants={isPendingPostBill || isPendingPostMembers ? 'loading' : 'primary'} disabled={!canSubmitMembers} diff --git a/client/src/pages/AddBillFunnel/steps/TitleStep.tsx b/client/src/pages/AddBillFunnel/steps/TitleStep.tsx index eb910991f..7e811aedf 100644 --- a/client/src/pages/AddBillFunnel/steps/TitleStep.tsx +++ b/client/src/pages/AddBillFunnel/steps/TitleStep.tsx @@ -5,7 +5,7 @@ import Top from '@components/Design/components/Top/Top'; import useTitleStep from '@hooks/useTitleStep'; import {BillStep} from '@hooks/useAddBillFunnel'; -import {FixedButton, LabelInput} from '@components/Design'; +import {FixedButton, Input} from '@components/Design'; import {BillInfo} from '../AddBillFunnel'; @@ -43,7 +43,7 @@ export const TitleStep = ({billInfo, setBillInfo, setStep}: Props) => { <Top.Line text={`${billInfo.price}원을`} /> <Top.Line text="어떤 곳에서 사용했나요??" emphasize={['어떤 곳']} /> </Top> - <LabelInput + <Input labelText="결제 내용" errorText={errorMessage ?? ''} value={billInfo.title} diff --git a/client/src/pages/CreateEventPage/SetEventNameStep.tsx b/client/src/pages/CreateEventPage/SetEventNameStep.tsx index 924c4b79d..704857456 100644 --- a/client/src/pages/CreateEventPage/SetEventNameStep.tsx +++ b/client/src/pages/CreateEventPage/SetEventNameStep.tsx @@ -4,7 +4,7 @@ import Top from '@components/Design/components/Top/Top'; import {UseSetEventNameStepReturnType} from '@hooks/useSetEventNameStep'; -import {FixedButton, Flex, LabelInput} from '@HDesign/index'; +import {FixedButton, Flex, Input} from '@HDesign/index'; type SetEventNamePageProps = UseSetEventNameStepReturnType & { moveToNextStep: () => void; @@ -37,7 +37,7 @@ const SetEventNameStep = ({ <Top.Line text="행사의 이름은 무엇인가요?" emphasize={['행사의 이름']} /> </Top> <form onSubmit={onSubmit}> - <LabelInput + <Input labelText="행사 이름" errorText={errorMessage ?? ''} value={eventName} diff --git a/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx index 45370fd01..6c29fcac3 100644 --- a/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx +++ b/client/src/pages/CreateEventPage/SetEventPasswordStep.tsx @@ -4,7 +4,7 @@ import Top from '@components/Design/components/Top/Top'; import useSetEventPasswordStep, {UseSetEventPasswordStepReturnType} from '@hooks/useSetEventPasswordStep'; -import {FixedButton, LabelInput} from '@HDesign/index'; +import {FixedButton, Input} from '@HDesign/index'; import RULE from '@constants/rule'; @@ -41,7 +41,7 @@ const SetEventPasswordStep = ({eventName, moveToNextStep, setEventToken}: SetEve <Top.Line text="비밀번호는 무엇으로 할까요?" emphasize={['비밀번호']} /> </Top> <form onSubmit={submit}> - <LabelInput + <Input labelText="비밀번호" errorText={errorMessage} value={password} diff --git a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx index 03e189fc1..734db75b4 100644 --- a/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx +++ b/client/src/pages/EventPage/AdminPage/EventLoginPage.tsx @@ -4,7 +4,7 @@ import Top from '@components/Design/components/Top/Top'; import useEventLogin from '@hooks/useEventLogin'; -import {FixedButton, LabelInput} from '@HDesign/index'; +import {FixedButton, Input} from '@HDesign/index'; import RULE from '@constants/rule'; @@ -28,7 +28,7 @@ const EventLoginPage = () => { <Top.Line text="숫자 비밀번호를 입력해 주세요." emphasize={['비밀번호']} /> </Top> <form onSubmit={submitPassword}> - <LabelInput + <Input labelText="비밀번호" errorText={errorMessage} value={password} @@ -38,7 +38,7 @@ const EventLoginPage = () => { onChange={e => handleChange(e)} isError={!!errorMessage} autoFocus - ></LabelInput> + ></Input> <FixedButton disabled={!canSubmit}>관리 페이지로</FixedButton> </form> </div> From 46c8c9bfdce6d88da5f266ea818526ca9c1c14bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=90=E1=85=A2=E1=84=92=E1=85=AE?= =?UTF-8?q?=E1=86=AB?= <rhymint@gmail.com> Date: Thu, 26 Sep 2024 21:44:39 +0900 Subject: [PATCH 269/273] =?UTF-8?q?fix:=20fe=EC=97=90=EC=84=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20workflow=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-dev.yml | 72 --------------------- .github/workflows/backend-prod.yml | 74 ---------------------- .github/workflows/backend-pull-request.yml | 44 ------------- 3 files changed, 190 deletions(-) delete mode 100644 .github/workflows/backend-dev.yml delete mode 100644 .github/workflows/backend-prod.yml delete mode 100644 .github/workflows/backend-pull-request.yml diff --git a/.github/workflows/backend-dev.yml b/.github/workflows/backend-dev.yml deleted file mode 100644 index a3257f028..000000000 --- a/.github/workflows/backend-dev.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: backend-push - -on: - push: - branches: [ "be-dev" ] - -jobs: - build: - runs-on: [ self-hosted, backend-dev ] - - defaults: - run: - shell: bash - working-directory: ./server - - permissions: - contents: read - - steps: - - name: CheckOut - uses: actions/checkout@v4 - with: - token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} - submodules: true - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Test with Gradle Wrapper - run: ./gradlew clean build - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Set up Docker BuildX - uses: docker/setup-buildx-action@v3 - - - name: Build and push - run: | - docker buildx build --platform linux/arm64 -t \ - ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} --push . - - deploy: - needs: build - runs-on: [ self-hosted, backend-dev ] - steps: - - name: Docker remove - run: | - CONTAINER_IDS=$(sudo docker ps -qa) - if [ -n "$CONTAINER_IDS" ]; then - sudo docker rm -f $CONTAINER_IDS - else - echo "No running containers found." - fi - - - name: Docker Image pull - run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} - - - name: Docker run - run: sudo docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=dev -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_DEV }} diff --git a/.github/workflows/backend-prod.yml b/.github/workflows/backend-prod.yml deleted file mode 100644 index f7daacd33..000000000 --- a/.github/workflows/backend-prod.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: backend-push - -on: - push: - branches: [ "main" ] - paths: - - 'server/**' - -jobs: - build: - runs-on: ubuntu-latest - - defaults: - run: - shell: bash - working-directory: ./server - - permissions: - contents: read - - steps: - - name: CheckOut - uses: actions/checkout@v4 - with: - token: ${{secrets.CONFIG_SUBMODULE_TOKEN}} - submodules: true - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Test with Gradle Wrapper - run: ./gradlew clean build - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Set up Docker BuildX - uses: docker/setup-buildx-action@v3 - - - name: Build and push - run: | - docker buildx build --platform linux/arm64 -t \ - ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} --push . - - deploy: - needs: build - runs-on: [ self-hosted, backend-prod ] - steps: - - name: Docker remove - run: | - CONTAINER_IDS=$(sudo docker ps -qa) - if [ -n "$CONTAINER_IDS" ]; then - sudo docker rm -f $CONTAINER_IDS - else - echo "No running containers found." - fi - - - name: Docker Image pull - run: sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} - - - name: Docker run - run: sudo docker run -d -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod -v log-volume:/app/logs --name haengdong-backend ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE_BE_PROD }} diff --git a/.github/workflows/backend-pull-request.yml b/.github/workflows/backend-pull-request.yml deleted file mode 100644 index df008fd97..000000000 --- a/.github/workflows/backend-pull-request.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: backend-pull-request - -on: - pull_request: - branches: [ "main", "be-dev" ] - -jobs: - build: - runs-on: [ ubuntu-latest ] - - defaults: - run: - working-directory: ./server - - steps: - - name: CheckOut - uses: actions/checkout@v4 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - - - name: Grant execute permission for gradlew - run: chmod +x gradlew - - - name: Test with Gradle Wrapper - run: ./gradlew clean build - - - name: publish unit test results - uses: EnricoMi/publish-unit-test-result-action@v2 - if: always() - with: - files: server/build/test-results/test/TEST-*.xml - - - name: add comments to a pull request - uses: mikepenz/action-junit-report@v3 - if: always() - with: - report_paths: server/build/test-results/test/TEST-*.xml From 3c7d85bbdaf651744410bc9ce795f8b3ea3eb948 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 27 Sep 2024 01:13:29 +0900 Subject: [PATCH 270/273] =?UTF-8?q?refactor:=20=EC=84=B1=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8A=94=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=EC=9D=84=20=EC=9D=BC=EB=B6=80=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0=20(#659)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: 충돌 병합 * refactor: lazy 로딩 적용 * chore: 경로 문제 해결 * feat: Lottie를 컴포넌트로 구현 * feat: primary컬러를 export * feat: Lottie컴포넌트를 버튼에서 사용하도록 함 * style: 린트 적용 * chore: 토스 이미지 크기 최적화 * feat: 내용이 없을 경우 공백 렌더링 * chore: 사용하지 않는 코드 제거 --- .gitmodules | 4 - client/package-lock.json | 150 ++++++++- client/package.json | 3 +- .../src/assets/image/Toss_Symbol_Primary.png | Bin 925412 -> 5800 bytes client/src/assets/image/addBillMockup.svg | 312 ----------------- client/src/assets/image/addMemberMockup.svg | 317 ------------------ client/src/assets/image/heundeut.svg | 1 - .../src/assets/image/memberReportMockup.svg | 311 ----------------- client/src/assets/image/runningDog.svg | 9 - client/src/assets/image/standingDog.svg | 9 - .../Design/components/Button/Button.tsx | 10 +- .../components/FixedButton/FixedButton.tsx | 19 +- .../Design/components/Icon/Icon.tsx | 3 +- .../Design/components/Lottie/Lottie.style.ts | 66 ++++ .../Design/components/Lottie/Lottie.tsx | 23 ++ .../NumberKeyboard/NumberKeyboard.tsx | 4 +- .../Design/components/Text/Text.tsx | 2 +- client/src/components/Design/index.tsx | 10 +- client/src/components/Design/token/colors.ts | 2 + client/src/components/Logo/RunningDogLogo.tsx | 4 +- .../src/components/Logo/StandingDogLogo.tsx | 4 +- client/src/components/Toast/Toast.tsx | 3 +- client/src/global.d.ts | 1 + client/src/mocks/handlers/eventHandlers.ts | 6 +- .../pages/EventPage/AdminPage/EventMember.tsx | 2 +- client/src/pages/MainPage/MainPage.tsx | 2 +- client/src/pages/MainPage/Nav/Nav.tsx | 2 +- .../pages/MainPage/Section/AddBillSection.tsx | 6 +- .../MainPage/Section/AddMemberSection.tsx | 8 +- .../MainPage/Section/DescriptionSection.tsx | 3 +- .../pages/MainPage/Section/MainSection.tsx | 8 +- .../pages/MainPage/Section/ReportSection.tsx | 6 +- client/src/router.tsx | 24 +- client/webpack.common.mjs | 2 +- client/webpack.dev.mjs | 22 ++ 35 files changed, 309 insertions(+), 1049 deletions(-) delete mode 100644 .gitmodules delete mode 100644 client/src/assets/image/addBillMockup.svg delete mode 100644 client/src/assets/image/addMemberMockup.svg delete mode 100644 client/src/assets/image/heundeut.svg delete mode 100644 client/src/assets/image/memberReportMockup.svg delete mode 100644 client/src/assets/image/runningDog.svg delete mode 100644 client/src/assets/image/standingDog.svg create mode 100644 client/src/components/Design/components/Lottie/Lottie.style.ts create mode 100644 client/src/components/Design/components/Lottie/Lottie.tsx diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index d013a93bc..000000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "server/src/main/resources/config"] - branch = main - path = server/src/main/resources/config - url = https://github.com/woowacourse-teams/2024-haeng-dong-config.git diff --git a/client/package-lock.json b/client/package-lock.json index 95211e1e6..018acf6d8 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,7 +12,6 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "lottie-react": "^2.4.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", @@ -72,6 +71,7 @@ "prettier": "3.3.2", "storybook": "^8.2.2", "storybook-addon-react-router-v6": "^2.0.15", + "terser-webpack-plugin": "^5.3.10", "ts-jest": "^29.2.4", "ts-loader": "^9.5.1", "ts-node": "^10.9.2", @@ -79,6 +79,7 @@ "typescript-eslint": "^7.16.0", "undici": "^5.28.4", "webpack": "^5.93.0", + "webpack-bundle-analyzer": "^4.10.2", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.4", "webpack-merge": "^6.0.1" @@ -4219,6 +4220,12 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "dev": true + }, "node_modules/@remix-run/router": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.0.tgz", @@ -10554,6 +10561,12 @@ "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", "dev": true }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true + }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", @@ -11024,6 +11037,12 @@ "webpack": "^4 || ^5" } }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -13199,6 +13218,21 @@ "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -17517,23 +17551,6 @@ "loose-envify": "cli.js" } }, - "node_modules/lottie-react": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", - "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", - "dependencies": { - "lottie-web": "^5.10.2" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/lottie-web": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", - "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" - }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", @@ -17947,6 +17964,15 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -18629,6 +18655,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -20545,6 +20580,20 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -21821,6 +21870,15 @@ "node": ">=0.6" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -22801,6 +22859,62 @@ } } }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/webpack-cli": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz", diff --git a/client/package.json b/client/package.json index 8c308b08b..932e4e911 100644 --- a/client/package.json +++ b/client/package.json @@ -71,6 +71,7 @@ "prettier": "3.3.2", "storybook": "^8.2.2", "storybook-addon-react-router-v6": "^2.0.15", + "terser-webpack-plugin": "^5.3.10", "ts-jest": "^29.2.4", "ts-loader": "^9.5.1", "ts-node": "^10.9.2", @@ -78,6 +79,7 @@ "typescript-eslint": "^7.16.0", "undici": "^5.28.4", "webpack": "^5.93.0", + "webpack-bundle-analyzer": "^4.10.2", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.4", "webpack-merge": "^6.0.1" @@ -86,7 +88,6 @@ "@emotion/react": "^11.11.4", "@sentry/react": "^8.25.0", "@tanstack/react-query": "^5.51.23", - "lottie-react": "^2.4.0", "react": "^18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "^18.3.1", diff --git a/client/src/assets/image/Toss_Symbol_Primary.png b/client/src/assets/image/Toss_Symbol_Primary.png index c6105618f9b7893cfd027665c9db86a08d595f00..073a2692474bb5fe6dcf8661c078748862760aa7 100644 GIT binary patch literal 5800 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 literal 925412 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%0AeW!ihCE6^s+2R0AkHqR*}G;l*2dO4dwtV%19 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ⅅ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 |`GzQ;a3B&U4t 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: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 #`$*cFSb*($t`3V8 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 A!~g&Q diff --git a/client/src/assets/image/addBillMockup.svg b/client/src/assets/image/addBillMockup.svg deleted file mode 100644 index c7e4aa109..000000000 --- a/client/src/assets/image/addBillMockup.svg +++ /dev/null @@ -1,312 +0,0 @@ -<svg width="100%" height="100%" viewBox="0 0 430 867" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<path d="M358.532 867H71.3893C33.968 867 3.6333 836.665 3.6333 799.244V348.944V282.739V265.653V199.447V170.878V136.894V67.6347C3.6333 30.2134 33.968 -0.12131 71.3893 -0.12131H358.532C395.954 -0.12131 426.288 30.2134 426.288 67.6347V799.244C426.288 836.665 395.954 867 358.532 867ZM71.9202 1.8971C35.3203 1.8971 5.65171 31.5657 5.65171 68.1655V798.713C5.65171 835.312 35.3203 864.982 71.9202 864.982H358.001C394.601 864.982 424.27 835.312 424.27 798.713V68.1655C424.27 31.5657 394.601 1.8971 358.001 1.8971H71.9202ZM357.471 862.963H72.451C36.6727 862.963 7.67012 833.96 7.67012 798.182V68.6964C7.67012 32.9181 36.6727 3.91551 72.451 3.91551H357.471C393.247 3.91551 422.251 32.9181 422.251 68.6964V798.182C422.251 833.96 393.247 862.963 357.471 862.963ZM73.0908 6.49706C38.683 6.49706 10.7906 34.3895 10.7906 68.7973V798.081C10.7906 832.489 38.683 860.381 73.0908 860.381H356.831C391.239 860.381 419.131 832.489 419.131 798.081V68.7973C419.131 34.3895 391.239 6.49706 356.831 6.49706H73.0908Z" fill="#5E465D"/> -<path d="M358.001 864.981H71.9193C35.3195 864.981 5.65088 835.312 5.65088 798.713V68.1653C5.65088 31.5655 35.3195 1.89689 71.9193 1.89689H358.001C394.6 1.89689 424.269 31.5655 424.269 68.1653V798.713C424.269 835.312 394.6 864.981 358.001 864.981ZM72.4502 3.9153C36.6718 3.9153 7.66929 32.9179 7.66929 68.6962V798.181C7.66929 833.96 36.6718 862.963 72.4502 862.963H357.47C393.246 862.963 422.251 833.96 422.251 798.181V68.6962C422.251 32.9179 393.246 3.9153 357.47 3.9153H72.4502Z" fill="#A597A4"/> -<path d="M356.831 860.381H73.0908C38.6829 860.381 10.7905 832.489 10.7905 798.08V68.7972C10.7905 34.3893 38.6829 6.49689 73.0908 6.49689H356.831C391.239 6.49689 419.131 34.3893 419.131 68.7972V798.08C419.131 832.489 391.239 860.381 356.831 860.381ZM72.7739 20.3169C45.9593 20.3169 24.223 42.0552 24.223 68.8698V798.008C24.223 824.823 45.9593 846.561 72.7759 846.561H357.146C383.962 846.561 405.698 824.823 405.698 798.008V68.8698C405.698 42.0552 383.962 20.3169 357.146 20.3169H324.147H105.383C94.1145 20.3169 83.421 20.3169 72.7739 20.3169Z" fill="#1D1D1B"/> -<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> -<mask id="mask0_1835_8259" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> -<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> -</mask> -<g mask="url(#mask0_1835_8259)"> -<g clip-path="url(#clip0_1835_8259)"> -<mask id="mask1_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> -<path d="M406 20H24V847H406V20Z" fill="white"/> -</mask> -<g mask="url(#mask1_1835_8259)"> -<path d="M406 20H24V847H406V20Z" fill="#F1F0F5"/> -<path d="M51.8437 93.2812H41.9297V89.1094H51.8437V93.2812ZM43.8906 91.7892H49.8906V90.5937H43.8906V91.7892ZM52.7109 81.7267H41.0391V80.2345H52.7109V81.7267ZM46.9062 82.1017C48.4583 82.1017 49.6406 82.2734 50.4531 82.6172C51.2708 82.9557 51.6797 83.4583 51.6797 84.125C51.6797 84.7917 51.2708 85.297 50.4531 85.6407C49.6406 85.9845 48.4583 86.1562 46.9062 86.1562C45.3594 86.1562 44.1745 85.9845 43.3516 85.6407C42.5286 85.297 42.1172 84.7917 42.1172 84.125C42.1172 83.4583 42.5286 82.9557 43.3516 82.6172C44.1745 82.2734 45.3594 82.1017 46.9062 82.1017ZM46.9062 83.4375C46.2708 83.4375 45.7656 83.461 45.3906 83.5079C45.0156 83.5548 44.7318 83.6277 44.5391 83.7267C44.3464 83.8256 44.25 83.9583 44.25 84.125C44.25 84.2865 44.3464 84.4168 44.5391 84.5157C44.7318 84.6147 45.0208 84.6902 45.4062 84.7423C45.7917 84.7944 46.2917 84.8203 46.9062 84.8203C47.5312 84.8203 48.0339 84.7944 48.4141 84.7423C48.7995 84.6902 49.0859 84.6147 49.2734 84.5157C49.4609 84.4168 49.5547 84.2865 49.5547 84.125C49.5547 83.9583 49.4609 83.8256 49.2734 83.7267C49.0859 83.6277 48.8047 83.5548 48.4297 83.5079C48.0547 83.461 47.5469 83.4375 46.9062 83.4375ZM47.8984 81.3047H45.8984V79.0938H47.8984V81.3047ZM53.3984 88.3907H40.4297V86.8359H53.3984V88.3907ZM47.8984 87.6798H45.8984V85.6484H47.8984V87.6798Z" fill="#B2B1B6"/> -<path d="M73.2187 81.875H67.0781V80.25H73.2187V81.875ZM70.8594 87.1094H68.875V83.5312H70.8594V87.1094ZM74.3984 81.2344C74.3932 81.9687 74.3724 82.6458 74.3359 83.2656C74.2995 83.8854 74.2135 84.5651 74.0781 85.3047L72.1094 85.1328C72.25 84.388 72.3385 83.737 72.375 83.1797C72.4167 82.6224 72.4427 81.9818 72.4531 81.2578V81.1328V80.25H74.3984V81.1328V81.2344ZM77.875 89.8516H75.8281V79.2031H77.875V89.8516ZM79.6016 85.2187H77.0703V83.5547H79.6016V85.2187ZM78.3203 93.1953H68.3281V91.5859H78.3203V93.1953ZM70.3281 92.0937H68.3281V88.9062H70.3281V92.0937ZM66.2344 86.3437C67.9375 86.3437 69.513 86.3151 70.9609 86.2578C72.4141 86.2005 73.7839 86.0781 75.0703 85.8906L75.1641 87.3281C73.8464 87.5729 72.4635 87.7344 71.0156 87.8125C69.5677 87.8906 68.0312 87.9297 66.4062 87.9297L66.2344 86.3437ZM92.1719 93.4766H90.1797V79.2031H92.1719V93.4766ZM82.2891 88.5C83.6276 88.5104 84.8281 88.4818 85.8906 88.4141C86.9583 88.3411 88.0495 88.2135 89.1641 88.0312L89.3437 89.6406C88.2448 89.8333 87.1484 89.9661 86.0547 90.0391C84.9661 90.1068 83.7109 90.1406 82.2891 90.1406H81.0156V88.5H82.2891ZM87.7578 85.8828H83.0703V89.125H81.0156V84.3203H85.7266V82.0156H81V80.4062H87.7578V85.8828Z" fill="#56555A"/> -<path d="M406 114H24V270H406V114Z" fill="white"/> -<path d="M60.9609 151.188H58.1133V137.805H60.9609V151.188ZM58.875 145.551H55.3828V143.113H58.875V145.551ZM56.4141 150.496H53.625V138.215H56.4141V150.496ZM52.9922 142.34H42.5273V140.008H52.9922V142.34ZM47.7891 143.066C48.6875 143.066 49.4883 143.219 50.1914 143.523C50.9023 143.828 51.457 144.266 51.8555 144.836C52.2539 145.398 52.4531 146.051 52.4531 146.793C52.4531 147.512 52.2539 148.152 51.8555 148.715C51.457 149.27 50.9023 149.703 50.1914 150.016C49.4883 150.32 48.6875 150.473 47.7891 150.473C46.9062 150.473 46.1133 150.32 45.4102 150.016C44.7148 149.703 44.168 149.27 43.7695 148.715C43.3711 148.152 43.1719 147.512 43.1719 146.793C43.1719 146.051 43.3711 145.398 43.7695 144.836C44.168 144.266 44.7148 143.828 45.4102 143.523C46.1133 143.219 46.9062 143.066 47.7891 143.066ZM47.7891 145.211C47.4062 145.203 47.0664 145.262 46.7695 145.387C46.4805 145.512 46.2539 145.695 46.0898 145.938C45.9258 146.18 45.8438 146.465 45.8438 146.793C45.8438 147.113 45.9219 147.391 46.0781 147.625C46.2422 147.859 46.4688 148.043 46.7578 148.176C47.0547 148.301 47.3984 148.363 47.7891 148.363C48.1797 148.363 48.5234 148.301 48.8203 148.176C49.1172 148.043 49.3477 147.859 49.5117 147.625C49.6758 147.391 49.7578 147.113 49.7578 146.793C49.7578 146.465 49.6758 146.18 49.5117 145.938C49.3477 145.695 49.1172 145.512 48.8203 145.387C48.5234 145.262 48.1797 145.203 47.7891 145.211ZM49.2656 141.625H46.2773V138.016H49.2656V141.625ZM53.6719 151.41C55.2031 151.41 56.5234 151.562 57.6328 151.867C58.7422 152.164 59.5898 152.605 60.1758 153.191C60.7695 153.777 61.0664 154.477 61.0664 155.289C61.0664 156.109 60.7695 156.805 60.1758 157.375C59.5898 157.953 58.7422 158.395 57.6328 158.699C56.5234 159.004 55.2031 159.156 53.6719 159.156C52.1484 159.156 50.832 159.004 49.7227 158.699C48.6211 158.395 47.7734 157.953 47.1797 157.375C46.5859 156.805 46.2891 156.109 46.2891 155.289C46.2891 154.477 46.5859 153.777 47.1797 153.191C47.7734 152.605 48.6211 152.164 49.7227 151.867C50.832 151.562 52.1484 151.41 53.6719 151.41ZM53.6719 153.648C52.6953 153.641 51.8828 153.695 51.2344 153.812C50.5938 153.93 50.1055 154.113 49.7695 154.363C49.4414 154.613 49.2812 154.922 49.2891 155.289C49.2812 155.641 49.4414 155.938 49.7695 156.18C50.1055 156.414 50.5977 156.594 51.2461 156.719C51.8945 156.844 52.7031 156.906 53.6719 156.906C54.6406 156.906 55.4492 156.844 56.0977 156.719C56.7539 156.594 57.2422 156.414 57.5625 156.18C57.8906 155.945 58.0586 155.648 58.0664 155.289C58.0586 154.914 57.8906 154.605 57.5625 154.363C57.2422 154.113 56.7578 153.93 56.1094 153.812C55.4609 153.695 54.6484 153.641 53.6719 153.648ZM82.875 150.262H63.3867V147.895H82.875V150.262ZM74.5898 148.832H71.6602V144.684H74.5898V148.832ZM80.6484 146.066H65.7422V143.723H80.6484V146.066ZM80.5312 141.098H68.707V145.258H65.7422V138.766H80.5312V141.098ZM73.0781 151.316C74.6172 151.316 75.9414 151.473 77.0508 151.785C78.1602 152.09 79.0117 152.539 79.6055 153.133C80.1992 153.719 80.5 154.43 80.5078 155.266C80.5 156.094 80.1992 156.797 79.6055 157.375C79.0195 157.961 78.168 158.406 77.0508 158.711C75.9414 159.023 74.6172 159.184 73.0781 159.191C71.5234 159.184 70.1875 159.023 69.0703 158.711C67.9531 158.406 67.0938 157.961 66.4922 157.375C65.8984 156.789 65.6016 156.086 65.6016 155.266C65.6016 154.43 65.8984 153.719 66.4922 153.133C67.0938 152.539 67.9531 152.09 69.0703 151.785C70.1875 151.473 71.5234 151.316 73.0781 151.316ZM73.0781 153.602C72.0859 153.602 71.2617 153.664 70.6055 153.789C69.957 153.906 69.4648 154.09 69.1289 154.34C68.8008 154.59 68.6406 154.898 68.6484 155.266C68.6406 155.641 68.8008 155.949 69.1289 156.191C69.4648 156.434 69.957 156.613 70.6055 156.73C71.2617 156.848 72.0859 156.906 73.0781 156.906C74.0547 156.906 74.8672 156.848 75.5156 156.73C76.1719 156.613 76.6641 156.434 76.9922 156.191C77.3281 155.949 77.4961 155.641 77.4961 155.266C77.4961 154.906 77.3281 154.602 76.9922 154.352C76.6641 154.094 76.1719 153.906 75.5156 153.789C74.8594 153.664 74.0469 153.602 73.0781 153.602ZM102.551 159.156H99.7383V137.805H102.551V159.156ZM100.418 148.457H96.7969V146.066H100.418V148.457ZM97.6758 158.125H94.9336V138.191H97.6758V158.125ZM86.2148 151.832C87.7773 151.832 89.1172 151.797 90.2344 151.727C91.3516 151.656 92.5 151.516 93.6797 151.305L93.8906 153.73C92.7031 153.965 91.5352 154.121 90.3867 154.199C89.2461 154.27 87.8555 154.312 86.2148 154.328H84.7148V151.832H86.2148ZM92.6836 142.703H87.7148V153.039H84.7148V140.301H92.6836V142.703ZM112.16 141.59C112.152 142.98 111.926 144.277 111.481 145.48C111.035 146.676 110.352 147.719 109.43 148.609C108.516 149.5 107.391 150.16 106.055 150.59L104.555 148.234C105.695 147.867 106.652 147.34 107.426 146.652C108.199 145.957 108.77 145.176 109.137 144.309C109.512 143.441 109.703 142.535 109.711 141.59V140.195H112.16V141.59ZM112.734 141.578C112.734 142.445 112.91 143.27 113.262 144.051C113.613 144.824 114.156 145.52 114.891 146.137C115.625 146.746 116.543 147.215 117.645 147.543L116.238 149.875C114.926 149.484 113.828 148.879 112.945 148.059C112.063 147.23 111.398 146.266 110.953 145.164C110.516 144.055 110.297 142.859 110.297 141.578V140.195H112.734V141.578ZM116.988 141.637H105.363V139.246H116.988V141.637ZM121.781 150.473H118.793V137.805H121.781V150.473ZM124.664 145.211H120.938V142.773H124.664V145.211ZM114.785 150.895C116.262 150.895 117.539 151.059 118.617 151.387C119.703 151.707 120.535 152.176 121.113 152.793C121.691 153.41 121.981 154.148 121.981 155.008C121.981 155.867 121.691 156.605 121.113 157.223C120.535 157.848 119.703 158.324 118.617 158.652C117.539 158.988 116.262 159.156 114.785 159.156C113.293 159.156 111.996 158.988 110.895 158.652C109.793 158.324 108.945 157.848 108.352 157.223C107.766 156.605 107.473 155.867 107.473 155.008C107.473 154.148 107.766 153.41 108.352 152.793C108.945 152.176 109.789 151.707 110.883 151.387C111.984 151.059 113.285 150.895 114.785 150.895ZM114.785 153.215C113.856 153.215 113.066 153.281 112.418 153.414C111.777 153.547 111.293 153.75 110.965 154.023C110.637 154.289 110.477 154.617 110.484 155.008C110.477 155.414 110.637 155.754 110.965 156.027C111.293 156.293 111.777 156.496 112.418 156.637C113.059 156.77 113.848 156.836 114.785 156.836C115.715 156.836 116.492 156.77 117.117 156.637C117.75 156.496 118.227 156.293 118.547 156.027C118.875 155.754 119.039 155.414 119.039 155.008C119.039 154.609 118.875 154.277 118.547 154.012C118.227 153.746 117.75 153.547 117.117 153.414C116.492 153.281 115.715 153.215 114.785 153.215ZM136.91 139.316C137.988 139.316 138.949 139.629 139.793 140.254C140.645 140.871 141.312 141.758 141.797 142.914C142.281 144.062 142.527 145.398 142.535 146.922C142.527 148.453 142.281 149.797 141.797 150.953C141.312 152.102 140.645 152.984 139.793 153.602C138.949 154.219 137.988 154.527 136.91 154.527C135.816 154.527 134.844 154.219 133.992 153.602C133.141 152.984 132.473 152.102 131.988 150.953C131.512 149.797 131.273 148.453 131.273 146.922C131.273 145.398 131.512 144.062 131.988 142.914C132.473 141.758 133.141 140.871 133.992 140.254C134.844 139.629 135.816 139.316 136.91 139.316ZM136.91 142.023C136.363 142.016 135.883 142.203 135.469 142.586C135.055 142.969 134.73 143.527 134.496 144.262C134.27 144.996 134.156 145.883 134.156 146.922C134.156 147.961 134.27 148.848 134.496 149.582C134.73 150.316 135.055 150.875 135.469 151.258C135.883 151.633 136.363 151.82 136.91 151.82C137.465 151.82 137.949 151.633 138.363 151.258C138.777 150.875 139.094 150.316 139.312 149.582C139.539 148.848 139.652 147.961 139.652 146.922C139.652 145.883 139.539 144.996 139.312 144.262C139.094 143.52 138.777 142.961 138.363 142.586C137.949 142.203 137.465 142.016 136.91 142.023ZM150.996 145.281H147.176V142.785H150.996V145.281ZM150.996 151.504H147.176V149.078H150.996V151.504ZM147.984 159.156H144.984V137.805H147.984V159.156ZM159.41 159.156H156.34V151.27H159.41V159.156ZM166.816 159.156H163.781V151.27H166.816V159.156ZM171.387 152.102H151.887V149.688H171.387V152.102ZM161.578 138.531C163.094 138.531 164.441 138.73 165.621 139.129C166.801 139.527 167.715 140.09 168.363 140.816C169.02 141.543 169.348 142.387 169.348 143.348C169.348 144.293 169.02 145.121 168.363 145.832C167.715 146.535 166.801 147.082 165.621 147.473C164.441 147.863 163.094 148.059 161.578 148.059C160.062 148.059 158.719 147.863 157.547 147.473C156.375 147.082 155.461 146.535 154.805 145.832C154.156 145.121 153.832 144.293 153.832 143.348C153.832 142.387 154.156 141.543 154.805 140.816C155.461 140.09 156.375 139.527 157.547 139.129C158.719 138.73 160.062 138.531 161.578 138.531ZM161.578 140.922C160.617 140.93 159.785 141.027 159.082 141.215C158.387 141.395 157.852 141.668 157.477 142.035C157.102 142.395 156.918 142.832 156.926 143.348C156.918 143.84 157.102 144.262 157.477 144.613C157.852 144.965 158.387 145.234 159.082 145.422C159.785 145.602 160.617 145.691 161.578 145.691C162.539 145.691 163.371 145.602 164.074 145.422C164.777 145.234 165.316 144.969 165.691 144.625C166.074 144.273 166.266 143.848 166.266 143.348C166.266 142.832 166.074 142.395 165.691 142.035C165.316 141.668 164.777 141.395 164.074 141.215C163.379 141.027 162.547 140.93 161.578 140.922ZM181.137 154.258H178.16V150.777H181.137V154.258ZM190.559 159.156H187.594V137.805H190.559V159.156ZM173.578 153.133C176.234 153.117 178.57 153.074 180.586 153.004C182.609 152.926 184.555 152.762 186.422 152.512L186.609 154.727C184.547 155.086 182.426 155.32 180.246 155.43C178.066 155.531 175.695 155.582 173.133 155.582L172.734 153.133H173.578ZM186.117 142.551H173.156V140.207H186.117V142.551ZM179.625 143.395C180.672 143.395 181.602 143.562 182.414 143.898C183.234 144.227 183.867 144.695 184.312 145.305C184.766 145.914 184.992 146.613 184.992 147.402C184.992 148.184 184.766 148.879 184.312 149.488C183.867 150.09 183.234 150.559 182.414 150.895C181.602 151.23 180.672 151.398 179.625 151.398C178.594 151.398 177.676 151.23 176.871 150.895C176.066 150.559 175.438 150.09 174.984 149.488C174.539 148.879 174.316 148.184 174.316 147.402C174.316 146.613 174.539 145.914 174.984 145.305C175.438 144.695 176.066 144.227 176.871 143.898C177.676 143.562 178.594 143.395 179.625 143.395ZM179.625 145.656C179.141 145.656 178.711 145.727 178.336 145.867C177.969 146 177.68 146.199 177.469 146.465C177.258 146.73 177.152 147.043 177.152 147.402C177.152 147.77 177.254 148.082 177.457 148.34C177.668 148.59 177.961 148.785 178.336 148.926C178.711 149.059 179.141 149.125 179.625 149.125C180.125 149.125 180.566 149.059 180.949 148.926C181.332 148.785 181.625 148.59 181.828 148.34C182.031 148.082 182.133 147.77 182.133 147.402C182.133 147.043 182.031 146.73 181.828 146.465C181.625 146.199 181.332 146 180.949 145.867C180.566 145.727 180.125 145.656 179.625 145.656ZM181.16 141.543H178.16V137.91H181.16V141.543Z" fill="#56555A"/> -<path d="M47.3125 183.641C47.3125 184.599 47.1302 185.544 46.7656 186.477C46.401 187.409 45.9115 188.237 45.2969 188.961C44.6875 189.685 44.0208 190.229 43.2969 190.594L42.5625 189.625C43.224 189.307 43.8385 188.828 44.4062 188.188C44.9792 187.542 45.4375 186.818 45.7812 186.016C46.125 185.214 46.2969 184.422 46.2969 183.641V181.344H47.3125V183.641ZM47.5312 183.641C47.5312 184.406 47.7031 185.169 48.0469 185.93C48.3906 186.685 48.849 187.359 49.4219 187.953C49.9948 188.547 50.6198 188.99 51.2969 189.281L50.6094 190.25C49.8542 189.906 49.1667 189.396 48.5469 188.719C47.9323 188.042 47.4427 187.263 47.0781 186.383C46.7188 185.497 46.5417 184.583 46.5469 183.641V181.344H47.5312V183.641ZM50.8438 181.828H43.0156V180.812H50.8438V181.828ZM54.0156 193.266H52.7812V179.375H54.0156V193.266ZM63.3125 188.391H62.1094V186.281H63.3125V188.391ZM69.0469 186.516H56.4062V185.562H69.0469V186.516ZM63.3125 180.984H62.1094V179.297H63.3125V180.984ZM63.125 181.312C63.125 182.016 62.8698 182.625 62.3594 183.141C61.849 183.651 61.1641 184.055 60.3047 184.352C59.4505 184.643 58.4948 184.833 57.4375 184.922L57.0781 183.984C57.9948 183.927 58.8307 183.784 59.5859 183.555C60.3411 183.32 60.9401 183.013 61.3828 182.633C61.8255 182.247 62.0469 181.807 62.0469 181.312V181.109H63.125V181.312ZM63.3906 181.312C63.3854 181.807 63.6042 182.247 64.0469 182.633C64.4948 183.013 65.0938 183.32 65.8438 183.555C66.599 183.784 67.4375 183.927 68.3594 183.984L67.9844 184.922C66.9323 184.833 65.9792 184.643 65.125 184.352C64.2708 184.055 63.5885 183.651 63.0781 183.141C62.5677 182.625 62.3125 182.016 62.3125 181.312V181.109H63.3906V181.312ZM67.7656 181.562H57.7031V180.594H67.7656V181.562ZM67.4219 190.812H59.1719V192.516H57.9531V189.938H66.2188V188.734H57.9219V187.812H67.4219V190.812ZM67.8438 193.109H57.9531V192.172H67.8438V193.109ZM86.0938 193.266H84.8906V179.375H86.0938V193.266ZM85.25 186.078H82.5312V185.031H85.25V186.078ZM82.8906 192.547H81.7344V179.688H82.8906V192.547ZM76.1562 189.078H74.9375V181.078H76.1562V189.078ZM75.7969 188.578C76.625 188.583 77.4349 188.555 78.2266 188.492C79.0234 188.424 79.849 188.302 80.7031 188.125L80.8594 189.219C79.9427 189.385 79.0755 189.503 78.2578 189.57C77.4453 189.638 76.625 189.672 75.7969 189.672H74.9375V188.578H75.7969ZM98.7188 182.438H94.4688V181.422H98.7188V182.438ZM98.7188 185.562H94.4688V184.547H98.7188V185.562ZM99.5781 193.266H98.3438V189.312H90.2344V188.328H99.5781V193.266ZM99.5781 187.562H98.3438V179.375H99.5781V187.562ZM91.8906 180.172C92.5677 180.172 93.1797 180.312 93.7266 180.594C94.2734 180.875 94.7005 181.268 95.0078 181.773C95.3203 182.279 95.4792 182.849 95.4844 183.484C95.4792 184.135 95.3203 184.714 95.0078 185.219C94.7005 185.719 94.2734 186.112 93.7266 186.398C93.1797 186.68 92.5677 186.818 91.8906 186.812C91.2031 186.818 90.5859 186.68 90.0391 186.398C89.4922 186.112 89.0625 185.716 88.75 185.211C88.4375 184.706 88.2812 184.13 88.2812 183.484C88.2812 182.849 88.4375 182.279 88.75 181.773C89.0625 181.268 89.4922 180.875 90.0391 180.594C90.5859 180.312 91.2031 180.172 91.8906 180.172ZM91.8906 181.219C91.4219 181.219 91.0026 181.315 90.6328 181.508C90.263 181.701 89.974 181.971 89.7656 182.32C89.5573 182.664 89.4531 183.052 89.4531 183.484C89.4531 183.927 89.5573 184.323 89.7656 184.672C89.974 185.016 90.263 185.286 90.6328 185.484C91.0026 185.682 91.4219 185.781 91.8906 185.781C92.3438 185.781 92.7526 185.682 93.1172 185.484C93.487 185.286 93.776 185.016 93.9844 184.672C94.1927 184.323 94.2969 183.927 94.2969 183.484C94.2969 183.057 94.1927 182.669 93.9844 182.32C93.776 181.971 93.487 181.701 93.1172 181.508C92.7474 181.315 92.3385 181.219 91.8906 181.219ZM113.156 185.938H106.641V180.281H113.156V185.938ZM107.844 184.969H111.953V181.281H107.844V184.969ZM117.359 187.359H116.156V179.375H117.359V187.359ZM113.391 189.266C113.391 189.911 113.146 190.513 112.656 191.07C112.167 191.628 111.516 192.091 110.703 192.461C109.891 192.836 109.016 193.089 108.078 193.219L107.641 192.266C108.432 192.177 109.19 191.982 109.914 191.68C110.638 191.372 111.221 191.005 111.664 190.578C112.107 190.151 112.328 189.714 112.328 189.266V188.984H113.391V189.266ZM113.594 189.266C113.594 189.703 113.81 190.135 114.242 190.562C114.675 190.99 115.245 191.357 115.953 191.664C116.667 191.966 117.417 192.167 118.203 192.266L117.781 193.219C116.849 193.089 115.979 192.831 115.172 192.445C114.37 192.065 113.727 191.596 113.242 191.039C112.763 190.482 112.526 189.891 112.531 189.266V188.984H113.594V189.266ZM117.719 189.266H108.219V188.312H117.719V189.266ZM113.562 188.75H112.344V186.953H113.562V188.75ZM135.219 189.547H134V179.391H135.219V189.547ZM135.656 192.969H126.25V191.938H135.656V192.969ZM127.469 192.281H126.25V188.516H127.469V192.281ZM127.719 180.359C128.406 180.359 129.026 180.505 129.578 180.797C130.13 181.089 130.565 181.492 130.883 182.008C131.201 182.523 131.359 183.109 131.359 183.766C131.359 184.427 131.201 185.018 130.883 185.539C130.565 186.055 130.13 186.458 129.578 186.75C129.026 187.042 128.406 187.188 127.719 187.188C127.031 187.188 126.411 187.042 125.859 186.75C125.307 186.458 124.872 186.055 124.555 185.539C124.237 185.018 124.078 184.427 124.078 183.766C124.078 183.109 124.237 182.523 124.555 182.008C124.872 181.492 125.307 181.089 125.859 180.797C126.411 180.505 127.031 180.359 127.719 180.359ZM127.719 181.438C127.255 181.438 126.836 181.536 126.461 181.734C126.091 181.932 125.799 182.208 125.586 182.562C125.378 182.917 125.276 183.318 125.281 183.766C125.276 184.219 125.378 184.625 125.586 184.984C125.799 185.339 126.091 185.615 126.461 185.812C126.836 186.01 127.255 186.109 127.719 186.109C128.177 186.109 128.591 186.01 128.961 185.812C129.331 185.615 129.622 185.339 129.836 184.984C130.049 184.625 130.156 184.219 130.156 183.766C130.156 183.318 130.049 182.917 129.836 182.562C129.622 182.208 129.331 181.932 128.961 181.734C128.591 181.536 128.177 181.438 127.719 181.438ZM142.812 189.453H141.578V186.359H142.812V189.453ZM149.031 189.938H147.797V179.391H149.031V189.938ZM149.375 192.969H139.5V191.938H149.375V192.969ZM140.734 192.234H139.5V188.906H140.734V192.234ZM137.5 185.828C139.359 185.818 141.005 185.789 142.438 185.742C143.87 185.69 145.24 185.583 146.547 185.422L146.625 186.312C145.276 186.526 143.862 186.667 142.383 186.734C140.904 186.802 139.333 186.833 137.672 186.828L137.5 185.828ZM148.125 188.5H144.922V187.609H148.125V188.5ZM142.062 179.953C142.734 179.953 143.331 180.052 143.852 180.25C144.378 180.448 144.784 180.732 145.07 181.102C145.357 181.471 145.5 181.896 145.5 182.375C145.5 182.865 145.357 183.289 145.07 183.648C144.784 184.008 144.38 184.286 143.859 184.484C143.339 184.682 142.74 184.781 142.062 184.781C141.38 184.781 140.779 184.682 140.258 184.484C139.742 184.286 139.341 184.008 139.055 183.648C138.768 183.289 138.625 182.865 138.625 182.375C138.625 181.896 138.768 181.471 139.055 181.102C139.341 180.732 139.745 180.448 140.266 180.25C140.786 180.052 141.385 179.953 142.062 179.953ZM142.062 180.891C141.615 180.885 141.219 180.945 140.875 181.07C140.531 181.19 140.263 181.365 140.07 181.594C139.883 181.823 139.792 182.083 139.797 182.375C139.792 182.672 139.883 182.935 140.07 183.164C140.263 183.388 140.531 183.562 140.875 183.688C141.219 183.812 141.615 183.875 142.062 183.875C142.5 183.875 142.891 183.812 143.234 183.688C143.578 183.562 143.846 183.388 144.039 183.164C144.232 182.935 144.328 182.672 144.328 182.375C144.328 182.083 144.232 181.823 144.039 181.594C143.846 181.365 143.578 181.19 143.234 181.07C142.891 180.945 142.5 180.885 142.062 180.891ZM166.156 182.969H162.109V181.938H166.156V182.969ZM166.203 185.938H162.109V184.922H166.203V185.938ZM166.938 189.672H165.703V179.391H166.938V189.672ZM167.25 192.969H157.953V191.938H167.25V192.969ZM159.188 192.438H157.953V188.656H159.188V192.438ZM157.344 182.781H161.219V180.312H162.422V187.297H156.125V180.312H157.344V182.781ZM161.219 186.281V183.75H157.344V186.281H161.219ZM181.922 187.234H169.25V186.25H181.922V187.234ZM176.172 186.672H174.984V184.016H176.172V186.672ZM180.438 184.625H170.859V183.625H180.438V184.625ZM180.344 181.016H172.062V184.234H170.859V180.031H180.344V181.016ZM175.578 188.25C176.568 188.25 177.419 188.349 178.133 188.547C178.846 188.745 179.393 189.031 179.773 189.406C180.159 189.776 180.354 190.224 180.359 190.75C180.354 191.281 180.161 191.732 179.781 192.102C179.406 192.471 178.859 192.755 178.141 192.953C177.422 193.156 176.568 193.26 175.578 193.266C174.578 193.26 173.719 193.156 173 192.953C172.281 192.755 171.732 192.469 171.352 192.094C170.971 191.724 170.781 191.276 170.781 190.75C170.781 190.224 170.971 189.776 171.352 189.406C171.732 189.031 172.281 188.745 173 188.547C173.719 188.349 174.578 188.25 175.578 188.25ZM175.578 189.219C174.839 189.219 174.203 189.279 173.672 189.398C173.141 189.518 172.732 189.695 172.445 189.93C172.164 190.159 172.026 190.432 172.031 190.75C172.026 191.073 172.164 191.349 172.445 191.578C172.732 191.807 173.141 191.982 173.672 192.102C174.203 192.221 174.839 192.281 175.578 192.281C176.307 192.281 176.938 192.221 177.469 192.102C178 191.982 178.409 191.807 178.695 191.578C178.982 191.349 179.125 191.073 179.125 190.75C179.125 190.432 178.982 190.159 178.695 189.93C178.409 189.695 178 189.518 177.469 189.398C176.938 189.279 176.307 189.219 175.578 189.219ZM189.406 179.625C190.432 179.625 191.312 179.716 192.047 179.898C192.786 180.081 193.349 180.352 193.734 180.711C194.12 181.07 194.312 181.505 194.312 182.016C194.312 182.536 194.12 182.979 193.734 183.344C193.349 183.708 192.789 183.984 192.055 184.172C191.32 184.354 190.438 184.448 189.406 184.453C188.37 184.448 187.484 184.354 186.75 184.172C186.021 183.984 185.461 183.708 185.07 183.344C184.68 182.979 184.484 182.536 184.484 182.016C184.484 181.505 184.68 181.07 185.07 180.711C185.461 180.352 186.023 180.081 186.758 179.898C187.492 179.716 188.375 179.625 189.406 179.625ZM189.406 180.547C188.641 180.547 187.984 180.607 187.438 180.727C186.896 180.846 186.479 181.016 186.188 181.234C185.901 181.453 185.76 181.714 185.766 182.016C185.76 182.333 185.901 182.607 186.188 182.836C186.479 183.06 186.896 183.229 187.438 183.344C187.984 183.458 188.641 183.516 189.406 183.516C190.172 183.516 190.828 183.458 191.375 183.344C191.927 183.229 192.346 183.06 192.633 182.836C192.919 182.612 193.062 182.339 193.062 182.016C193.062 181.714 192.919 181.453 192.633 181.234C192.346 181.016 191.927 180.846 191.375 180.727C190.823 180.607 190.167 180.547 189.406 180.547ZM195.734 186.391H183.078V185.391H195.734V186.391ZM194.109 190.703H185.859V192.391H184.641V189.797H192.906V188.531H184.609V187.594H194.109V190.703ZM194.531 193.109H184.641V192.141H194.531V193.109ZM207.844 193.297H206.641V188.188H207.844V193.297ZM213.578 188.812H200.922V187.781H213.578V188.812ZM207.719 182.125C207.719 182.896 207.461 183.602 206.945 184.242C206.43 184.883 205.747 185.417 204.898 185.844C204.055 186.266 203.146 186.552 202.172 186.703L201.719 185.719C202.552 185.604 203.346 185.37 204.102 185.016C204.857 184.661 205.469 184.232 205.938 183.727C206.406 183.221 206.641 182.688 206.641 182.125V181.75H207.719V182.125ZM207.859 182.125C207.859 182.682 208.091 183.216 208.555 183.727C209.018 184.232 209.628 184.661 210.383 185.016C211.138 185.37 211.932 185.604 212.766 185.719L212.312 186.703C211.339 186.557 210.43 186.268 209.586 185.836C208.747 185.404 208.073 184.867 207.562 184.227C207.052 183.581 206.797 182.88 206.797 182.125V181.75H207.859V182.125ZM212.359 182.109H202.156V181.109H212.359V182.109ZM207.844 181.453H206.641V179.375H207.844V181.453ZM225.5 193.266H224.281V179.375H225.5V193.266ZM227.75 186.062H225.188V185.031H227.75V186.062ZM221.906 180.875C221.901 182.224 221.677 183.5 221.234 184.703C220.797 185.901 220.104 187.008 219.156 188.023C218.208 189.034 217 189.901 215.531 190.625L214.844 189.656C216.13 189.016 217.208 188.263 218.078 187.398C218.953 186.529 219.607 185.565 220.039 184.508C220.477 183.451 220.698 182.307 220.703 181.078V180.875H221.906ZM221.328 181.906H215.484V180.875H221.328V181.906ZM235.516 182.781H228.547V181.781H235.516V182.781ZM232.031 183.719C232.609 183.719 233.125 183.854 233.578 184.125C234.036 184.396 234.393 184.771 234.648 185.25C234.909 185.724 235.042 186.266 235.047 186.875C235.042 187.49 234.909 188.036 234.648 188.516C234.393 188.995 234.036 189.372 233.578 189.648C233.125 189.924 232.609 190.062 232.031 190.062C231.464 190.062 230.951 189.924 230.492 189.648C230.039 189.372 229.685 188.995 229.43 188.516C229.174 188.036 229.047 187.49 229.047 186.875C229.047 186.271 229.177 185.729 229.438 185.25C229.698 184.771 230.052 184.396 230.5 184.125C230.953 183.854 231.464 183.719 232.031 183.719ZM232.031 184.75C231.667 184.755 231.341 184.852 231.055 185.039C230.768 185.221 230.544 185.474 230.383 185.797C230.221 186.115 230.141 186.474 230.141 186.875C230.141 187.281 230.221 187.643 230.383 187.961C230.544 188.279 230.768 188.529 231.055 188.711C231.341 188.893 231.667 188.984 232.031 188.984C232.396 188.984 232.724 188.893 233.016 188.711C233.307 188.529 233.536 188.279 233.703 187.961C233.87 187.643 233.953 187.281 233.953 186.875C233.953 186.474 233.87 186.115 233.703 185.797C233.536 185.474 233.307 185.221 233.016 185.039C232.724 184.852 232.396 184.755 232.031 184.75ZM240.406 193.266H239.234V179.375H240.406V193.266ZM239.625 186.25H236.969V185.234H239.625V186.25ZM237.391 192.578H236.234V179.719H237.391V192.578ZM232.656 182.391H231.438V179.797H232.656V182.391ZM253.141 181.344C253.141 182.141 252.883 182.872 252.367 183.539C251.852 184.201 251.174 184.755 250.336 185.203C249.497 185.646 248.604 185.948 247.656 186.109L247.172 185.141C247.99 185.021 248.773 184.776 249.523 184.406C250.279 184.031 250.891 183.576 251.359 183.039C251.828 182.503 252.062 181.938 252.062 181.344V180.75H253.141V181.344ZM253.438 181.344C253.438 181.938 253.672 182.503 254.141 183.039C254.609 183.576 255.219 184.031 255.969 184.406C256.724 184.776 257.51 185.021 258.328 185.141L257.875 186.109C256.917 185.948 256.018 185.646 255.18 185.203C254.341 184.755 253.664 184.201 253.148 183.539C252.633 182.872 252.375 182.141 252.375 181.344V180.75H253.438V181.344ZM253.328 193.266H252.125V187.953H253.328V193.266ZM259.078 188.312H246.422V187.297H259.078V188.312ZM257.875 181.25H247.609V180.25H257.875V181.25ZM268.5 185.406H265.766V184.359H268.5V185.406ZM264.156 183.375C264.156 184.328 264.023 185.258 263.758 186.164C263.492 187.065 263.109 187.875 262.609 188.594C262.115 189.307 261.536 189.865 260.875 190.266L260.094 189.344C260.719 188.979 261.266 188.479 261.734 187.844C262.203 187.208 262.562 186.505 262.812 185.734C263.062 184.958 263.188 184.172 263.188 183.375V180.688H264.156V183.375ZM264.375 183.328C264.375 184.073 264.492 184.815 264.727 185.555C264.961 186.289 265.297 186.961 265.734 187.57C266.177 188.18 266.698 188.661 267.297 189.016L266.594 189.969C265.938 189.573 265.37 189.023 264.891 188.32C264.411 187.617 264.047 186.833 263.797 185.969C263.552 185.104 263.432 184.224 263.438 183.328V180.688H264.375V183.328ZM272.156 193.266H270.969V179.375H272.156V193.266ZM269.281 192.562H268.125V179.672H269.281V192.562ZM278.438 190.703H277.234V186.547H278.438V190.703ZM283.641 190.703H282.406V186.547H283.641V190.703ZM286.797 191.484H274.078V190.453H286.797V191.484ZM280.406 180.25C281.391 180.255 282.266 180.406 283.031 180.703C283.802 180.995 284.404 181.414 284.836 181.961C285.268 182.503 285.484 183.125 285.484 183.828C285.484 184.536 285.268 185.159 284.836 185.695C284.404 186.232 283.802 186.648 283.031 186.945C282.266 187.242 281.391 187.391 280.406 187.391C279.422 187.391 278.544 187.242 277.773 186.945C277.008 186.648 276.409 186.232 275.977 185.695C275.544 185.159 275.328 184.536 275.328 183.828C275.328 183.125 275.544 182.503 275.977 181.961C276.409 181.414 277.008 180.995 277.773 180.703C278.544 180.406 279.422 180.255 280.406 180.25ZM280.406 181.266C279.651 181.26 278.977 181.365 278.383 181.578C277.794 181.786 277.336 182.086 277.008 182.477C276.68 182.867 276.516 183.318 276.516 183.828C276.516 184.339 276.68 184.789 277.008 185.18C277.336 185.57 277.794 185.875 278.383 186.094C278.977 186.312 279.651 186.422 280.406 186.422C281.156 186.422 281.826 186.312 282.414 186.094C283.003 185.875 283.464 185.57 283.797 185.18C284.13 184.789 284.297 184.339 284.297 183.828C284.297 183.318 284.13 182.867 283.797 182.477C283.464 182.086 283.003 181.786 282.414 181.578C281.826 181.365 281.156 181.26 280.406 181.266ZM54.0312 213.547H52.8125V203.391H54.0312V213.547ZM54.4688 216.969H45.0625V215.938H54.4688V216.969ZM46.2812 216.281H45.0625V212.516H46.2812V216.281ZM46.5312 204.359C47.2188 204.359 47.8385 204.505 48.3906 204.797C48.9427 205.089 49.3776 205.492 49.6953 206.008C50.013 206.523 50.1719 207.109 50.1719 207.766C50.1719 208.427 50.013 209.018 49.6953 209.539C49.3776 210.055 48.9427 210.458 48.3906 210.75C47.8385 211.042 47.2188 211.188 46.5312 211.188C45.8438 211.188 45.224 211.042 44.6719 210.75C44.1198 210.458 43.6849 210.055 43.3672 209.539C43.0495 209.018 42.8906 208.427 42.8906 207.766C42.8906 207.109 43.0495 206.523 43.3672 206.008C43.6849 205.492 44.1198 205.089 44.6719 204.797C45.224 204.505 45.8438 204.359 46.5312 204.359ZM46.5312 205.438C46.0677 205.438 45.6484 205.536 45.2734 205.734C44.9036 205.932 44.612 206.208 44.3984 206.562C44.1901 206.917 44.0885 207.318 44.0938 207.766C44.0885 208.219 44.1901 208.625 44.3984 208.984C44.612 209.339 44.9036 209.615 45.2734 209.812C45.6484 210.01 46.0677 210.109 46.5312 210.109C46.9896 210.109 47.4036 210.01 47.7734 209.812C48.1432 209.615 48.4349 209.339 48.6484 208.984C48.862 208.625 48.9688 208.219 48.9688 207.766C48.9688 207.318 48.862 206.917 48.6484 206.562C48.4349 206.208 48.1432 205.932 47.7734 205.734C47.4036 205.536 46.9896 205.438 46.5312 205.438ZM61.625 213.453H60.3906V210.359H61.625V213.453ZM67.8438 213.938H66.6094V203.391H67.8438V213.938ZM68.1875 216.969H58.3125V215.938H68.1875V216.969ZM59.5469 216.234H58.3125V212.906H59.5469V216.234ZM56.3125 209.828C58.1719 209.818 59.8177 209.789 61.25 209.742C62.6823 209.69 64.0521 209.583 65.3594 209.422L65.4375 210.312C64.0885 210.526 62.6745 210.667 61.1953 210.734C59.7161 210.802 58.1458 210.833 56.4844 210.828L56.3125 209.828ZM66.9375 212.5H63.7344V211.609H66.9375V212.5ZM60.875 203.953C61.5469 203.953 62.1432 204.052 62.6641 204.25C63.1901 204.448 63.5964 204.732 63.8828 205.102C64.1693 205.471 64.3125 205.896 64.3125 206.375C64.3125 206.865 64.1693 207.289 63.8828 207.648C63.5964 208.008 63.1927 208.286 62.6719 208.484C62.151 208.682 61.5521 208.781 60.875 208.781C60.1927 208.781 59.5911 208.682 59.0703 208.484C58.5547 208.286 58.1536 208.008 57.8672 207.648C57.5807 207.289 57.4375 206.865 57.4375 206.375C57.4375 205.896 57.5807 205.471 57.8672 205.102C58.1536 204.732 58.5573 204.448 59.0781 204.25C59.599 204.052 60.1979 203.953 60.875 203.953ZM60.875 204.891C60.4271 204.885 60.0312 204.945 59.6875 205.07C59.3438 205.19 59.0755 205.365 58.8828 205.594C58.6953 205.823 58.6042 206.083 58.6094 206.375C58.6042 206.672 58.6953 206.935 58.8828 207.164C59.0755 207.388 59.3438 207.562 59.6875 207.688C60.0312 207.812 60.4271 207.875 60.875 207.875C61.3125 207.875 61.7031 207.812 62.0469 207.688C62.3906 207.562 62.6589 207.388 62.8516 207.164C63.0443 206.935 63.1406 206.672 63.1406 206.375C63.1406 206.083 63.0443 205.823 62.8516 205.594C62.6589 205.365 62.3906 205.19 62.0469 205.07C61.7031 204.945 61.3125 204.885 60.875 204.891ZM84.9688 206.969H80.9219V205.938H84.9688V206.969ZM85.0156 209.938H80.9219V208.922H85.0156V209.938ZM85.75 213.672H84.5156V203.391H85.75V213.672ZM86.0625 216.969H76.7656V215.938H86.0625V216.969ZM78 216.438H76.7656V212.656H78V216.438ZM76.1562 206.781H80.0312V204.312H81.2344V211.297H74.9375V204.312H76.1562V206.781ZM80.0312 210.281V207.75H76.1562V210.281H80.0312ZM100.734 211.234H88.0625V210.25H100.734V211.234ZM94.9844 210.672H93.7969V208.016H94.9844V210.672ZM99.25 208.625H89.6719V207.625H99.25V208.625ZM99.1562 205.016H90.875V208.234H89.6719V204.031H99.1562V205.016ZM94.3906 212.25C95.3802 212.25 96.2318 212.349 96.9453 212.547C97.6589 212.745 98.2057 213.031 98.5859 213.406C98.9714 213.776 99.1667 214.224 99.1719 214.75C99.1667 215.281 98.974 215.732 98.5938 216.102C98.2188 216.471 97.6719 216.755 96.9531 216.953C96.2344 217.156 95.3802 217.26 94.3906 217.266C93.3906 217.26 92.5312 217.156 91.8125 216.953C91.0938 216.755 90.5443 216.469 90.1641 216.094C89.7839 215.724 89.5938 215.276 89.5938 214.75C89.5938 214.224 89.7839 213.776 90.1641 213.406C90.5443 213.031 91.0938 212.745 91.8125 212.547C92.5312 212.349 93.3906 212.25 94.3906 212.25ZM94.3906 213.219C93.651 213.219 93.0156 213.279 92.4844 213.398C91.9531 213.518 91.5443 213.695 91.2578 213.93C90.9766 214.159 90.8385 214.432 90.8438 214.75C90.8385 215.073 90.9766 215.349 91.2578 215.578C91.5443 215.807 91.9531 215.982 92.4844 216.102C93.0156 216.221 93.651 216.281 94.3906 216.281C95.1198 216.281 95.75 216.221 96.2812 216.102C96.8125 215.982 97.2214 215.807 97.5078 215.578C97.7943 215.349 97.9375 215.073 97.9375 214.75C97.9375 214.432 97.7943 214.159 97.5078 213.93C97.2214 213.695 96.8125 213.518 96.2812 213.398C95.75 213.279 95.1198 213.219 94.3906 213.219ZM108.219 203.625C109.245 203.625 110.125 203.716 110.859 203.898C111.599 204.081 112.161 204.352 112.547 204.711C112.932 205.07 113.125 205.505 113.125 206.016C113.125 206.536 112.932 206.979 112.547 207.344C112.161 207.708 111.602 207.984 110.867 208.172C110.133 208.354 109.25 208.448 108.219 208.453C107.182 208.448 106.297 208.354 105.562 208.172C104.833 207.984 104.273 207.708 103.883 207.344C103.492 206.979 103.297 206.536 103.297 206.016C103.297 205.505 103.492 205.07 103.883 204.711C104.273 204.352 104.836 204.081 105.57 203.898C106.305 203.716 107.188 203.625 108.219 203.625ZM108.219 204.547C107.453 204.547 106.797 204.607 106.25 204.727C105.708 204.846 105.292 205.016 105 205.234C104.713 205.453 104.573 205.714 104.578 206.016C104.573 206.333 104.713 206.607 105 206.836C105.292 207.06 105.708 207.229 106.25 207.344C106.797 207.458 107.453 207.516 108.219 207.516C108.984 207.516 109.641 207.458 110.188 207.344C110.74 207.229 111.159 207.06 111.445 206.836C111.732 206.612 111.875 206.339 111.875 206.016C111.875 205.714 111.732 205.453 111.445 205.234C111.159 205.016 110.74 204.846 110.188 204.727C109.635 204.607 108.979 204.547 108.219 204.547ZM114.547 210.391H101.891V209.391H114.547V210.391ZM112.922 214.703H104.672V216.391H103.453V213.797H111.719V212.531H103.422V211.594H112.922V214.703ZM113.344 217.109H103.453V216.141H113.344V217.109ZM131.219 217.266H129.984V203.375H131.219V217.266ZM127.109 204.891C127.104 206.266 126.875 207.552 126.422 208.75C125.974 209.948 125.266 211.052 124.297 212.062C123.328 213.068 122.089 213.932 120.578 214.656L119.906 213.656C121.245 213.021 122.357 212.271 123.242 211.406C124.133 210.542 124.794 209.583 125.227 208.531C125.664 207.474 125.885 206.323 125.891 205.078V204.891H127.109ZM126.391 205.891H120.547V204.891H126.391V205.891ZM140.188 205.109C140.188 205.865 139.94 206.552 139.445 207.172C138.951 207.786 138.292 208.297 137.469 208.703C136.651 209.104 135.76 209.375 134.797 209.516L134.344 208.547C135.167 208.432 135.943 208.208 136.672 207.875C137.401 207.542 137.987 207.135 138.43 206.656C138.872 206.177 139.094 205.661 139.094 205.109V204.688H140.188V205.109ZM140.688 205.109C140.688 205.661 140.911 206.177 141.359 206.656C141.807 207.135 142.396 207.542 143.125 207.875C143.859 208.208 144.641 208.432 145.469 208.547L144.984 209.516C144.026 209.375 143.135 209.104 142.312 208.703C141.49 208.297 140.831 207.786 140.336 207.172C139.841 206.552 139.594 205.865 139.594 205.109V204.688H140.688V205.109ZM145.094 205.078H134.719V204.078H145.094V205.078ZM146.266 211.547H133.547V210.531H146.266V211.547ZM140.609 214.391H139.391V211.156H140.609V214.391ZM144.844 216.969H135.172V215.938H144.844V216.969ZM136.406 216.328H135.172V213H136.406V216.328ZM153.719 204.281C154.682 204.281 155.549 204.44 156.32 204.758C157.096 205.076 157.703 205.523 158.141 206.102C158.578 206.68 158.797 207.344 158.797 208.094C158.797 208.849 158.578 209.518 158.141 210.102C157.703 210.68 157.096 211.128 156.32 211.445C155.549 211.758 154.682 211.911 153.719 211.906C152.755 211.911 151.888 211.758 151.117 211.445C150.352 211.128 149.747 210.68 149.305 210.102C148.862 209.518 148.641 208.849 148.641 208.094C148.641 207.344 148.862 206.68 149.305 206.102C149.747 205.523 150.352 205.076 151.117 204.758C151.888 204.44 152.755 204.281 153.719 204.281ZM153.719 205.281C152.979 205.281 152.312 205.398 151.719 205.633C151.125 205.867 150.656 206.201 150.312 206.633C149.974 207.06 149.807 207.547 149.812 208.094C149.807 208.646 149.974 209.135 150.312 209.562C150.656 209.99 151.122 210.32 151.711 210.555C152.305 210.789 152.974 210.906 153.719 210.906C154.458 210.906 155.125 210.789 155.719 210.555C156.312 210.32 156.776 209.99 157.109 209.562C157.443 209.135 157.609 208.646 157.609 208.094C157.609 207.547 157.44 207.06 157.102 206.633C156.763 206.201 156.297 205.867 155.703 205.633C155.115 205.398 154.453 205.281 153.719 205.281ZM160.109 215.422H147.391V214.391H160.109V215.422ZM173.938 215.547H161.219V214.516H173.938V215.547ZM168.141 214.969H166.938V211.531H168.141V214.969ZM172.328 208.609H164.031V211.422H162.812V207.609H171.125V205.422H162.781V204.406H172.328V208.609ZM172.656 211.891H162.812V210.875H172.656V211.891ZM189.719 206.344H185.734V205.359H189.719V206.344ZM189.75 208.953H185.734V207.984H189.75V208.953ZM186.172 210.125H179.719V204.234H186.172V210.125ZM180.938 209.156H184.969V205.219H180.938V209.156ZM190.562 211.375H189.344V203.375H190.562V211.375ZM186.562 213.266C186.562 213.911 186.318 214.51 185.828 215.062C185.339 215.615 184.688 216.078 183.875 216.453C183.068 216.828 182.198 217.078 181.266 217.203L180.844 216.266C181.635 216.177 182.393 215.984 183.117 215.688C183.841 215.385 184.424 215.021 184.867 214.594C185.31 214.161 185.531 213.719 185.531 213.266V212.984H186.562V213.266ZM186.781 213.266C186.776 213.703 186.99 214.135 187.422 214.562C187.859 214.99 188.432 215.357 189.141 215.664C189.854 215.966 190.604 216.167 191.391 216.266L190.969 217.203C190.036 217.073 189.169 216.815 188.367 216.43C187.57 216.049 186.93 215.583 186.445 215.031C185.961 214.479 185.719 213.891 185.719 213.266V212.984H186.781V213.266ZM190.891 213.266H181.406V212.297H190.891V213.266ZM186.781 212.844H185.531V210.953H186.781V212.844ZM201.328 207.906C201.323 208.859 201.154 209.781 200.82 210.672C200.492 211.557 200.036 212.341 199.453 213.023C198.87 213.706 198.214 214.224 197.484 214.578L196.781 213.625C197.453 213.312 198.06 212.857 198.602 212.258C199.148 211.659 199.576 210.982 199.883 210.227C200.19 209.466 200.344 208.693 200.344 207.906V206.656H201.328V207.906ZM201.531 207.906C201.531 208.641 201.682 209.367 201.984 210.086C202.286 210.799 202.698 211.448 203.219 212.031C203.745 212.609 204.339 213.057 205 213.375L204.281 214.328C203.562 213.974 202.924 213.466 202.367 212.805C201.81 212.143 201.372 211.388 201.055 210.539C200.737 209.685 200.578 208.807 200.578 207.906V206.656H201.531V207.906ZM204.688 206.797H197.156V205.797H204.688V206.797ZM201.562 206.359H200.328V203.641H201.562V206.359ZM207.656 217.266H206.438V203.375H207.656V217.266ZM209.984 210.125H207.375V209.078H209.984V210.125ZM222.203 213.547H220.984V203.391H222.203V213.547ZM222.641 216.969H213.234V215.938H222.641V216.969ZM214.453 216.281H213.234V212.516H214.453V216.281ZM214.703 204.359C215.391 204.359 216.01 204.505 216.562 204.797C217.115 205.089 217.549 205.492 217.867 206.008C218.185 206.523 218.344 207.109 218.344 207.766C218.344 208.427 218.185 209.018 217.867 209.539C217.549 210.055 217.115 210.458 216.562 210.75C216.01 211.042 215.391 211.188 214.703 211.188C214.016 211.188 213.396 211.042 212.844 210.75C212.292 210.458 211.857 210.055 211.539 209.539C211.221 209.018 211.062 208.427 211.062 207.766C211.062 207.109 211.221 206.523 211.539 206.008C211.857 205.492 212.292 205.089 212.844 204.797C213.396 204.505 214.016 204.359 214.703 204.359ZM214.703 205.438C214.24 205.438 213.82 205.536 213.445 205.734C213.076 205.932 212.784 206.208 212.57 206.562C212.362 206.917 212.26 207.318 212.266 207.766C212.26 208.219 212.362 208.625 212.57 208.984C212.784 209.339 213.076 209.615 213.445 209.812C213.82 210.01 214.24 210.109 214.703 210.109C215.161 210.109 215.576 210.01 215.945 209.812C216.315 209.615 216.607 209.339 216.82 208.984C217.034 208.625 217.141 208.219 217.141 207.766C217.141 207.318 217.034 206.917 216.82 206.562C216.607 206.208 216.315 205.932 215.945 205.734C215.576 205.536 215.161 205.438 214.703 205.438ZM229.312 207.641C229.312 208.599 229.13 209.544 228.766 210.477C228.401 211.409 227.911 212.237 227.297 212.961C226.688 213.685 226.021 214.229 225.297 214.594L224.562 213.625C225.224 213.307 225.839 212.828 226.406 212.188C226.979 211.542 227.438 210.818 227.781 210.016C228.125 209.214 228.297 208.422 228.297 207.641V205.344H229.312V207.641ZM229.531 207.641C229.531 208.406 229.703 209.169 230.047 209.93C230.391 210.685 230.849 211.359 231.422 211.953C231.995 212.547 232.62 212.99 233.297 213.281L232.609 214.25C231.854 213.906 231.167 213.396 230.547 212.719C229.932 212.042 229.443 211.263 229.078 210.383C228.719 209.497 228.542 208.583 228.547 207.641V205.344H229.531V207.641ZM232.844 205.828H225.016V204.812H232.844V205.828ZM236.016 217.266H234.781V203.375H236.016V217.266ZM255.406 209.953H252.844V208.922H255.406V209.953ZM253.156 217.266H251.938V203.375H253.156V217.266ZM244.203 213.344H242.984V204.75H244.203V213.344ZM244.094 212.703C245.193 212.708 246.273 212.661 247.336 212.562C248.398 212.464 249.484 212.297 250.594 212.062L250.75 213.109C249.62 213.339 248.513 213.5 247.43 213.594C246.346 213.688 245.234 213.734 244.094 213.734H242.984V212.703H244.094ZM261.453 216.844H260.219V211.219H261.453V216.844ZM267.734 217.281H266.516V203.391H267.734V217.281ZM256.484 210.828C258.167 210.823 259.755 210.794 261.25 210.742C262.745 210.685 264.156 210.583 265.484 210.438L265.547 211.359C264.177 211.557 262.755 211.69 261.281 211.758C259.807 211.826 258.214 211.865 256.5 211.875H256.328L256.172 210.828H256.484ZM264.312 208.859H257.547V207.828H264.312V208.859ZM258.766 208.125H257.547V204.328H258.766V208.125ZM273.797 204.453C274.469 204.453 275.068 204.651 275.594 205.047C276.125 205.443 276.536 206.008 276.828 206.742C277.12 207.477 277.266 208.328 277.266 209.297C277.266 210.271 277.12 211.122 276.828 211.852C276.536 212.576 276.125 213.135 275.594 213.531C275.068 213.927 274.469 214.125 273.797 214.125C273.115 214.125 272.508 213.927 271.977 213.531C271.451 213.135 271.042 212.576 270.75 211.852C270.458 211.122 270.312 210.271 270.312 209.297C270.312 208.328 270.458 207.477 270.75 206.742C271.042 206.008 271.451 205.443 271.977 205.047C272.508 204.651 273.115 204.453 273.797 204.453ZM273.797 205.547C273.344 205.547 272.943 205.703 272.594 206.016C272.25 206.328 271.979 206.768 271.781 207.336C271.583 207.898 271.484 208.552 271.484 209.297C271.484 210.042 271.583 210.698 271.781 211.266C271.979 211.828 272.25 212.263 272.594 212.57C272.943 212.878 273.344 213.031 273.797 213.031C274.245 213.031 274.646 212.878 275 212.57C275.354 212.263 275.628 211.826 275.82 211.258C276.013 210.69 276.109 210.036 276.109 209.297C276.109 208.557 276.013 207.904 275.82 207.336C275.628 206.768 275.354 206.328 275 206.016C274.646 205.703 274.245 205.547 273.797 205.547ZM281.578 217.297H280.359V203.375H281.578V217.297ZM280.906 209.703H276.859V208.688H280.906V209.703ZM295.406 217.266H294.172V203.375H295.406V217.266ZM288.469 207.5C288.464 208.469 288.286 209.424 287.938 210.367C287.594 211.31 287.125 212.151 286.531 212.891C285.943 213.625 285.302 214.188 284.609 214.578L283.797 213.641C284.453 213.312 285.062 212.82 285.625 212.164C286.188 211.503 286.635 210.763 286.969 209.945C287.302 209.122 287.469 208.307 287.469 207.5V205.344H288.469V207.5ZM288.703 207.5C288.703 208.214 288.87 208.958 289.203 209.734C289.536 210.505 289.979 211.211 290.531 211.852C291.089 212.487 291.693 212.969 292.344 213.297L291.609 214.234C290.906 213.87 290.258 213.328 289.664 212.609C289.076 211.891 288.604 211.081 288.25 210.18C287.896 209.279 287.719 208.385 287.719 207.5V205.344H288.703V207.5ZM291.875 205.828H284.297V204.812H291.875V205.828ZM294.969 208.328H291.328V207.297H294.969V208.328ZM294.969 211.281H291.328V210.25H294.969V211.281ZM302.078 214.703H300.875V210.547H302.078V214.703ZM307.281 214.703H306.047V210.547H307.281V214.703ZM310.438 215.484H297.719V214.453H310.438V215.484ZM304.047 204.25C305.031 204.255 305.906 204.406 306.672 204.703C307.443 204.995 308.044 205.414 308.477 205.961C308.909 206.503 309.125 207.125 309.125 207.828C309.125 208.536 308.909 209.159 308.477 209.695C308.044 210.232 307.443 210.648 306.672 210.945C305.906 211.242 305.031 211.391 304.047 211.391C303.062 211.391 302.185 211.242 301.414 210.945C300.648 210.648 300.049 210.232 299.617 209.695C299.185 209.159 298.969 208.536 298.969 207.828C298.969 207.125 299.185 206.503 299.617 205.961C300.049 205.414 300.648 204.995 301.414 204.703C302.185 204.406 303.062 204.255 304.047 204.25ZM304.047 205.266C303.292 205.26 302.617 205.365 302.023 205.578C301.435 205.786 300.977 206.086 300.648 206.477C300.32 206.867 300.156 207.318 300.156 207.828C300.156 208.339 300.32 208.789 300.648 209.18C300.977 209.57 301.435 209.875 302.023 210.094C302.617 210.312 303.292 210.422 304.047 210.422C304.797 210.422 305.466 210.312 306.055 210.094C306.643 209.875 307.104 209.57 307.438 209.18C307.771 208.789 307.938 208.339 307.938 207.828C307.938 207.318 307.771 206.867 307.438 206.477C307.104 206.086 306.643 205.786 306.055 205.578C305.466 205.365 304.797 205.26 304.047 205.266Z" fill="#929195"/> -<path d="M380 230H50C45.5817 230 42 233.582 42 238V246C42 250.418 45.5817 254 50 254H380C384.418 254 388 250.418 388 246V238C388 233.582 384.418 230 380 230Z" fill="white"/> -<path d="M50.6602 243.188H47.9883V242.426H50.6602V243.188ZM51.0585 247.184H50.1327V239.543H51.0585V247.184ZM51.3516 249.727H44.3672V248.953H51.3516V249.727ZM45.2929 249.328H44.3672V246.492H45.2929V249.328ZM45.8789 241.688C45.8789 242.309 45.7559 242.896 45.5098 243.451C45.2637 244.002 44.918 244.486 44.4727 244.904C44.0312 245.318 43.5234 245.633 42.9492 245.848L42.4688 245.098C42.9765 244.918 43.4316 244.654 43.834 244.307C44.2363 243.959 44.5508 243.559 44.7773 243.105C45.0039 242.648 45.1172 242.176 45.1172 241.688V240.832H45.8789V241.688ZM46.0429 241.688C46.0429 242.133 46.1522 242.566 46.371 242.988C46.5897 243.41 46.8926 243.785 47.2793 244.113C47.666 244.441 48.1094 244.691 48.6094 244.863L48.1289 245.602C47.5703 245.398 47.0762 245.1 46.6465 244.705C46.2207 244.311 45.8887 243.854 45.6504 243.334C45.4121 242.814 45.2929 242.266 45.2929 241.688V240.832H46.0429V241.688ZM48.375 241.148H42.7617V240.387H48.375V241.148ZM59.0858 244.43H57.082V243.645H59.0858V244.43ZM55.6875 242.742C55.6836 243.438 55.584 244.117 55.3887 244.781C55.1973 245.445 54.918 246.043 54.5508 246.574C54.1875 247.102 53.7578 247.516 53.2617 247.816L52.7108 247.113C53.1718 246.848 53.5723 246.482 53.9121 246.018C54.252 245.553 54.5117 245.035 54.6914 244.465C54.875 243.895 54.9688 243.32 54.9727 242.742V242.191H55.6875V242.742ZM55.8398 242.742C55.8438 243.305 55.9355 243.855 56.1152 244.395C56.2988 244.934 56.5625 245.424 56.9062 245.865C57.25 246.303 57.6523 246.645 58.1133 246.891L57.5858 247.582C57.0819 247.309 56.6444 246.92 56.2733 246.416C55.9061 245.912 55.6229 245.342 55.4237 244.705C55.2284 244.068 55.1328 243.414 55.1367 242.742V242.191H55.8398V242.742ZM57.7969 242.227H52.9922V241.465H57.7969V242.227ZM55.8516 242.039H54.9727V239.918H55.8516V242.039ZM61.6992 249.949H60.8203V239.531H61.6992V249.949ZM59.5898 249.41H58.7226V239.789H59.5898V249.41ZM69.7383 242.73C69.7383 243.449 69.6015 244.158 69.328 244.857C69.0546 245.557 68.6875 246.178 68.2266 246.721C67.7695 247.264 67.2695 247.672 66.7266 247.945L66.1758 247.219C66.6719 246.98 67.1328 246.621 67.5586 246.141C67.9883 245.656 68.332 245.113 68.5898 244.512C68.8477 243.91 68.9766 243.316 68.9766 242.73V241.008H69.7383V242.73ZM69.9023 242.73C69.9023 243.305 70.0312 243.877 70.2891 244.447C70.5469 245.014 70.8906 245.52 71.3203 245.965C71.75 246.41 72.2188 246.742 72.7266 246.961L72.2108 247.688C71.6444 247.43 71.1289 247.047 70.6641 246.539C70.2031 246.031 69.8359 245.447 69.5625 244.787C69.293 244.123 69.1602 243.438 69.1641 242.73V241.008H69.9023V242.73ZM72.3867 241.371H66.5155V240.609H72.3867V241.371ZM74.7655 249.949H73.8398V239.531H74.7655V249.949ZM81.7383 246.293H80.8358V244.711H81.7383V246.293ZM86.0391 244.887H76.5586V244.172H86.0391V244.887ZM81.7383 240.738H80.8358V239.473H81.7383V240.738ZM81.5976 240.984C81.5976 241.512 81.4061 241.969 81.0233 242.355C80.6405 242.738 80.1269 243.041 79.4823 243.264C78.8417 243.482 78.125 243.625 77.332 243.691L77.0625 242.988C77.75 242.945 78.377 242.838 78.9434 242.666C79.5098 242.49 79.959 242.26 80.291 241.975C80.623 241.686 80.7891 241.355 80.7891 240.984V240.832H81.5976V240.984ZM81.7969 240.984C81.793 241.355 81.957 241.686 82.2891 241.975C82.625 242.26 83.0742 242.49 83.6367 242.666C84.2031 242.838 84.8319 242.945 85.5233 242.988L85.2421 243.691C84.453 243.625 83.7382 243.482 83.0976 243.264C82.4569 243.041 81.9453 242.738 81.5625 242.355C81.1797 241.969 80.9883 241.512 80.9883 240.984V240.832H81.7969V240.984ZM85.078 241.172H77.5312V240.445H85.078V241.172ZM84.8203 248.109H78.6328V249.387H77.7188V247.453H83.9179V246.551H77.6953V245.859H84.8203V248.109ZM85.1367 249.832H77.7188V249.129H85.1367V249.832ZM97.9102 240.855H91.1367V240.094H97.9102V240.855ZM99.4688 244.688H89.9297V243.926H99.4688V244.688ZM98.2147 240.867C98.2147 241.473 98.1952 242.023 98.1561 242.52C98.1171 243.012 98.0234 243.578 97.875 244.219L96.9608 244.16C97.0663 243.73 97.1425 243.326 97.1894 242.947C97.2401 242.568 97.2715 242.236 97.2832 241.951C97.2949 241.662 97.3007 241.324 97.3007 240.938V240.867V240.094H98.2147V240.867ZM98.2617 249.809H91.1016V246.129H98.2617V249.809ZM92.0156 249.059H97.3477V246.855H92.0156V249.059ZM102.797 240.188C103.25 240.188 103.658 240.291 104.021 240.498C104.385 240.705 104.67 240.996 104.877 241.371C105.084 241.746 105.187 242.172 105.187 242.648C105.187 243.125 105.084 243.547 104.877 243.914C104.67 244.281 104.385 244.568 104.021 244.775C103.662 244.982 103.254 245.086 102.797 245.086C102.336 245.086 101.926 244.982 101.566 244.775C101.207 244.568 100.926 244.281 100.723 243.914C100.519 243.547 100.418 243.125 100.418 242.648C100.418 242.172 100.519 241.746 100.723 241.371C100.926 240.996 101.207 240.705 101.566 240.498C101.926 240.291 102.336 240.188 102.797 240.188ZM102.797 240.984C102.5 240.984 102.234 241.055 102 241.195C101.766 241.336 101.58 241.535 101.443 241.793C101.31 242.047 101.246 242.332 101.25 242.648C101.246 242.965 101.31 243.25 101.443 243.504C101.58 243.754 101.766 243.951 102 244.096C102.234 244.24 102.5 244.312 102.797 244.312C103.09 244.312 103.353 244.24 103.588 244.096C103.826 243.951 104.012 243.754 104.144 243.504C104.277 243.25 104.344 242.965 104.344 242.648C104.344 242.332 104.277 242.047 104.144 241.793C104.012 241.535 103.826 241.336 103.588 241.195C103.353 241.055 103.09 240.984 102.797 240.984ZM109.148 245.742H108.269V239.543H109.148V245.742ZM108.551 242.988H106.547V242.227H108.551V242.988ZM106.887 245.672H106.019V239.742H106.887V245.672ZM109.148 249.949H108.246V247.066H102.129V246.328H109.148V249.949Z" fill="#B2B1B6"/> -<path d="M316.062 248H314.641V238.156H314.578L311.828 239.984V238.562L314.641 236.688H316.062V248ZM322.781 248.156C321.948 248.156 321.237 247.93 320.648 247.477C320.06 247.023 319.609 246.362 319.297 245.492C318.984 244.622 318.828 243.573 318.828 242.344C318.828 241.13 318.984 240.089 319.297 239.219C319.609 238.344 320.06 237.677 320.648 237.219C321.242 236.76 321.953 236.531 322.781 236.531C323.604 236.531 324.312 236.76 324.906 237.219C325.5 237.677 325.953 238.344 326.266 239.219C326.578 240.089 326.734 241.13 326.734 242.344C326.734 243.573 326.581 244.622 326.273 245.492C325.966 246.362 325.516 247.023 324.922 247.477C324.328 247.93 323.615 248.156 322.781 248.156ZM322.781 246.906C323.323 246.906 323.789 246.729 324.18 246.375C324.57 246.021 324.865 245.503 325.062 244.82C325.26 244.138 325.359 243.312 325.359 242.344C325.359 241.375 325.258 240.547 325.055 239.859C324.852 239.172 324.557 238.648 324.172 238.289C323.786 237.93 323.323 237.75 322.781 237.75C322.24 237.75 321.776 237.93 321.391 238.289C321.005 238.648 320.708 239.172 320.5 239.859C320.292 240.547 320.188 241.375 320.188 242.344C320.188 243.312 320.292 244.138 320.5 244.82C320.708 245.503 321.003 246.021 321.383 246.375C321.768 246.729 322.234 246.906 322.781 246.906ZM328.328 244.531L333.422 236.688H334.266V238.469H333.672L329.844 244.359V244.453H336.734V245.688H328.328V244.531ZM333.812 245.344V244.797V236.688H335.156V248H333.812V245.344ZM338.641 251.203H337.484L338.344 246.953H339.859L338.641 251.203ZM345.5 248.156C344.667 248.156 343.956 247.93 343.367 247.477C342.779 247.023 342.328 246.362 342.016 245.492C341.703 244.622 341.547 243.573 341.547 242.344C341.547 241.13 341.703 240.089 342.016 239.219C342.328 238.344 342.779 237.677 343.367 237.219C343.961 236.76 344.672 236.531 345.5 236.531C346.323 236.531 347.031 236.76 347.625 237.219C348.219 237.677 348.672 238.344 348.984 239.219C349.297 240.089 349.453 241.13 349.453 242.344C349.453 243.573 349.299 244.622 348.992 245.492C348.685 246.362 348.234 247.023 347.641 247.477C347.047 247.93 346.333 248.156 345.5 248.156ZM345.5 246.906C346.042 246.906 346.508 246.729 346.898 246.375C347.289 246.021 347.583 245.503 347.781 244.82C347.979 244.138 348.078 243.312 348.078 242.344C348.078 241.375 347.977 240.547 347.773 239.859C347.57 239.172 347.276 238.648 346.891 238.289C346.505 237.93 346.042 237.75 345.5 237.75C344.958 237.75 344.495 237.93 344.109 238.289C343.724 238.648 343.427 239.172 343.219 239.859C343.01 240.547 342.906 241.375 342.906 242.344C342.906 243.312 343.01 244.138 343.219 244.82C343.427 245.503 343.721 246.021 344.102 246.375C344.487 246.729 344.953 246.906 345.5 246.906ZM355.031 248.156C354.198 248.156 353.487 247.93 352.898 247.477C352.31 247.023 351.859 246.362 351.547 245.492C351.234 244.622 351.078 243.573 351.078 242.344C351.078 241.13 351.234 240.089 351.547 239.219C351.859 238.344 352.31 237.677 352.898 237.219C353.492 236.76 354.203 236.531 355.031 236.531C355.854 236.531 356.562 236.76 357.156 237.219C357.75 237.677 358.203 238.344 358.516 239.219C358.828 240.089 358.984 241.13 358.984 242.344C358.984 243.573 358.831 244.622 358.523 245.492C358.216 246.362 357.766 247.023 357.172 247.477C356.578 247.93 355.865 248.156 355.031 248.156ZM355.031 246.906C355.573 246.906 356.039 246.729 356.43 246.375C356.82 246.021 357.115 245.503 357.312 244.82C357.51 244.138 357.609 243.312 357.609 242.344C357.609 241.375 357.508 240.547 357.305 239.859C357.102 239.172 356.807 238.648 356.422 238.289C356.036 237.93 355.573 237.75 355.031 237.75C354.49 237.75 354.026 237.93 353.641 238.289C353.255 238.648 352.958 239.172 352.75 239.859C352.542 240.547 352.438 241.375 352.438 242.344C352.438 243.312 352.542 244.138 352.75 244.82C352.958 245.503 353.253 246.021 353.633 246.375C354.018 246.729 354.484 246.906 355.031 246.906ZM364.562 248.156C363.729 248.156 363.018 247.93 362.43 247.477C361.841 247.023 361.391 246.362 361.078 245.492C360.766 244.622 360.609 243.573 360.609 242.344C360.609 241.13 360.766 240.089 361.078 239.219C361.391 238.344 361.841 237.677 362.43 237.219C363.023 236.76 363.734 236.531 364.562 236.531C365.385 236.531 366.094 236.76 366.688 237.219C367.281 237.677 367.734 238.344 368.047 239.219C368.359 240.089 368.516 241.13 368.516 242.344C368.516 243.573 368.362 244.622 368.055 245.492C367.747 246.362 367.297 247.023 366.703 247.477C366.109 247.93 365.396 248.156 364.562 248.156ZM364.562 246.906C365.104 246.906 365.57 246.729 365.961 246.375C366.352 246.021 366.646 245.503 366.844 244.82C367.042 244.138 367.141 243.312 367.141 242.344C367.141 241.375 367.039 240.547 366.836 239.859C366.633 239.172 366.339 238.648 365.953 238.289C365.568 237.93 365.104 237.75 364.562 237.75C364.021 237.75 363.557 237.93 363.172 238.289C362.786 238.648 362.49 239.172 362.281 239.859C362.073 240.547 361.969 241.375 361.969 242.344C361.969 243.312 362.073 244.138 362.281 244.82C362.49 245.503 362.784 246.021 363.164 246.375C363.549 246.729 364.016 246.906 364.562 246.906ZM379.141 245.453H377.906V242.359H379.141V245.453ZM385.359 245.938H384.125V235.391H385.359V245.938ZM385.703 248.969H375.828V247.938H385.703V248.969ZM377.062 248.234H375.828V244.906H377.062V248.234ZM373.828 241.828C375.688 241.818 377.333 241.789 378.766 241.742C380.198 241.69 381.568 241.583 382.875 241.422L382.953 242.312C381.604 242.526 380.19 242.667 378.711 242.734C377.232 242.802 375.661 242.833 374 242.828L373.828 241.828ZM384.453 244.5H381.25V243.609H384.453V244.5ZM378.391 235.953C379.062 235.953 379.659 236.052 380.18 236.25C380.706 236.448 381.112 236.732 381.398 237.102C381.685 237.471 381.828 237.896 381.828 238.375C381.828 238.865 381.685 239.289 381.398 239.648C381.112 240.008 380.708 240.286 380.188 240.484C379.667 240.682 379.068 240.781 378.391 240.781C377.708 240.781 377.107 240.682 376.586 240.484C376.07 240.286 375.669 240.008 375.383 239.648C375.096 239.289 374.953 238.865 374.953 238.375C374.953 237.896 375.096 237.471 375.383 237.102C375.669 236.732 376.073 236.448 376.594 236.25C377.115 236.052 377.714 235.953 378.391 235.953ZM378.391 236.891C377.943 236.885 377.547 236.945 377.203 237.07C376.859 237.19 376.591 237.365 376.398 237.594C376.211 237.823 376.12 238.083 376.125 238.375C376.12 238.672 376.211 238.935 376.398 239.164C376.591 239.388 376.859 239.562 377.203 239.688C377.547 239.812 377.943 239.875 378.391 239.875C378.828 239.875 379.219 239.812 379.562 239.688C379.906 239.562 380.174 239.388 380.367 239.164C380.56 238.935 380.656 238.672 380.656 238.375C380.656 238.083 380.56 237.823 380.367 237.594C380.174 237.365 379.906 237.19 379.562 237.07C379.219 236.945 378.828 236.885 378.391 236.891Z" fill="#56555A"/> -<path d="M24 270H399V300H24V270Z" fill="white"/> -<mask id="mask2_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="270" width="375" height="30"> -<path d="M24 270H399V300H24V270Z" fill="white"/> -</mask> -<g mask="url(#mask2_1835_8259)"> -<path d="M24 271H399V269H24V271Z" fill="#F1F0F5"/> -</g> -<path d="M48.7266 283.187H46.0547V282.426H48.7266V283.187ZM49.125 287.184H48.1992V279.543H49.125V287.184ZM49.418 289.727H42.4336V288.953H49.418V289.727ZM43.3594 289.328H42.4336V286.492H43.3594V289.328ZM43.9453 281.687C43.9453 282.309 43.8223 282.896 43.5762 283.451C43.3301 284.002 42.9844 284.486 42.5391 284.904C42.0977 285.318 41.5898 285.633 41.0156 285.848L40.5352 285.098C41.043 284.918 41.498 284.654 41.9004 284.307C42.3027 283.959 42.6172 283.559 42.8437 283.105C43.0703 282.648 43.1836 282.176 43.1836 281.687V280.832H43.9453V281.687ZM44.1094 281.687C44.1094 282.133 44.2187 282.566 44.4375 282.988C44.6562 283.41 44.959 283.785 45.3457 284.113C45.7324 284.441 46.1758 284.691 46.6758 284.863L46.1953 285.602C45.6367 285.398 45.1426 285.1 44.7129 284.705C44.2871 284.311 43.9551 283.854 43.7168 283.334C43.4785 282.814 43.3594 282.266 43.3594 281.687V280.832H44.1094V281.687ZM46.4414 281.148H40.8281V280.387H46.4414V281.148ZM57.1523 284.43H55.1484V283.645H57.1523V284.43ZM53.7539 282.742C53.75 283.437 53.6504 284.117 53.4551 284.781C53.2637 285.445 52.9844 286.043 52.6172 286.574C52.2539 287.102 51.8242 287.516 51.3281 287.816L50.7773 287.113C51.2383 286.848 51.6387 286.482 51.9785 286.018C52.3184 285.553 52.5781 285.035 52.7578 284.465C52.9414 283.895 53.0352 283.32 53.0391 282.742V282.191H53.7539V282.742ZM53.9062 282.742C53.9102 283.305 54.002 283.855 54.1816 284.395C54.3652 284.934 54.6289 285.424 54.9727 285.865C55.3164 286.303 55.7187 286.645 56.1797 286.891L55.6523 287.582C55.1484 287.309 54.7109 286.92 54.3398 286.416C53.9727 285.912 53.6895 285.342 53.4902 284.705C53.2949 284.068 53.1992 283.414 53.2031 282.742V282.191H53.9062V282.742ZM55.8633 282.227H51.0586V281.465H55.8633V282.227ZM53.918 282.039H53.0391V279.918H53.918V282.039ZM59.7656 289.949H58.8867V279.531H59.7656V289.949ZM57.6562 289.41H56.7891V279.789H57.6562V289.41ZM67.6406 281.699C67.6406 282.285 67.5176 282.832 67.2715 283.34C67.0254 283.848 66.6797 284.287 66.2344 284.658C65.7891 285.029 65.2773 285.309 64.6992 285.496L64.2422 284.77C64.7578 284.613 65.2168 284.381 65.6191 284.072C66.0215 283.764 66.334 283.406 66.5566 283C66.7793 282.59 66.8906 282.156 66.8906 281.699V281.254H67.6406V281.699ZM67.793 281.699C67.793 282.121 67.9023 282.521 68.1211 282.9C68.3398 283.279 68.6426 283.615 69.0293 283.908C69.4199 284.197 69.8711 284.418 70.3828 284.57L69.9492 285.297C69.3711 285.117 68.8633 284.85 68.4258 284.494C67.9883 284.139 67.6484 283.723 67.4062 283.246C67.1641 282.766 67.043 282.25 67.043 281.699V281.254H67.793V281.699ZM70.1484 281.512H64.5352V280.773H70.1484V281.512ZM67.8164 281.066H66.8906V279.484H67.8164V281.066ZM72.3867 285.707H71.4727V279.531H72.3867V285.707ZM73.957 282.953H72.1289V282.18H73.957V282.953ZM72.3867 289.809H65.8125V286.187H72.3867V289.809ZM66.7148 289.059H71.4727V286.914H66.7148V289.059ZM82.5586 282.637H79.3477V281.863H82.5586V282.637ZM82.5586 285.93H79.3477V285.168H82.5586V285.93ZM77.4141 280.34C77.918 280.34 78.3672 280.488 78.7617 280.785C79.1602 281.082 79.4687 281.506 79.6875 282.057C79.9062 282.607 80.0156 283.246 80.0156 283.973C80.0156 284.703 79.9062 285.342 79.6875 285.889C79.4687 286.432 79.1602 286.852 78.7617 287.148C78.3672 287.445 77.918 287.594 77.4141 287.594C76.9023 287.594 76.4473 287.445 76.0488 287.148C75.6543 286.852 75.3477 286.432 75.1289 285.889C74.9102 285.342 74.8008 284.703 74.8008 283.973C74.8008 283.246 74.9102 282.607 75.1289 282.057C75.3477 281.506 75.6543 281.082 76.0488 280.785C76.4473 280.488 76.9023 280.34 77.4141 280.34ZM77.4141 281.16C77.0742 281.16 76.7734 281.277 76.5117 281.512C76.2539 281.746 76.0508 282.076 75.9023 282.502C75.7539 282.924 75.6797 283.414 75.6797 283.973C75.6797 284.531 75.7539 285.023 75.9023 285.449C76.0508 285.871 76.2539 286.197 76.5117 286.428C76.7734 286.658 77.0742 286.773 77.4141 286.773C77.75 286.773 78.0508 286.658 78.3164 286.428C78.582 286.197 78.7871 285.869 78.9316 285.443C79.0762 285.018 79.1484 284.527 79.1484 283.973C79.1484 283.418 79.0762 282.928 78.9316 282.502C78.7871 282.076 78.582 281.746 78.3164 281.512C78.0508 281.277 77.75 281.16 77.4141 281.16ZM83.25 289.973H82.3359V279.531H83.25V289.973ZM88.3359 282.73C88.3359 283.437 88.2031 284.141 87.9375 284.84C87.6719 285.535 87.3105 286.158 86.8535 286.709C86.3965 287.26 85.9023 287.672 85.3711 287.945L84.8086 287.219C85.3047 286.977 85.7656 286.613 86.1914 286.129C86.6211 285.645 86.9629 285.102 87.2168 284.5C87.4746 283.898 87.6055 283.309 87.6094 282.73V281.008H88.3359V282.73ZM88.5117 282.73C88.5078 283.277 88.625 283.832 88.8633 284.395C89.1055 284.957 89.4336 285.467 89.8477 285.924C90.2617 286.377 90.7187 286.723 91.2187 286.961L90.6914 287.687C90.1484 287.422 89.6543 287.029 89.209 286.51C88.7676 285.99 88.418 285.4 88.1602 284.74C87.9023 284.076 87.7734 283.406 87.7734 282.73V281.008H88.5117V282.73ZM90.8555 281.371H85.1836V280.609H90.8555V281.371ZM93.0469 289.949H92.1328V279.531H93.0469V289.949ZM94.793 284.535H92.8359V283.75H94.793V284.535Z" fill="#B2B1B6"/> -<path d="M349.656 286.398L353.477 280.516H354.109V281.852H353.664L350.793 286.27V286.34H355.961V287.266H349.656V286.398ZM353.77 287.008V286.598V280.516H354.777V289H353.77V287.008ZM365.055 281.992H361.984V281.23H365.055V281.992ZM365.066 284.066H361.984V283.293H365.066V284.066ZM365.617 285.707H364.691V279.531H365.617V285.707ZM362.254 284.957H357.473V280.328H362.254V284.957ZM358.387 284.207H361.352V281.078H358.387V284.207ZM362.16 286.012C362.879 286.012 363.5 286.088 364.023 286.24C364.547 286.393 364.949 286.617 365.23 286.914C365.512 287.211 365.652 287.566 365.652 287.98C365.652 288.391 365.512 288.74 365.23 289.029C364.949 289.322 364.547 289.545 364.023 289.697C363.5 289.85 362.879 289.926 362.16 289.926C361.437 289.926 360.814 289.85 360.291 289.697C359.771 289.545 359.371 289.322 359.09 289.029C358.809 288.74 358.668 288.391 358.668 287.98C358.668 287.566 358.809 287.211 359.09 286.914C359.371 286.617 359.771 286.393 360.291 286.24C360.814 286.088 361.437 286.012 362.16 286.012ZM362.16 286.727C361.629 286.73 361.17 286.783 360.783 286.885C360.396 286.982 360.1 287.125 359.893 287.312C359.686 287.5 359.582 287.723 359.582 287.98C359.582 288.23 359.686 288.447 359.893 288.631C360.1 288.814 360.396 288.955 360.783 289.053C361.17 289.15 361.629 289.199 362.16 289.199C362.687 289.199 363.145 289.15 363.531 289.053C363.922 288.955 364.221 288.814 364.428 288.631C364.635 288.447 364.738 288.23 364.738 287.98C364.738 287.723 364.635 287.5 364.428 287.312C364.221 287.125 363.924 286.982 363.537 286.885C363.15 286.783 362.691 286.73 362.16 286.727Z" fill="#B2B1B6"/> -<mask id="mask3_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="375" y="279" width="8" height="12"> -<path d="M383 283C383 280.791 381.209 279 379 279C376.791 279 375 280.791 375 283V287C375 289.209 376.791 291 379 291C381.209 291 383 289.209 383 287V283Z" fill="white"/> -</mask> -<g mask="url(#mask3_1835_8259)"> -<path d="M377 281L381 285L377 289" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -</g> -<path d="M390 316H40C35.5817 316 32 319.582 32 324V348C32 352.418 35.5817 356 40 356H390C394.418 356 398 352.418 398 348V324C398 319.582 394.418 316 390 316Z" fill="white"/> -<path d="M52.4062 339.633H50.4219V329.234H52.4062V339.633ZM50.7031 334.977H47.875V333.352H50.7031V334.977ZM48.0078 330.273C48.0026 331.539 47.7422 332.693 47.2266 333.734C46.7109 334.771 45.9609 335.669 44.9766 336.43C43.9922 337.185 42.8073 337.779 41.4219 338.211L40.6016 336.617C41.6953 336.273 42.638 335.831 43.4297 335.289C44.2266 334.742 44.8333 334.12 45.25 333.422C45.6719 332.724 45.8854 331.974 45.8906 331.172V330.273H48.0078ZM47.1641 331.906H41.3437V330.273H47.1641V331.906ZM52.7734 343.195H43.0234V341.586H52.7734V343.195ZM45.0469 342.508H43.0234V338.57H45.0469V342.508ZM59.0547 331.258C59.0547 332.227 58.9089 333.125 58.6172 333.953C58.3307 334.781 57.8932 335.503 57.3047 336.117C56.7161 336.727 55.987 337.18 55.1172 337.477L54.0469 335.914C54.8073 335.654 55.4401 335.286 55.9453 334.812C56.4505 334.333 56.8229 333.792 57.0625 333.187C57.3021 332.583 57.4245 331.94 57.4297 331.258V329.969H59.0547V331.258ZM59.4297 331.453C59.4297 332.052 59.5469 332.617 59.7812 333.148C60.0208 333.68 60.3828 334.154 60.8672 334.57C61.3568 334.982 61.9635 335.302 62.6875 335.531L61.625 337.078C60.7917 336.802 60.0911 336.388 59.5234 335.836C58.9557 335.279 58.5286 334.628 58.2422 333.883C57.9557 333.138 57.8151 332.328 57.8203 331.453V329.969H59.4297V331.453ZM65.5312 337.648H63.5391V329.203H65.5312V337.648ZM67.4531 334.203H64.9687V332.539H67.4531V334.203ZM60.8672 337.937C61.8464 337.937 62.6953 338.047 63.4141 338.266C64.138 338.479 64.6927 338.794 65.0781 339.211C65.4687 339.622 65.6641 340.112 65.6641 340.68C65.6641 341.258 65.4687 341.753 65.0781 342.164C64.6927 342.576 64.138 342.891 63.4141 343.109C62.6953 343.328 61.8464 343.437 60.8672 343.437C59.8724 343.437 59.0078 343.328 58.2734 343.109C57.5443 342.891 56.9818 342.576 56.5859 342.164C56.1901 341.753 55.9922 341.258 55.9922 340.68C55.9922 340.112 56.1901 339.622 56.5859 339.211C56.9818 338.794 57.5443 338.479 58.2734 338.266C59.0078 338.047 59.8724 337.937 60.8672 337.937ZM60.8672 339.5C60.2474 339.495 59.724 339.539 59.2969 339.633C58.8698 339.721 58.5443 339.854 58.3203 340.031C58.1016 340.208 57.9948 340.424 58 340.68C57.9948 340.945 58.1016 341.167 58.3203 341.344C58.5391 341.521 58.8594 341.654 59.2812 341.742C59.7083 341.831 60.237 341.875 60.8672 341.875C61.487 341.875 62.0078 341.831 62.4297 341.742C62.8516 341.654 63.1693 341.521 63.3828 341.344C63.5964 341.167 63.7031 340.945 63.7031 340.68C63.7031 340.424 63.5937 340.208 63.375 340.031C63.1615 339.849 62.8437 339.714 62.4219 339.625C62 339.536 61.4818 339.495 60.8672 339.5ZM69.7266 345.297H68.0703L68.8437 340.852H71.0781L69.7266 345.297ZM82.9297 331.227C82.9297 332.07 82.7031 332.841 82.25 333.539C81.8021 334.232 81.1484 334.815 80.2891 335.289C79.4297 335.758 78.4115 336.073 77.2344 336.234L76.4922 334.68C77.487 334.56 78.3385 334.323 79.0469 333.969C79.7604 333.609 80.2969 333.193 80.6562 332.719C81.0156 332.24 81.1953 331.742 81.1953 331.227V330.797H82.9297V331.227ZM83.5 331.227C83.5 331.742 83.6771 332.24 84.0312 332.719C84.3906 333.193 84.9245 333.609 85.6328 333.969C86.3464 334.323 87.2083 334.56 88.2187 334.68L87.5 336.234C86.3125 336.073 85.2865 335.758 84.4219 335.289C83.5573 334.815 82.8984 334.232 82.4453 333.539C81.9922 332.841 81.7656 332.07 81.7656 331.227V330.797H83.5V331.227ZM83.2969 343.445H81.3203V338.203H83.2969V343.445ZM88.8359 338.656H75.8672V337.07H88.8359V338.656ZM87.6641 331.523H77.0312V329.969H87.6641V331.523ZM101.062 340.32H99.0547V329.203H101.062V340.32ZM102.883 335.531H100.352V333.891H102.883V335.531ZM101.547 343.195H91.5234V341.586H101.547V343.195ZM93.5391 342.062H91.5234V339.586H93.5391V342.062ZM94.9687 338.125H92.9844V336.039H94.9687V338.125ZM89.5391 337.391C91.1849 337.391 92.7474 337.359 94.2266 337.297C95.7057 337.229 97.0964 337.102 98.3984 336.914L98.5469 338.281C97.2969 338.521 96.0078 338.682 94.6797 338.766C93.3516 338.849 91.8385 338.904 90.1406 338.93C90.0625 338.93 89.9948 338.93 89.9375 338.93C89.8802 338.93 89.8125 338.93 89.7344 338.93L89.5391 337.391ZM98.0391 331.805H89.8984V330.367H98.0391V331.805ZM93.9687 332.195C94.6615 332.195 95.2708 332.284 95.7969 332.461C96.3229 332.633 96.7292 332.888 97.0156 333.227C97.3021 333.56 97.4479 333.958 97.4531 334.422C97.4479 334.859 97.3021 335.242 97.0156 335.57C96.7292 335.893 96.3229 336.146 95.7969 336.328C95.2708 336.505 94.6615 336.594 93.9687 336.594C93.2708 336.594 92.6589 336.505 92.1328 336.328C91.6068 336.151 91.1979 335.901 90.9062 335.578C90.6198 335.25 90.4766 334.865 90.4766 334.422C90.4766 333.958 90.6198 333.56 90.9062 333.227C91.1979 332.888 91.6042 332.633 92.125 332.461C92.651 332.284 93.2656 332.195 93.9687 332.195ZM93.9687 333.531C93.625 333.531 93.3359 333.562 93.1016 333.625C92.8672 333.687 92.6875 333.786 92.5625 333.922C92.4427 334.057 92.3828 334.224 92.3828 334.422C92.3828 334.594 92.4427 334.745 92.5625 334.875C92.6875 335 92.8672 335.096 93.1016 335.164C93.3411 335.227 93.6302 335.258 93.9687 335.258C94.2969 335.258 94.5781 335.227 94.8125 335.164C95.0521 335.096 95.2318 335 95.3516 334.875C95.4766 334.745 95.5391 334.594 95.5391 334.422C95.5391 334.224 95.4792 334.057 95.3594 333.922C95.2396 333.786 95.0599 333.687 94.8203 333.625C94.5859 333.562 94.3021 333.531 93.9687 333.531ZM94.9687 331.008H92.9844V329.164H94.9687V331.008ZM105.164 345.297H103.508L104.281 340.852H106.516L105.164 345.297ZM123.687 332.609H111.852V331.016H123.687V332.609ZM124.305 341.992H111.305V340.383H124.305V341.992ZM118.75 341.008H116.773V338.469H118.75V341.008ZM117.766 333.227C118.745 333.227 119.599 333.336 120.328 333.555C121.062 333.773 121.625 334.094 122.016 334.516C122.411 334.932 122.609 335.424 122.609 335.992C122.609 336.57 122.411 337.07 122.016 337.492C121.625 337.909 121.065 338.232 120.336 338.461C119.607 338.685 118.75 338.799 117.766 338.805C116.766 338.799 115.901 338.685 115.172 338.461C114.443 338.232 113.88 337.909 113.484 337.492C113.094 337.07 112.901 336.57 112.906 335.992C112.901 335.419 113.094 334.924 113.484 334.508C113.88 334.091 114.443 333.773 115.172 333.555C115.906 333.336 116.771 333.227 117.766 333.227ZM117.766 334.781C117.141 334.786 116.62 334.833 116.203 334.922C115.792 335.005 115.479 335.138 115.266 335.32C115.052 335.497 114.948 335.721 114.953 335.992C114.948 336.263 115.052 336.49 115.266 336.672C115.479 336.849 115.792 336.984 116.203 337.078C116.62 337.167 117.141 337.211 117.766 337.211C118.375 337.211 118.885 337.167 119.297 337.078C119.713 336.984 120.029 336.849 120.242 336.672C120.456 336.49 120.562 336.263 120.562 335.992C120.562 335.721 120.456 335.497 120.242 335.32C120.029 335.138 119.713 335.005 119.297 334.922C118.885 334.833 118.375 334.786 117.766 334.781ZM118.75 332.008H116.773V329.359H118.75V332.008ZM137.109 339.633H135.125V329.234H137.109V339.633ZM135.406 334.977H132.578V333.352H135.406V334.977ZM132.711 330.273C132.706 331.539 132.445 332.693 131.93 333.734C131.414 334.771 130.664 335.669 129.68 336.43C128.695 337.185 127.51 337.779 126.125 338.211L125.305 336.617C126.398 336.273 127.341 335.831 128.133 335.289C128.93 334.742 129.536 334.12 129.953 333.422C130.375 332.724 130.589 331.974 130.594 331.172V330.273H132.711ZM131.867 331.906H126.047V330.273H131.867V331.906ZM137.477 343.195H127.727V341.586H137.477V343.195ZM129.75 342.508H127.727V338.57H129.75V342.508ZM140.602 345.297H138.945L139.719 340.852H141.953L140.602 345.297ZM153.805 331.227C153.805 332.07 153.578 332.841 153.125 333.539C152.677 334.232 152.023 334.815 151.164 335.289C150.305 335.758 149.286 336.073 148.109 336.234L147.367 334.68C148.362 334.56 149.214 334.323 149.922 333.969C150.635 333.609 151.172 333.193 151.531 332.719C151.891 332.24 152.07 331.742 152.07 331.227V330.797H153.805V331.227ZM154.375 331.227C154.375 331.742 154.552 332.24 154.906 332.719C155.266 333.193 155.799 333.609 156.508 333.969C157.221 334.323 158.083 334.56 159.094 334.68L158.375 336.234C157.187 336.073 156.161 335.758 155.297 335.289C154.432 334.815 153.773 334.232 153.32 333.539C152.867 332.841 152.641 332.07 152.641 331.227V330.797H154.375V331.227ZM154.172 343.445H152.195V338.203H154.172V343.445ZM159.711 338.656H146.742V337.07H159.711V338.656ZM158.539 331.523H147.906V329.969H158.539V331.523ZM171.781 343.437H169.812V329.203H171.781V343.437ZM173.891 336.422H171.344V334.789H173.891V336.422ZM168.844 332.937H160.492V331.336H168.844V332.937ZM164.703 333.727C165.385 333.727 166.003 333.872 166.555 334.164C167.112 334.451 167.547 334.852 167.859 335.367C168.177 335.883 168.339 336.466 168.344 337.117C168.339 337.773 168.177 338.359 167.859 338.875C167.547 339.385 167.112 339.786 166.555 340.078C166.003 340.365 165.385 340.508 164.703 340.508C164.01 340.508 163.388 340.365 162.836 340.078C162.284 339.786 161.852 339.385 161.539 338.875C161.227 338.359 161.07 337.773 161.07 337.117C161.07 336.466 161.227 335.883 161.539 335.367C161.852 334.852 162.284 334.451 162.836 334.164C163.388 333.872 164.01 333.727 164.703 333.727ZM164.703 335.352C164.37 335.357 164.073 335.43 163.812 335.57C163.552 335.711 163.346 335.917 163.195 336.187C163.049 336.453 162.977 336.763 162.977 337.117C162.977 337.482 163.049 337.797 163.195 338.062C163.346 338.323 163.552 338.523 163.812 338.664C164.073 338.805 164.37 338.878 164.703 338.883C165.036 338.878 165.333 338.805 165.594 338.664C165.859 338.523 166.062 338.323 166.203 338.062C166.349 337.797 166.422 337.482 166.422 337.117C166.422 336.763 166.349 336.453 166.203 336.187C166.062 335.917 165.859 335.711 165.594 335.57C165.333 335.43 165.036 335.357 164.703 335.352ZM165.695 331.945H163.711V329.43H165.695V331.945ZM191.094 336.336H178.102V334.773H191.094V336.336ZM189.539 333.984H179.711V332.414H189.539V333.984ZM189.437 331.086H181.703V333.75H179.711V329.508H189.437V331.086ZM189.484 340.883H181.562V342.164H179.602V339.469H187.516V338.672H179.594V337.172H189.484V340.883ZM189.859 343.32H179.602V341.773H189.859V343.32ZM195.844 330.211C196.552 330.211 197.185 330.419 197.742 330.836C198.305 331.247 198.742 331.839 199.055 332.609C199.367 333.375 199.523 334.266 199.523 335.281C199.523 336.302 199.367 337.198 199.055 337.969C198.742 338.734 198.305 339.323 197.742 339.734C197.185 340.146 196.552 340.352 195.844 340.352C195.125 340.352 194.487 340.146 193.93 339.734C193.372 339.323 192.935 338.734 192.617 337.969C192.299 337.198 192.141 336.302 192.141 335.281C192.141 334.266 192.299 333.375 192.617 332.609C192.935 331.839 193.372 331.247 193.93 330.836C194.487 330.419 195.125 330.211 195.844 330.211ZM195.844 332.016C195.484 332.01 195.172 332.135 194.906 332.391C194.641 332.646 194.432 333.018 194.281 333.508C194.13 333.997 194.057 334.589 194.062 335.281C194.057 335.974 194.13 336.565 194.281 337.055C194.432 337.544 194.641 337.917 194.906 338.172C195.172 338.422 195.484 338.547 195.844 338.547C196.203 338.547 196.518 338.422 196.789 338.172C197.06 337.917 197.268 337.544 197.414 337.055C197.56 336.565 197.633 335.974 197.633 335.281C197.633 334.589 197.56 333.997 197.414 333.508C197.268 333.013 197.06 332.641 196.789 332.391C196.518 332.135 196.203 332.01 195.844 332.016ZM203.922 343.477H201.945V329.203H203.922V343.477ZM202.797 335.953H198.93V334.352H202.797V335.953ZM213.187 336.516H211.227V334.398H213.187V336.516ZM212.234 329.422C213.281 329.422 214.193 329.534 214.969 329.758C215.75 329.977 216.349 330.294 216.766 330.711C217.187 331.128 217.398 331.617 217.398 332.18C217.398 332.742 217.187 333.232 216.766 333.648C216.349 334.065 215.753 334.385 214.977 334.609C214.201 334.828 213.286 334.935 212.234 334.93C211.187 334.935 210.273 334.828 209.492 334.609C208.711 334.385 208.107 334.065 207.68 333.648C207.258 333.232 207.047 332.742 207.047 332.18C207.047 331.617 207.26 331.128 207.687 330.711C208.115 330.294 208.716 329.977 209.492 329.758C210.273 329.534 211.187 329.422 212.234 329.422ZM212.234 330.953C211.573 330.953 211.008 331 210.539 331.094C210.076 331.182 209.721 331.32 209.477 331.508C209.237 331.69 209.117 331.914 209.117 332.18C209.117 332.456 209.237 332.687 209.477 332.875C209.721 333.057 210.073 333.195 210.531 333.289C210.995 333.378 211.562 333.422 212.234 333.422C212.896 333.422 213.458 333.378 213.922 333.289C214.391 333.195 214.745 333.057 214.984 332.875C215.224 332.687 215.344 332.456 215.344 332.18C215.344 331.914 215.221 331.69 214.977 331.508C214.732 331.32 214.378 331.182 213.914 331.094C213.451 331 212.891 330.953 212.234 330.953ZM217.172 343.281H207.258V338.43H217.172V343.281ZM209.219 341.68H215.219V340.008H209.219V341.68ZM218.727 337.492H205.758V335.914H218.727V337.492Z" fill="#56555A"/> -<path d="M386 364H44C37.3726 364 32 369.373 32 376V556C32 562.627 37.3726 568 44 568H386C392.627 568 398 562.627 398 556V376C398 369.373 392.627 364 386 364Z" fill="white"/> -<path d="M52.3184 385H50.5488V378.191H50.502L48.5625 379.422V377.852L50.6602 376.516H52.3184V385ZM57.4922 378.76C57.4883 379.525 57.375 380.262 57.1523 380.969C56.9297 381.676 56.5977 382.307 56.1562 382.861C55.7187 383.412 55.1875 383.824 54.5625 384.098L53.7422 382.937C54.2969 382.695 54.7676 382.35 55.1543 381.9C55.5449 381.447 55.8359 380.949 56.0273 380.406C56.2187 379.863 56.3145 379.314 56.3145 378.76V378.15H57.4922V378.76ZM57.7969 378.76C57.793 379.283 57.8828 379.803 58.0664 380.318C58.2539 380.83 58.5332 381.305 58.9043 381.742C59.2754 382.176 59.7324 382.521 60.2754 382.779L59.4492 383.916C58.8437 383.643 58.3301 383.238 57.9082 382.703C57.4863 382.164 57.168 381.555 56.9531 380.875C56.7383 380.191 56.6328 379.486 56.6367 378.76V378.15H57.7969V378.76ZM59.9766 378.344H54.1055V377.154H59.9766V378.344ZM57.8086 377.775H56.3086V375.648H57.8086V377.775ZM62.3555 386.078H60.8555V375.402H62.3555V386.078ZM63.9375 380.805H62.0273V379.551H63.9375V380.805Z" fill="#56555A"/> -<path d="M364.586 382.398L368.406 376.516H369.039V377.852H368.594L365.723 382.27V382.34H370.891V383.266H364.586V382.398ZM368.699 383.008V382.598V376.516H369.707V385H368.699V383.008ZM379.984 377.992H376.914V377.23H379.984V377.992ZM379.996 380.066H376.914V379.293H379.996V380.066ZM380.547 381.707H379.621V375.531H380.547V381.707ZM377.184 380.957H372.402V376.328H377.184V380.957ZM373.316 380.207H376.281V377.078H373.316V380.207ZM377.09 382.012C377.809 382.012 378.43 382.088 378.953 382.24C379.477 382.393 379.879 382.617 380.16 382.914C380.441 383.211 380.582 383.566 380.582 383.98C380.582 384.391 380.441 384.74 380.16 385.029C379.879 385.322 379.477 385.545 378.953 385.697C378.43 385.85 377.809 385.926 377.09 385.926C376.367 385.926 375.744 385.85 375.221 385.697C374.701 385.545 374.301 385.322 374.02 385.029C373.738 384.74 373.598 384.391 373.598 383.98C373.598 383.566 373.738 383.211 374.02 382.914C374.301 382.617 374.701 382.393 375.221 382.24C375.744 382.088 376.367 382.012 377.09 382.012ZM377.09 382.727C376.559 382.73 376.1 382.783 375.713 382.885C375.326 382.982 375.029 383.125 374.822 383.312C374.615 383.5 374.512 383.723 374.512 383.98C374.512 384.23 374.615 384.447 374.822 384.631C375.029 384.814 375.326 384.955 375.713 385.053C376.1 385.15 376.559 385.199 377.09 385.199C377.617 385.199 378.074 385.15 378.461 385.053C378.852 384.955 379.15 384.814 379.357 384.631C379.564 384.447 379.668 384.23 379.668 383.98C379.668 383.723 379.564 383.5 379.357 383.312C379.15 383.125 378.854 382.982 378.467 382.885C378.08 382.783 377.621 382.73 377.09 382.727Z" fill="#B2B1B6"/> -<path d="M364 386.916H381.859V387.73H364V386.916Z" fill="#B2B1B6"/> -<path d="M382 398H48C43.5817 398 40 401.582 40 406V430C40 434.418 43.5817 438 48 438H382C386.418 438 390 434.418 390 430V406C390 401.582 386.418 398 382 398Z" fill="#F9F8FD"/> -<path d="M51.3203 412.82H52.6406V411.625H54.4844V417.078H49.4375V411.625H51.3203V412.82ZM52.6406 415.477V414.328H51.3203V415.477H52.6406ZM57.2109 412.82H58.4766V411.625H60.375V417.078H55.3125V411.625H57.2109V412.82ZM58.4766 415.477V414.328H57.2109V415.477H58.4766ZM61.3984 419.719H48.4297V418.125H61.3984V419.719ZM55.8906 418.703H53.8828V416.641H55.8906V418.703ZM54.8906 420.414C55.9167 420.414 56.7995 420.513 57.5391 420.711C58.2839 420.909 58.8542 421.195 59.25 421.57C59.6458 421.945 59.8464 422.396 59.8516 422.922C59.8464 423.458 59.6458 423.914 59.25 424.289C58.8594 424.669 58.2917 424.956 57.5469 425.148C56.8021 425.346 55.9167 425.443 54.8906 425.437C53.849 425.437 52.9557 425.341 52.2109 425.148C51.4714 424.956 50.9036 424.672 50.5078 424.297C50.1172 423.922 49.9219 423.464 49.9219 422.922C49.9219 422.396 50.1172 421.945 50.5078 421.57C50.9036 421.195 51.4714 420.909 52.2109 420.711C52.9557 420.513 53.849 420.414 54.8906 420.414ZM54.8906 421.898C54.2187 421.898 53.6615 421.937 53.2187 422.016C52.7812 422.089 52.4531 422.203 52.2344 422.359C52.0208 422.51 51.9167 422.698 51.9219 422.922C51.9167 423.151 52.0234 423.341 52.2422 423.492C52.4661 423.643 52.7943 423.758 53.2266 423.836C53.6641 423.914 54.2187 423.953 54.8906 423.953C55.5417 423.953 56.0833 423.914 56.5156 423.836C56.9531 423.758 57.2812 423.643 57.5 423.492C57.7187 423.341 57.8281 423.151 57.8281 422.922C57.8281 422.698 57.7187 422.51 57.5 422.359C57.2812 422.203 56.9557 422.089 56.5234 422.016C56.0911 421.937 55.5469 421.898 54.8906 421.898ZM66.3594 413.992C66.3542 414.831 66.237 415.615 66.0078 416.344C65.7839 417.073 65.4297 417.719 64.9453 418.281C64.4661 418.844 63.8594 419.271 63.125 419.562L62.0547 418.039C62.6797 417.784 63.1979 417.445 63.6094 417.023C64.0208 416.602 64.3203 416.135 64.5078 415.625C64.7005 415.109 64.7969 414.565 64.7969 413.992V413.07H66.3594V413.992ZM66.7031 413.992C66.7031 414.539 66.7917 415.049 66.9687 415.523C67.1458 415.992 67.4219 416.414 67.7969 416.789C68.1771 417.159 68.6615 417.458 69.25 417.687L68.2109 419.211C67.513 418.935 66.9401 418.542 66.4922 418.031C66.0495 417.516 65.7214 416.917 65.5078 416.234C65.2995 415.552 65.1979 414.805 65.2031 413.992V413.07H66.7031V413.992ZM68.8828 413.859H62.5234V412.273H68.8828V413.859ZM74.4687 419.844H72.5703V411.234H74.4687V419.844ZM73.0937 416.289H70.8125V414.68H73.0937V416.289ZM71.4453 419.406H69.5547V411.477H71.4453V419.406ZM69.6094 420.055C70.6094 420.055 71.4792 420.164 72.2187 420.383C72.9635 420.596 73.5365 420.906 73.9375 421.312C74.3385 421.714 74.5391 422.19 74.5391 422.742C74.5391 423.294 74.3385 423.773 73.9375 424.18C73.5365 424.586 72.9635 424.896 72.2187 425.109C71.474 425.328 70.6042 425.437 69.6094 425.437C68.6094 425.437 67.7396 425.328 67 425.109C66.2604 424.896 65.6901 424.586 65.2891 424.18C64.888 423.773 64.6875 423.294 64.6875 422.742C64.6875 422.19 64.888 421.714 65.2891 421.312C65.6901 420.906 66.2604 420.596 67 420.383C67.7396 420.164 68.6094 420.055 69.6094 420.055ZM69.6094 421.57C68.9896 421.57 68.4609 421.615 68.0234 421.703C67.5911 421.786 67.2578 421.919 67.0234 422.102C66.7943 422.279 66.6823 422.492 66.6875 422.742C66.6823 423.003 66.7943 423.221 67.0234 423.398C67.2526 423.57 67.5833 423.701 68.0156 423.789C68.4479 423.872 68.9792 423.917 69.6094 423.922C70.2396 423.917 70.7708 423.872 71.2031 423.789C71.6354 423.701 71.9635 423.57 72.1875 423.398C72.4167 423.221 72.5339 423.003 72.5391 422.742C72.5339 422.492 72.4167 422.279 72.1875 422.102C71.9635 421.919 71.6302 421.786 71.1875 421.703C70.75 421.615 70.224 421.57 69.6094 421.57ZM87.9844 425.477H85.9609V411.203H87.9844V425.477ZM80.2578 412.211C80.9714 412.211 81.612 412.419 82.1797 412.836C82.7526 413.247 83.1979 413.839 83.5156 414.609C83.8385 415.375 84 416.266 84 417.281C84 418.302 83.8385 419.198 83.5156 419.969C83.1979 420.734 82.7526 421.323 82.1797 421.734C81.612 422.146 80.9714 422.352 80.2578 422.352C79.5339 422.357 78.8854 422.154 78.3125 421.742C77.7448 421.326 77.2995 420.734 76.9766 419.969C76.6536 419.198 76.4922 418.302 76.4922 417.281C76.4922 416.266 76.6536 415.375 76.9766 414.609C77.2995 413.839 77.7448 413.247 78.3125 412.836C78.8854 412.419 79.5339 412.211 80.2578 412.211ZM80.2578 414.016C79.888 414.01 79.5625 414.135 79.2812 414.391C79.0052 414.641 78.7917 415.013 78.6406 415.508C78.4948 415.997 78.4245 416.589 78.4297 417.281C78.4245 417.974 78.4948 418.565 78.6406 419.055C78.7917 419.544 79.0052 419.917 79.2812 420.172C79.5625 420.422 79.888 420.547 80.2578 420.547C80.6172 420.547 80.9349 420.422 81.2109 420.172C81.487 419.917 81.7005 419.544 81.8516 419.055C82.0026 418.565 82.0781 417.974 82.0781 417.281C82.0781 416.589 82.0026 415.997 81.8516 415.508C81.7005 415.018 81.487 414.646 81.2109 414.391C80.9349 414.135 80.6172 414.01 80.2578 414.016ZM100.484 412.898C100.479 413.628 100.26 414.292 99.8281 414.891C99.401 415.49 98.7656 415.99 97.9219 416.391C97.0781 416.792 96.0651 417.052 94.8828 417.172L94.1875 415.609C95.1667 415.516 95.9974 415.328 96.6797 415.047C97.3672 414.766 97.8776 414.437 98.2109 414.062C98.5495 413.687 98.7214 413.299 98.7266 412.898V412.492H100.484V412.898ZM101.453 412.898C101.453 413.305 101.622 413.695 101.961 414.07C102.305 414.445 102.82 414.773 103.508 415.055C104.195 415.331 105.036 415.516 106.031 415.609L105.312 417.172C104.13 417.052 103.115 416.794 102.266 416.398C101.422 415.997 100.779 415.497 100.336 414.898C99.8932 414.294 99.6693 413.628 99.6641 412.898V412.492H101.453V412.898ZM105.414 413.312H94.7891V411.734H105.414V413.312ZM106.586 419.734H93.6172V418.148H106.586V419.734ZM101.062 418.852H99.0859V416.273H101.062V418.852ZM105 425.437H103.016V422.344H95.0469V420.758H105V425.437ZM109.836 413.547H112.75V411.852H114.75V418.062H107.859V411.852H109.836V413.547ZM112.75 416.492V415.039H109.836V416.492H112.75ZM118.719 418.453H116.727V411.203H118.719V418.453ZM120.641 415.602H117.891V413.984H120.641V415.602ZM118.719 422.852H111.273V424.555H109.312V421.422H116.734V420.531H109.289V418.992H118.719V422.852ZM119.133 425.336H109.312V423.773H119.133V425.336Z" fill="#56555A"/> -<path d="M320.406 424.156C319.677 424.146 319.005 423.974 318.391 423.641C317.776 423.307 317.271 422.742 316.875 421.945C316.479 421.148 316.281 420.094 316.281 418.781C316.281 417.458 316.456 416.328 316.805 415.391C317.154 414.453 317.648 413.742 318.289 413.258C318.93 412.773 319.693 412.531 320.578 412.531C321.229 412.531 321.815 412.656 322.336 412.906C322.862 413.156 323.289 413.51 323.617 413.969C323.945 414.422 324.156 414.943 324.25 415.531H322.859C322.771 415.187 322.625 414.883 322.422 414.617C322.224 414.352 321.969 414.146 321.656 414C321.344 413.854 320.984 413.781 320.578 413.781C319.958 413.781 319.424 413.951 318.977 414.289C318.534 414.628 318.195 415.122 317.961 415.773C317.727 416.419 317.609 417.193 317.609 418.094H317.75C317.969 417.776 318.227 417.505 318.523 417.281C318.82 417.052 319.148 416.88 319.508 416.766C319.872 416.651 320.255 416.594 320.656 416.594C321.323 416.594 321.937 416.755 322.5 417.078C323.062 417.401 323.51 417.849 323.844 418.422C324.177 418.99 324.344 419.63 324.344 420.344C324.344 421.057 324.18 421.706 323.852 422.289C323.523 422.867 323.06 423.326 322.461 423.664C321.867 423.997 321.182 424.161 320.406 424.156ZM320.406 422.922C320.885 422.922 321.32 422.805 321.711 422.57C322.102 422.336 322.411 422.026 322.641 421.641C322.87 421.25 322.984 420.823 322.984 420.359C322.984 419.901 322.875 419.479 322.656 419.094C322.437 418.708 322.133 418.401 321.742 418.172C321.352 417.943 320.917 417.828 320.437 417.828C319.953 417.828 319.51 417.945 319.109 418.18C318.714 418.414 318.396 418.729 318.156 419.125C317.922 419.516 317.802 419.932 317.797 420.375C317.797 420.818 317.911 421.234 318.141 421.625C318.37 422.01 318.682 422.323 319.078 422.562C319.474 422.802 319.917 422.922 320.406 422.922ZM326 420.531L331.094 412.687H331.937V414.469H331.344L327.516 420.359V420.453H334.406V421.687H326V420.531ZM331.484 421.344V420.797V412.687H332.828V424H331.484V421.344ZM336.312 427.203H335.156L336.016 422.953H337.531L336.312 427.203ZM343.172 424.156C342.339 424.156 341.628 423.93 341.039 423.477C340.451 423.023 340 422.362 339.687 421.492C339.375 420.622 339.219 419.573 339.219 418.344C339.219 417.13 339.375 416.089 339.687 415.219C340 414.344 340.451 413.677 341.039 413.219C341.633 412.76 342.344 412.531 343.172 412.531C343.995 412.531 344.703 412.76 345.297 413.219C345.891 413.677 346.344 414.344 346.656 415.219C346.969 416.089 347.125 417.13 347.125 418.344C347.125 419.573 346.971 420.622 346.664 421.492C346.357 422.362 345.906 423.023 345.312 423.477C344.719 423.93 344.005 424.156 343.172 424.156ZM343.172 422.906C343.714 422.906 344.18 422.729 344.57 422.375C344.961 422.021 345.255 421.503 345.453 420.82C345.651 420.138 345.75 419.312 345.75 418.344C345.75 417.375 345.648 416.547 345.445 415.859C345.242 415.172 344.948 414.648 344.562 414.289C344.177 413.93 343.714 413.75 343.172 413.75C342.63 413.75 342.167 413.93 341.781 414.289C341.396 414.648 341.099 415.172 340.891 415.859C340.682 416.547 340.578 417.375 340.578 418.344C340.578 419.312 340.682 420.138 340.891 420.82C341.099 421.503 341.393 422.021 341.773 422.375C342.159 422.729 342.625 422.906 343.172 422.906ZM352.703 424.156C351.87 424.156 351.159 423.93 350.57 423.477C349.982 423.023 349.531 422.362 349.219 421.492C348.906 420.622 348.75 419.573 348.75 418.344C348.75 417.13 348.906 416.089 349.219 415.219C349.531 414.344 349.982 413.677 350.57 413.219C351.164 412.76 351.875 412.531 352.703 412.531C353.526 412.531 354.234 412.76 354.828 413.219C355.422 413.677 355.875 414.344 356.187 415.219C356.5 416.089 356.656 417.13 356.656 418.344C356.656 419.573 356.503 420.622 356.195 421.492C355.888 422.362 355.437 423.023 354.844 423.477C354.25 423.93 353.536 424.156 352.703 424.156ZM352.703 422.906C353.245 422.906 353.711 422.729 354.102 422.375C354.492 422.021 354.786 421.503 354.984 420.82C355.182 420.138 355.281 419.312 355.281 418.344C355.281 417.375 355.18 416.547 354.977 415.859C354.773 415.172 354.479 414.648 354.094 414.289C353.708 413.93 353.245 413.75 352.703 413.75C352.161 413.75 351.698 413.93 351.312 414.289C350.927 414.648 350.63 415.172 350.422 415.859C350.214 416.547 350.109 417.375 350.109 418.344C350.109 419.312 350.214 420.138 350.422 420.82C350.63 421.503 350.924 422.021 351.305 422.375C351.69 422.729 352.156 422.906 352.703 422.906ZM362.234 424.156C361.401 424.156 360.69 423.93 360.102 423.477C359.513 423.023 359.062 422.362 358.75 421.492C358.437 420.622 358.281 419.573 358.281 418.344C358.281 417.13 358.437 416.089 358.75 415.219C359.062 414.344 359.513 413.677 360.102 413.219C360.695 412.76 361.406 412.531 362.234 412.531C363.057 412.531 363.766 412.76 364.359 413.219C364.953 413.677 365.406 414.344 365.719 415.219C366.031 416.089 366.187 417.13 366.187 418.344C366.187 419.573 366.034 420.622 365.727 421.492C365.419 422.362 364.969 423.023 364.375 423.477C363.781 423.93 363.068 424.156 362.234 424.156ZM362.234 422.906C362.776 422.906 363.242 422.729 363.633 422.375C364.023 422.021 364.318 421.503 364.516 420.82C364.714 420.138 364.812 419.312 364.812 418.344C364.812 417.375 364.711 416.547 364.508 415.859C364.305 415.172 364.01 414.648 363.625 414.289C363.24 413.93 362.776 413.75 362.234 413.75C361.693 413.75 361.229 413.93 360.844 414.289C360.458 414.648 360.161 415.172 359.953 415.859C359.745 416.547 359.641 417.375 359.641 418.344C359.641 419.312 359.745 420.138 359.953 420.82C360.161 421.503 360.456 422.021 360.836 422.375C361.221 422.729 361.687 422.906 362.234 422.906Z" fill="#56555A"/> -<path d="M375.348 423.09H374.422V420.77H375.348V423.09ZM380.012 423.453H379.086V415.543H380.012V423.453ZM380.27 425.727H372.863V424.953H380.27V425.727ZM373.789 425.176H372.863V422.68H373.789V425.176ZM371.363 420.371C372.758 420.363 373.992 420.342 375.066 420.307C376.141 420.268 377.168 420.187 378.148 420.066L378.207 420.734C377.195 420.895 376.135 421 375.025 421.051C373.916 421.102 372.738 421.125 371.492 421.121L371.363 420.371ZM379.332 422.375H376.93V421.707H379.332V422.375ZM374.785 415.965C375.289 415.965 375.736 416.039 376.127 416.187C376.521 416.336 376.826 416.549 377.041 416.826C377.256 417.104 377.363 417.422 377.363 417.781C377.363 418.148 377.256 418.467 377.041 418.736C376.826 419.006 376.523 419.215 376.133 419.363C375.742 419.512 375.293 419.586 374.785 419.586C374.273 419.586 373.822 419.512 373.432 419.363C373.045 419.215 372.744 419.006 372.529 418.736C372.314 418.467 372.207 418.148 372.207 417.781C372.207 417.422 372.314 417.104 372.529 416.826C372.744 416.549 373.047 416.336 373.437 416.187C373.828 416.039 374.277 415.965 374.785 415.965ZM374.785 416.668C374.449 416.664 374.152 416.709 373.895 416.803C373.637 416.893 373.436 417.023 373.291 417.195C373.15 417.367 373.082 417.562 373.086 417.781C373.082 418.004 373.15 418.201 373.291 418.373C373.436 418.541 373.637 418.672 373.895 418.766C374.152 418.859 374.449 418.906 374.785 418.906C375.113 418.906 375.406 418.859 375.664 418.766C375.922 418.672 376.123 418.541 376.268 418.373C376.412 418.201 376.484 418.004 376.484 417.781C376.484 417.562 376.412 417.367 376.268 417.195C376.123 417.023 375.922 416.893 375.664 416.803C375.406 416.709 375.113 416.664 374.785 416.668Z" fill="#56555A"/> -<path d="M382 446H48C43.5817 446 40 449.582 40 454V478C40 482.418 43.5817 486 48 486H382C386.418 486 390 482.418 390 478V454C390 449.582 386.418 446 382 446Z" fill="#F9F8FD"/> -<path d="M61.4297 471.781H48.4297V470.172H61.4297V471.781ZM55.8828 470.57H53.9219V467.086H55.8828V470.57ZM51.8047 462.336H58V460.117H59.9844V467.531H49.8047V460.117H51.8047V462.336ZM58 465.937V463.914H51.8047V465.937H58ZM73.8359 467.398H63.7891V465.805H73.8359V467.398ZM75.2578 471.711H62.2578V470.07H75.2578V471.711ZM73.7344 462.016H65.7578V466.469H63.7891V460.406H73.7344V462.016ZM88.3984 473.437H86.5234V459.203H88.3984V473.437ZM83.8828 466.281H80.7734V464.695H83.8828V466.281ZM85.375 472.812H83.5V459.539H85.375V472.812ZM82.2969 460.906C82.2917 462.318 82.1224 463.596 81.7891 464.742C81.4609 465.888 80.9089 466.945 80.1328 467.914C79.362 468.878 78.3281 469.732 77.0312 470.477L75.9062 469.078C76.9844 468.437 77.849 467.737 78.5 466.977C79.1562 466.211 79.6302 465.367 79.9219 464.445C80.2135 463.523 80.362 462.479 80.3672 461.312V460.906H82.2969ZM81.0078 462.508H76.6875V460.906H81.0078V462.508ZM101.805 467.266H99.8125V459.234H101.805V467.266ZM101.805 473.281H92.2812V467.906H101.805V473.281ZM94.2422 471.68H99.8516V469.484H94.2422V471.68ZM94.0156 459.875C94.7448 459.875 95.4062 460.021 96 460.312C96.5937 460.599 97.0599 461.005 97.3984 461.531C97.737 462.052 97.9062 462.643 97.9062 463.305C97.9062 463.945 97.737 464.526 97.3984 465.047C97.0599 465.562 96.5937 465.969 96 466.266C95.4062 466.557 94.7448 466.703 94.0156 466.703C93.2812 466.703 92.6172 466.557 92.0234 466.266C91.4349 465.969 90.9714 465.562 90.6328 465.047C90.2943 464.526 90.125 463.945 90.125 463.305C90.125 462.643 90.2943 462.052 90.6328 461.531C90.9714 461.005 91.4349 460.599 92.0234 460.312C92.6172 460.021 93.2812 459.875 94.0156 459.875ZM94.0156 461.555C93.6354 461.555 93.2969 461.622 93 461.758C92.7083 461.893 92.4792 462.094 92.3125 462.359C92.151 462.625 92.0703 462.94 92.0703 463.305C92.0703 463.654 92.151 463.958 92.3125 464.219C92.4792 464.474 92.7083 464.672 93 464.812C93.2969 464.953 93.6354 465.023 94.0156 465.023C94.3854 465.023 94.7135 464.953 95 464.812C95.2917 464.672 95.5182 464.474 95.6797 464.219C95.8464 463.958 95.9297 463.654 95.9297 463.305C95.9297 462.94 95.849 462.625 95.6875 462.359C95.526 462.094 95.2995 461.893 95.0078 461.758C94.7161 461.622 94.3854 461.555 94.0156 461.555Z" fill="#56555A"/> -<path d="M316.359 468.531L321.453 460.687H322.297V462.469H321.703L317.875 468.359V468.453H324.766V469.687H316.359V468.531ZM321.844 469.344V468.797V460.687H323.187V472H321.844V469.344ZM330.328 472.156C329.495 472.156 328.784 471.93 328.195 471.477C327.607 471.023 327.156 470.362 326.844 469.492C326.531 468.622 326.375 467.573 326.375 466.344C326.375 465.13 326.531 464.089 326.844 463.219C327.156 462.344 327.607 461.677 328.195 461.219C328.789 460.76 329.5 460.531 330.328 460.531C331.151 460.531 331.859 460.76 332.453 461.219C333.047 461.677 333.5 462.344 333.812 463.219C334.125 464.089 334.281 465.13 334.281 466.344C334.281 467.573 334.128 468.622 333.82 469.492C333.513 470.362 333.062 471.023 332.469 471.477C331.875 471.93 331.161 472.156 330.328 472.156ZM330.328 470.906C330.87 470.906 331.336 470.729 331.727 470.375C332.117 470.021 332.411 469.503 332.609 468.82C332.807 468.138 332.906 467.312 332.906 466.344C332.906 465.375 332.805 464.547 332.602 463.859C332.398 463.172 332.104 462.648 331.719 462.289C331.333 461.93 330.87 461.75 330.328 461.75C329.786 461.75 329.323 461.93 328.937 462.289C328.552 462.648 328.255 463.172 328.047 463.859C327.839 464.547 327.734 465.375 327.734 466.344C327.734 467.312 327.839 468.138 328.047 468.82C328.255 469.503 328.549 470.021 328.93 470.375C329.315 470.729 329.781 470.906 330.328 470.906ZM336.312 475.203H335.156L336.016 470.953H337.531L336.312 475.203ZM343.172 472.156C342.339 472.156 341.628 471.93 341.039 471.477C340.451 471.023 340 470.362 339.687 469.492C339.375 468.622 339.219 467.573 339.219 466.344C339.219 465.13 339.375 464.089 339.687 463.219C340 462.344 340.451 461.677 341.039 461.219C341.633 460.76 342.344 460.531 343.172 460.531C343.995 460.531 344.703 460.76 345.297 461.219C345.891 461.677 346.344 462.344 346.656 463.219C346.969 464.089 347.125 465.13 347.125 466.344C347.125 467.573 346.971 468.622 346.664 469.492C346.357 470.362 345.906 471.023 345.312 471.477C344.719 471.93 344.005 472.156 343.172 472.156ZM343.172 470.906C343.714 470.906 344.18 470.729 344.57 470.375C344.961 470.021 345.255 469.503 345.453 468.82C345.651 468.138 345.75 467.312 345.75 466.344C345.75 465.375 345.648 464.547 345.445 463.859C345.242 463.172 344.948 462.648 344.562 462.289C344.177 461.93 343.714 461.75 343.172 461.75C342.63 461.75 342.167 461.93 341.781 462.289C341.396 462.648 341.099 463.172 340.891 463.859C340.682 464.547 340.578 465.375 340.578 466.344C340.578 467.312 340.682 468.138 340.891 468.82C341.099 469.503 341.393 470.021 341.773 470.375C342.159 470.729 342.625 470.906 343.172 470.906ZM352.703 472.156C351.87 472.156 351.159 471.93 350.57 471.477C349.982 471.023 349.531 470.362 349.219 469.492C348.906 468.622 348.75 467.573 348.75 466.344C348.75 465.13 348.906 464.089 349.219 463.219C349.531 462.344 349.982 461.677 350.57 461.219C351.164 460.76 351.875 460.531 352.703 460.531C353.526 460.531 354.234 460.76 354.828 461.219C355.422 461.677 355.875 462.344 356.187 463.219C356.5 464.089 356.656 465.13 356.656 466.344C356.656 467.573 356.503 468.622 356.195 469.492C355.888 470.362 355.437 471.023 354.844 471.477C354.25 471.93 353.536 472.156 352.703 472.156ZM352.703 470.906C353.245 470.906 353.711 470.729 354.102 470.375C354.492 470.021 354.786 469.503 354.984 468.82C355.182 468.138 355.281 467.312 355.281 466.344C355.281 465.375 355.18 464.547 354.977 463.859C354.773 463.172 354.479 462.648 354.094 462.289C353.708 461.93 353.245 461.75 352.703 461.75C352.161 461.75 351.698 461.93 351.312 462.289C350.927 462.648 350.63 463.172 350.422 463.859C350.214 464.547 350.109 465.375 350.109 466.344C350.109 467.312 350.214 468.138 350.422 468.82C350.63 469.503 350.924 470.021 351.305 470.375C351.69 470.729 352.156 470.906 352.703 470.906ZM362.234 472.156C361.401 472.156 360.69 471.93 360.102 471.477C359.513 471.023 359.062 470.362 358.75 469.492C358.437 468.622 358.281 467.573 358.281 466.344C358.281 465.13 358.437 464.089 358.75 463.219C359.062 462.344 359.513 461.677 360.102 461.219C360.695 460.76 361.406 460.531 362.234 460.531C363.057 460.531 363.766 460.76 364.359 461.219C364.953 461.677 365.406 462.344 365.719 463.219C366.031 464.089 366.187 465.13 366.187 466.344C366.187 467.573 366.034 468.622 365.727 469.492C365.419 470.362 364.969 471.023 364.375 471.477C363.781 471.93 363.068 472.156 362.234 472.156ZM362.234 470.906C362.776 470.906 363.242 470.729 363.633 470.375C364.023 470.021 364.318 469.503 364.516 468.82C364.714 468.138 364.812 467.312 364.812 466.344C364.812 465.375 364.711 464.547 364.508 463.859C364.305 463.172 364.01 462.648 363.625 462.289C363.24 461.93 362.776 461.75 362.234 461.75C361.693 461.75 361.229 461.93 360.844 462.289C360.458 462.648 360.161 463.172 359.953 463.859C359.745 464.547 359.641 465.375 359.641 466.344C359.641 467.312 359.745 468.138 359.953 468.82C360.161 469.503 360.456 470.021 360.836 470.375C361.221 470.729 361.687 470.906 362.234 470.906Z" fill="#56555A"/> -<path d="M375.348 471.09H374.422V468.77H375.348V471.09ZM380.012 471.453H379.086V463.543H380.012V471.453ZM380.27 473.727H372.863V472.953H380.27V473.727ZM373.789 473.176H372.863V470.68H373.789V473.176ZM371.363 468.371C372.758 468.363 373.992 468.342 375.066 468.307C376.141 468.268 377.168 468.187 378.148 468.066L378.207 468.734C377.195 468.895 376.135 469 375.025 469.051C373.916 469.102 372.738 469.125 371.492 469.121L371.363 468.371ZM379.332 470.375H376.93V469.707H379.332V470.375ZM374.785 463.965C375.289 463.965 375.736 464.039 376.127 464.187C376.521 464.336 376.826 464.549 377.041 464.826C377.256 465.104 377.363 465.422 377.363 465.781C377.363 466.148 377.256 466.467 377.041 466.736C376.826 467.006 376.523 467.215 376.133 467.363C375.742 467.512 375.293 467.586 374.785 467.586C374.273 467.586 373.822 467.512 373.432 467.363C373.045 467.215 372.744 467.006 372.529 466.736C372.314 466.467 372.207 466.148 372.207 465.781C372.207 465.422 372.314 465.104 372.529 464.826C372.744 464.549 373.047 464.336 373.437 464.187C373.828 464.039 374.277 463.965 374.785 463.965ZM374.785 464.668C374.449 464.664 374.152 464.709 373.895 464.803C373.637 464.893 373.436 465.023 373.291 465.195C373.15 465.367 373.082 465.562 373.086 465.781C373.082 466.004 373.15 466.201 373.291 466.373C373.436 466.541 373.637 466.672 373.895 466.766C374.152 466.859 374.449 466.906 374.785 466.906C375.113 466.906 375.406 466.859 375.664 466.766C375.922 466.672 376.123 466.541 376.268 466.373C376.412 466.201 376.484 466.004 376.484 465.781C376.484 465.562 376.412 465.367 376.268 465.195C376.123 465.023 375.922 464.893 375.664 464.803C375.406 464.709 375.113 464.664 374.785 464.668Z" fill="#56555A"/> -<path d="M382 494H48C43.5817 494 40 497.582 40 502V526C40 530.418 43.5817 534 48 534H382C386.418 534 390 530.418 390 526V502C390 497.582 386.418 494 382 494Z" fill="#F9F8FD"/> -<mask id="mask4_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="48" y="502" width="60" height="25"> -<path d="M108 502H48V527H108V502Z" fill="white"/> -<path d="M48 502H108V526H48V502Z" fill="black"/> -</mask> -<g mask="url(#mask4_1835_8259)"> -<path d="M108 525H48V527H108V525Z" fill="#B575FF"/> -</g> -<path d="M53.5156 511.086C53.5104 512.206 53.3516 513.273 53.0391 514.289C52.7266 515.305 52.2656 516.206 51.6562 516.992C51.0469 517.773 50.3125 518.365 49.4531 518.766L48.3125 517.195C49.0781 516.852 49.7292 516.357 50.2656 515.711C50.8073 515.06 51.2135 514.336 51.4844 513.539C51.7604 512.737 51.8984 511.919 51.8984 511.086V509.43H53.5156V511.086ZM53.9297 511.086C53.9297 511.883 54.0651 512.659 54.3359 513.414C54.6068 514.164 55.0078 514.844 55.5391 515.453C56.0755 516.057 56.7292 516.518 57.5 516.836L56.4219 518.398C55.5417 518.029 54.7969 517.474 54.1875 516.734C53.5781 515.99 53.1198 515.133 52.8125 514.164C52.5052 513.195 52.3542 512.169 52.3594 511.086V509.43H53.9297V511.086ZM56.9141 510.219H48.8828V508.594H56.9141V510.219ZM60.3281 521.437H58.3047V507.203H60.3281V521.437ZM69.7109 516.5H67.75V514.43H69.7109V516.5ZM75.1953 514.727H62.2812V513.273H75.1953V514.727ZM69.7031 508.922H67.7266V507.203H69.7031V508.922ZM69.3516 509.289C69.3516 509.977 69.1224 510.578 68.6641 511.094C68.2057 511.609 67.5234 512.023 66.6172 512.336C65.7161 512.643 64.6198 512.831 63.3281 512.898L62.7891 511.43C63.8828 511.378 64.7891 511.25 65.5078 511.047C66.2318 510.839 66.7604 510.583 67.0937 510.281C67.4323 509.979 67.6016 509.648 67.6016 509.289V509H69.3516V509.289ZM69.8359 509.289C69.8307 509.648 69.9974 509.979 70.3359 510.281C70.6745 510.583 71.2057 510.839 71.9297 511.047C72.6536 511.25 73.5677 511.378 74.6719 511.43L74.0937 512.898C72.8073 512.831 71.7135 512.641 70.8125 512.328C69.9167 512.016 69.237 511.604 68.7734 511.094C68.3099 510.578 68.0807 509.977 68.0859 509.289V509H69.8359V509.289ZM73.9687 509.805H63.5V508.328H73.9687V509.805ZM73.6406 519.086H65.7187V520.469H63.7578V517.75H71.6719V517.055H63.75V515.625H73.6406V519.086ZM74.0156 521.336H63.7578V519.875H74.0156V521.336ZM92.0469 521.437H90.125V507.203H92.0469V521.437ZM90.6484 514.328H88.2344V512.711H90.6484V514.328ZM88.7969 520.75H86.9297V507.461H88.7969V520.75ZM82.3516 517.008H80.3594V508.797H82.3516V517.008ZM81.3125 516.242C82.1354 516.242 82.9349 516.214 83.7109 516.156C84.4922 516.099 85.2943 515.99 86.1172 515.828L86.3281 517.547C85.4271 517.703 84.5651 517.815 83.7422 517.883C82.9245 517.945 82.1146 517.974 81.3125 517.969H80.3594V516.242H81.3125ZM104.211 510.734H99.9766V509.125H104.211V510.734ZM104.211 513.82H99.9766V512.227H104.211V513.82ZM105.594 521.437H103.609V517.836H95.8281V516.258H105.594V521.437ZM105.594 515.625H103.609V507.203H105.594V515.625ZM97.5781 507.977C98.276 507.977 98.9115 508.125 99.4844 508.422C100.062 508.719 100.516 509.135 100.844 509.672C101.172 510.203 101.338 510.799 101.344 511.461C101.338 512.138 101.172 512.745 100.844 513.281C100.516 513.818 100.065 514.237 99.4922 514.539C98.9193 514.841 98.2812 514.992 97.5781 514.992C96.8646 514.992 96.2187 514.841 95.6406 514.539C95.0677 514.237 94.6146 513.818 94.2812 513.281C93.9531 512.74 93.7891 512.133 93.7891 511.461C93.7891 510.799 93.9531 510.203 94.2812 509.672C94.6146 509.135 95.0677 508.719 95.6406 508.422C96.2187 508.125 96.8646 507.977 97.5781 507.977ZM97.5781 509.664C97.2083 509.664 96.8802 509.734 96.5937 509.875C96.3073 510.016 96.0833 510.224 95.9219 510.5C95.7604 510.776 95.6797 511.096 95.6797 511.461C95.6797 511.836 95.7604 512.161 95.9219 512.437C96.0833 512.714 96.3073 512.927 96.5937 513.078C96.8802 513.229 97.2083 513.305 97.5781 513.305C97.9323 513.305 98.25 513.229 98.5312 513.078C98.8125 512.927 99.0339 512.714 99.1953 512.437C99.3568 512.161 99.4375 511.836 99.4375 511.461C99.4375 511.096 99.3568 510.776 99.1953 510.5C99.0339 510.224 98.8099 510.016 98.5234 509.875C98.2422 509.734 97.9271 509.664 97.5781 509.664Z" fill="#B2B1B6"/> -<path d="M361.766 520.156C360.932 520.156 360.221 519.93 359.633 519.477C359.044 519.023 358.594 518.362 358.281 517.492C357.969 516.622 357.812 515.573 357.812 514.344C357.812 513.125 357.969 512.081 358.281 511.211C358.594 510.341 359.047 509.677 359.641 509.219C360.234 508.76 360.943 508.531 361.766 508.531C362.589 508.531 363.297 508.76 363.891 509.219C364.484 509.677 364.937 510.341 365.25 511.211C365.562 512.081 365.719 513.125 365.719 514.344C365.719 515.573 365.565 516.622 365.258 517.492C364.951 518.362 364.5 519.023 363.906 519.477C363.312 519.93 362.599 520.156 361.766 520.156ZM361.766 518.906C362.307 518.906 362.771 518.729 363.156 518.375C363.542 518.021 363.836 517.503 364.039 516.82C364.242 516.138 364.344 515.312 364.344 514.344C364.344 513.375 364.242 512.547 364.039 511.859C363.836 511.172 363.542 510.648 363.156 510.289C362.771 509.93 362.307 509.75 361.766 509.75C361.224 509.75 360.76 509.93 360.375 510.289C359.99 510.648 359.693 511.172 359.484 511.859C359.276 512.547 359.172 513.375 359.172 514.344C359.172 515.312 359.273 516.138 359.477 516.82C359.68 517.503 359.977 518.021 360.367 518.375C360.758 518.729 361.224 518.906 361.766 518.906Z" fill="#B2B1B6"/> -<path d="M375.348 519.09H374.422V516.77H375.348V519.09ZM380.012 519.453H379.086V511.543H380.012V519.453ZM380.27 521.727H372.863V520.953H380.27V521.727ZM373.789 521.176H372.863V518.68H373.789V521.176ZM371.363 516.371C372.758 516.363 373.992 516.342 375.066 516.307C376.141 516.268 377.168 516.187 378.148 516.066L378.207 516.734C377.195 516.895 376.135 517 375.025 517.051C373.916 517.102 372.738 517.125 371.492 517.121L371.363 516.371ZM379.332 518.375H376.93V517.707H379.332V518.375ZM374.785 511.965C375.289 511.965 375.736 512.039 376.127 512.187C376.521 512.336 376.826 512.549 377.041 512.826C377.256 513.104 377.363 513.422 377.363 513.781C377.363 514.148 377.256 514.467 377.041 514.736C376.826 515.006 376.523 515.215 376.133 515.363C375.742 515.512 375.293 515.586 374.785 515.586C374.273 515.586 373.822 515.512 373.432 515.363C373.045 515.215 372.744 515.006 372.529 514.736C372.314 514.467 372.207 514.148 372.207 513.781C372.207 513.422 372.314 513.104 372.529 512.826C372.744 512.549 373.047 512.336 373.437 512.187C373.828 512.039 374.277 511.965 374.785 511.965ZM374.785 512.668C374.449 512.664 374.152 512.709 373.895 512.803C373.637 512.893 373.436 513.023 373.291 513.195C373.15 513.367 373.082 513.562 373.086 513.781C373.082 514.004 373.15 514.201 373.291 514.373C373.436 514.541 373.637 514.672 373.895 514.766C374.152 514.859 374.449 514.906 374.785 514.906C375.113 514.906 375.406 514.859 375.664 514.766C375.922 514.672 376.123 514.541 376.268 514.373C376.412 514.201 376.484 514.004 376.484 513.781C376.484 513.562 376.412 513.367 376.268 513.195C376.123 513.023 375.922 512.893 375.664 512.803C375.406 512.709 375.113 512.664 374.785 512.668Z" fill="#56555A"/> -<path d="M58.0488 551.953H48.3223V550.764H58.0488V551.953ZM53.9062 551.314H52.4238V549.732H53.9062V551.314ZM53.9062 547.014H52.4238V545.443H53.9062V547.014ZM53.6426 547.277C53.6426 547.82 53.4687 548.303 53.1211 548.725C52.7773 549.143 52.2715 549.482 51.6035 549.744C50.9355 550.006 50.127 550.17 49.1777 550.236L48.7207 549.111C49.5371 549.057 50.2168 548.939 50.7598 548.76C51.3027 548.576 51.6992 548.357 51.9492 548.104C52.2031 547.85 52.3301 547.574 52.3301 547.277V547.066H53.6426V547.277ZM54.0059 547.277C54.002 547.57 54.127 547.846 54.3809 548.104C54.6348 548.357 55.0312 548.576 55.5703 548.76C56.1133 548.939 56.793 549.057 57.6094 549.111L57.1582 550.236C56.209 550.17 55.4004 550.006 54.7324 549.744C54.0645 549.482 53.5566 549.143 53.209 548.725C52.8613 548.303 52.6895 547.82 52.6934 547.277V547.066H54.0059V547.277ZM57.1055 547.547H49.2539V546.363H57.1055V547.547ZM53.168 552.451C53.9453 552.451 54.6113 552.521 55.166 552.662C55.7207 552.803 56.1445 553.008 56.4375 553.277C56.7305 553.547 56.8789 553.875 56.8828 554.262C56.8789 554.652 56.7305 554.982 56.4375 555.252C56.1445 555.525 55.7207 555.73 55.166 555.867C54.6113 556.008 53.9453 556.078 53.168 556.078C52.3828 556.078 51.7109 556.008 51.1523 555.867C50.5977 555.73 50.1719 555.525 49.875 555.252C49.5781 554.982 49.4297 554.652 49.4297 554.262C49.4297 553.875 49.5781 553.547 49.875 553.277C50.1719 553.008 50.5977 552.803 51.1523 552.662C51.7109 552.521 52.3828 552.451 53.168 552.451ZM53.168 553.559C52.6641 553.555 52.248 553.58 51.9199 553.635C51.5957 553.686 51.3516 553.764 51.1875 553.869C51.0273 553.971 50.9492 554.102 50.9531 554.262C50.9492 554.426 51.0273 554.561 51.1875 554.666C51.3516 554.768 51.5957 554.844 51.9199 554.895C52.248 554.945 52.6641 554.971 53.168 554.971C53.6602 554.971 54.0684 554.945 54.3926 554.895C54.7207 554.844 54.9668 554.768 55.1309 554.666C55.2949 554.561 55.377 554.426 55.377 554.262C55.377 554.102 55.2949 553.971 55.1309 553.869C54.9668 553.764 54.7207 553.686 54.3926 553.635C54.0684 553.58 53.6602 553.555 53.168 553.559ZM61.1836 546.053C61.6523 546.053 62.0742 546.164 62.4492 546.387C62.8242 546.605 63.1172 546.914 63.3281 547.312C63.543 547.707 63.6504 548.156 63.6504 548.66C63.6504 549.168 63.543 549.617 63.3281 550.008C63.1172 550.398 62.8242 550.703 62.4492 550.922C62.0742 551.141 61.6523 551.25 61.1836 551.25C60.7148 551.25 60.2949 551.141 59.9238 550.922C59.5527 550.703 59.2617 550.398 59.0508 550.008C58.8437 549.617 58.7402 549.168 58.7402 548.66C58.7402 548.16 58.8437 547.711 59.0508 547.312C59.2617 546.914 59.5527 546.605 59.9238 546.387C60.2949 546.164 60.7148 546.053 61.1836 546.053ZM61.1836 547.33C60.9648 547.33 60.7715 547.383 60.6035 547.488C60.4355 547.59 60.3047 547.742 60.2109 547.945C60.1172 548.145 60.0723 548.383 60.0762 548.66C60.0723 548.937 60.1172 549.178 60.2109 549.381C60.3047 549.58 60.4355 549.734 60.6035 549.844C60.7715 549.953 60.9648 550.008 61.1836 550.008C61.3984 550.008 61.5898 549.953 61.7578 549.844C61.9297 549.734 62.0605 549.58 62.1504 549.381C62.2441 549.178 62.291 548.937 62.291 548.66C62.291 548.383 62.2441 548.145 62.1504 547.945C62.0605 547.742 61.9316 547.59 61.7637 547.488C61.5957 547.383 61.4023 547.33 61.1836 547.33ZM67.8516 551.795H66.4277V545.426H67.8516V551.795ZM66.832 549.205H65.1035V548.01H66.832V549.205ZM65.5605 551.736H64.166V545.607H65.5605V551.736ZM67.8516 556.078H66.3691V553.453H60.4805V552.264H67.8516V556.078Z" fill="#56555A"/> -<path d="M327.797 555H326.73V547.617H326.684L324.621 548.988V547.922L326.73 546.516H327.797V555ZM332.836 555.117C332.211 555.117 331.678 554.947 331.236 554.607C330.795 554.268 330.457 553.771 330.223 553.119C329.988 552.467 329.871 551.68 329.871 550.758C329.871 549.848 329.988 549.066 330.223 548.414C330.457 547.758 330.795 547.258 331.236 546.914C331.682 546.57 332.215 546.398 332.836 546.398C333.453 546.398 333.984 546.57 334.43 546.914C334.875 547.258 335.215 547.758 335.449 548.414C335.684 549.066 335.801 549.848 335.801 550.758C335.801 551.68 335.686 552.467 335.455 553.119C335.225 553.771 334.887 554.268 334.441 554.607C333.996 554.947 333.461 555.117 332.836 555.117ZM332.836 554.18C333.242 554.18 333.592 554.047 333.885 553.781C334.178 553.516 334.398 553.127 334.547 552.615C334.695 552.104 334.77 551.484 334.77 550.758C334.77 550.031 334.693 549.41 334.541 548.895C334.389 548.379 334.168 547.986 333.879 547.717C333.59 547.447 333.242 547.312 332.836 547.312C332.43 547.312 332.082 547.447 331.793 547.717C331.504 547.986 331.281 548.379 331.125 548.895C330.969 549.41 330.891 550.031 330.891 550.758C330.891 551.484 330.969 552.104 331.125 552.615C331.281 553.127 331.502 553.516 331.787 553.781C332.076 554.047 332.426 554.18 332.836 554.18ZM336.996 552.398L340.816 546.516H341.449V547.852H341.004L338.133 552.27V552.34H343.301V553.266H336.996V552.398ZM341.109 553.008V552.598V546.516H342.117V555H341.109V553.008ZM344.73 557.402H343.863L344.508 554.215H345.645L344.73 557.402ZM349.875 555.117C349.25 555.117 348.717 554.947 348.275 554.607C347.834 554.268 347.496 553.771 347.262 553.119C347.027 552.467 346.91 551.68 346.91 550.758C346.91 549.848 347.027 549.066 347.262 548.414C347.496 547.758 347.834 547.258 348.275 546.914C348.721 546.57 349.254 546.398 349.875 546.398C350.492 546.398 351.023 546.57 351.469 546.914C351.914 547.258 352.254 547.758 352.488 548.414C352.723 549.066 352.84 549.848 352.84 550.758C352.84 551.68 352.725 552.467 352.494 553.119C352.264 553.771 351.926 554.268 351.48 554.607C351.035 554.947 350.5 555.117 349.875 555.117ZM349.875 554.18C350.281 554.18 350.631 554.047 350.924 553.781C351.217 553.516 351.437 553.127 351.586 552.615C351.734 552.104 351.809 551.484 351.809 550.758C351.809 550.031 351.732 549.41 351.58 548.895C351.428 548.379 351.207 547.986 350.918 547.717C350.629 547.447 350.281 547.312 349.875 547.312C349.469 547.312 349.121 547.447 348.832 547.717C348.543 547.986 348.32 548.379 348.164 548.895C348.008 549.41 347.93 550.031 347.93 550.758C347.93 551.484 348.008 552.104 348.164 552.615C348.32 553.127 348.541 553.516 348.826 553.781C349.115 554.047 349.465 554.18 349.875 554.18ZM357.023 555.117C356.398 555.117 355.865 554.947 355.424 554.607C354.982 554.268 354.645 553.771 354.41 553.119C354.176 552.467 354.059 551.68 354.059 550.758C354.059 549.848 354.176 549.066 354.41 548.414C354.645 547.758 354.982 547.258 355.424 546.914C355.869 546.57 356.402 546.398 357.023 546.398C357.641 546.398 358.172 546.57 358.617 546.914C359.062 547.258 359.402 547.758 359.637 548.414C359.871 549.066 359.988 549.848 359.988 550.758C359.988 551.68 359.873 552.467 359.643 553.119C359.412 553.771 359.074 554.268 358.629 554.607C358.184 554.947 357.648 555.117 357.023 555.117ZM357.023 554.18C357.43 554.18 357.779 554.047 358.072 553.781C358.365 553.516 358.586 553.127 358.734 552.615C358.883 552.104 358.957 551.484 358.957 550.758C358.957 550.031 358.881 549.41 358.729 548.895C358.576 548.379 358.355 547.986 358.066 547.717C357.777 547.447 357.43 547.312 357.023 547.312C356.617 547.312 356.27 547.447 355.98 547.717C355.691 547.986 355.469 548.379 355.312 548.895C355.156 549.41 355.078 550.031 355.078 550.758C355.078 551.484 355.156 552.104 355.312 552.615C355.469 553.127 355.689 553.516 355.975 553.781C356.264 554.047 356.613 554.18 357.023 554.18ZM364.172 555.117C363.547 555.117 363.014 554.947 362.572 554.607C362.131 554.268 361.793 553.771 361.559 553.119C361.324 552.467 361.207 551.68 361.207 550.758C361.207 549.848 361.324 549.066 361.559 548.414C361.793 547.758 362.131 547.258 362.572 546.914C363.018 546.57 363.551 546.398 364.172 546.398C364.789 546.398 365.32 546.57 365.766 546.914C366.211 547.258 366.551 547.758 366.785 548.414C367.02 549.066 367.137 549.848 367.137 550.758C367.137 551.68 367.021 552.467 366.791 553.119C366.561 553.771 366.223 554.268 365.777 554.607C365.332 554.947 364.797 555.117 364.172 555.117ZM364.172 554.18C364.578 554.18 364.928 554.047 365.221 553.781C365.514 553.516 365.734 553.127 365.883 552.615C366.031 552.104 366.105 551.484 366.105 550.758C366.105 550.031 366.029 549.41 365.877 548.895C365.725 548.379 365.504 547.986 365.215 547.717C364.926 547.447 364.578 547.312 364.172 547.312C363.766 547.312 363.418 547.447 363.129 547.717C362.84 547.986 362.617 548.379 362.461 548.895C362.305 549.41 362.227 550.031 362.227 550.758C362.227 551.484 362.305 552.104 362.461 552.615C362.617 553.127 362.838 553.516 363.123 553.781C363.412 554.047 363.762 554.18 364.172 554.18ZM375.105 553.09H374.18V550.77H375.105V553.09ZM379.77 553.453H378.844V545.543H379.77V553.453ZM380.027 555.727H372.621V554.953H380.027V555.727ZM373.547 555.176H372.621V552.68H373.547V555.176ZM371.121 550.371C372.516 550.363 373.75 550.342 374.824 550.307C375.898 550.268 376.926 550.187 377.906 550.066L377.965 550.734C376.953 550.895 375.893 551 374.783 551.051C373.674 551.102 372.496 551.125 371.25 551.121L371.121 550.371ZM379.09 552.375H376.687V551.707H379.09V552.375ZM374.543 545.965C375.047 545.965 375.494 546.039 375.885 546.187C376.279 546.336 376.584 546.549 376.799 546.826C377.014 547.104 377.121 547.422 377.121 547.781C377.121 548.148 377.014 548.467 376.799 548.736C376.584 549.006 376.281 549.215 375.891 549.363C375.5 549.512 375.051 549.586 374.543 549.586C374.031 549.586 373.58 549.512 373.189 549.363C372.803 549.215 372.502 549.006 372.287 548.736C372.072 548.467 371.965 548.148 371.965 547.781C371.965 547.422 372.072 547.104 372.287 546.826C372.502 546.549 372.805 546.336 373.195 546.187C373.586 546.039 374.035 545.965 374.543 545.965ZM374.543 546.668C374.207 546.664 373.91 546.709 373.652 546.803C373.395 546.893 373.193 547.023 373.049 547.195C372.908 547.367 372.84 547.562 372.844 547.781C372.84 548.004 372.908 548.201 373.049 548.373C373.193 548.541 373.395 548.672 373.652 548.766C373.91 548.859 374.207 548.906 374.543 548.906C374.871 548.906 375.164 548.859 375.422 548.766C375.68 548.672 375.881 548.541 376.025 548.373C376.17 548.201 376.242 548.004 376.242 547.781C376.242 547.562 376.17 547.367 376.025 547.195C375.881 547.023 375.68 546.893 375.422 546.803C375.164 546.709 374.871 546.664 374.543 546.668Z" fill="#B2B1B6"/> -<path d="M199 584H44C37.3726 584 32 589.373 32 596V612C32 618.627 37.3726 624 44 624H199C205.627 624 211 618.627 211 612V596C211 589.373 205.627 584 199 584Z" fill="#E7E6EB"/> -<path d="M88.6328 607.453H86.6406V597.234H88.6328V607.453ZM89.0234 611.195H79.1094V609.586H89.0234V611.195ZM81.125 610.242H79.1094V606.43H81.125V610.242ZM80.8437 598.133C81.5625 598.133 82.2187 598.286 82.8125 598.594C83.4115 598.901 83.8802 599.328 84.2187 599.875C84.5625 600.422 84.7344 601.034 84.7344 601.711C84.7344 602.404 84.5625 603.026 84.2187 603.578C83.8802 604.125 83.4141 604.555 82.8203 604.867C82.2266 605.174 81.5677 605.328 80.8437 605.328C80.1198 605.328 79.4609 605.174 78.8672 604.867C78.2786 604.555 77.8125 604.125 77.4687 603.578C77.125 603.026 76.9531 602.404 76.9531 601.711C76.9531 601.034 77.125 600.422 77.4687 599.875C77.8125 599.328 78.2786 598.901 78.8672 598.594C79.4609 598.286 80.1198 598.133 80.8437 598.133ZM80.8437 599.867C80.474 599.867 80.1406 599.943 79.8437 600.094C79.5521 600.24 79.3203 600.453 79.1484 600.734C78.9818 601.01 78.8984 601.336 78.8984 601.711C78.8984 602.102 78.9818 602.437 79.1484 602.719C79.3203 603 79.5521 603.216 79.8437 603.367C80.1406 603.518 80.474 603.591 80.8437 603.586C81.2083 603.591 81.5339 603.518 81.8203 603.367C82.112 603.216 82.3411 603 82.5078 602.719C82.6745 602.437 82.7578 602.102 82.7578 601.711C82.7578 601.336 82.6745 601.01 82.5078 600.734C82.3411 600.453 82.112 600.24 81.8203 600.094C81.5286 599.943 81.2031 599.867 80.8437 599.867ZM96.3203 607.633H94.3125V604.492H96.3203V607.633ZM102.609 607.977H100.609V597.234H102.609V607.977ZM102.922 611.195H92.3125V609.586H102.922V611.195ZM94.3203 610.016H92.3125V606.945H94.3203V610.016ZM90.5078 603.539C92.4036 603.523 94.0703 603.49 95.5078 603.437C96.9453 603.38 98.3255 603.268 99.6484 603.102L99.75 604.531C98.375 604.76 96.9349 604.917 95.4297 605C93.9297 605.078 92.3672 605.115 90.7422 605.109L90.5078 603.539ZM101.063 606.844H97.8906V605.484H101.063V606.844ZM95.1328 597.711C95.8151 597.711 96.4271 597.818 96.9687 598.031C97.5104 598.245 97.9323 598.547 98.2344 598.937C98.5365 599.323 98.6875 599.763 98.6875 600.258C98.6875 600.763 98.5365 601.203 98.2344 601.578C97.9323 601.953 97.5104 602.247 96.9687 602.461C96.4323 602.669 95.8203 602.773 95.1328 602.773C94.4349 602.773 93.8151 602.669 93.2734 602.461C92.737 602.247 92.3177 601.953 92.0156 601.578C91.7135 601.203 91.5625 600.763 91.5625 600.258C91.5625 599.763 91.7135 599.32 92.0156 598.93C92.3177 598.539 92.7396 598.24 93.2812 598.031C93.8229 597.818 94.4401 597.711 95.1328 597.711ZM95.1328 599.172C94.7943 599.172 94.5 599.214 94.25 599.297C94 599.38 93.8021 599.505 93.6562 599.672C93.5156 599.833 93.4479 600.029 93.4531 600.258C93.4479 600.487 93.5156 600.682 93.6562 600.844C93.8021 601.005 94 601.128 94.25 601.211C94.5 601.294 94.7943 601.336 95.1328 601.336C95.4609 601.336 95.7474 601.294 95.9922 601.211C96.2422 601.128 96.4375 601.005 96.5781 600.844C96.7187 600.682 96.7891 600.487 96.7891 600.258C96.7891 600.034 96.7187 599.839 96.5781 599.672C96.4375 599.505 96.2422 599.38 95.9922 599.297C95.7474 599.214 95.4609 599.172 95.1328 599.172ZM118.789 601.219H115.125V599.602H118.789V601.219ZM118.859 604.25H115.125V602.648H118.859V604.25ZM120.078 607.719H118.094V597.234H120.078V607.719ZM120.383 611.195H110.609V609.586H120.383V611.195ZM112.625 610.5H110.609V606.672H112.625V610.5ZM110.703 600.336H113.5V598.164H115.477V605.477H108.695V598.164H110.703V600.336ZM113.5 603.898V601.859H110.703V603.898H113.5ZM134.922 605.508H121.93V603.93H134.922V605.508ZM129.398 604.555H127.445V601.789H129.398V604.555ZM133.437 602.711H123.5V601.148H133.437V602.711ZM133.359 599.398H125.477V602.172H123.5V597.844H133.359V599.398ZM128.391 606.211C129.417 606.211 130.299 606.315 131.039 606.523C131.779 606.727 132.346 607.026 132.742 607.422C133.138 607.812 133.339 608.286 133.344 608.844C133.339 609.396 133.138 609.865 132.742 610.25C132.352 610.641 131.784 610.937 131.039 611.141C130.299 611.349 129.417 611.456 128.391 611.461C127.354 611.456 126.464 611.349 125.719 611.141C124.974 610.937 124.401 610.641 124 610.25C123.604 609.859 123.406 609.391 123.406 608.844C123.406 608.286 123.604 607.812 124 607.422C124.401 607.026 124.974 606.727 125.719 606.523C126.464 606.315 127.354 606.211 128.391 606.211ZM128.391 607.734C127.729 607.734 127.18 607.776 126.742 607.859C126.31 607.937 125.982 608.06 125.758 608.227C125.539 608.393 125.432 608.599 125.437 608.844C125.432 609.094 125.539 609.299 125.758 609.461C125.982 609.622 126.31 609.742 126.742 609.82C127.18 609.898 127.729 609.937 128.391 609.937C129.042 609.937 129.583 609.898 130.016 609.82C130.453 609.742 130.781 609.622 131 609.461C131.224 609.299 131.336 609.094 131.336 608.844C131.336 608.604 131.224 608.401 131 608.234C130.781 608.062 130.453 607.937 130.016 607.859C129.578 607.776 129.036 607.734 128.391 607.734ZM146.906 611.453H144.93V606.297H146.906V611.453ZM152.43 607.359H139.461V605.727H152.43V607.359ZM146.68 600.109C146.68 600.917 146.448 601.664 145.984 602.352C145.526 603.034 144.854 603.607 143.969 604.07C143.089 604.534 142.044 604.836 140.836 604.977L140.109 603.422C141.125 603.297 141.997 603.06 142.727 602.711C143.456 602.362 144.005 601.958 144.375 601.5C144.745 601.042 144.93 600.578 144.93 600.109V599.75H146.68V600.109ZM146.93 600.109C146.93 600.568 147.112 601.026 147.477 601.484C147.846 601.943 148.393 602.349 149.117 602.703C149.846 603.057 150.716 603.297 151.727 603.422L151.008 604.977C149.805 604.836 148.76 604.529 147.875 604.055C146.995 603.576 146.323 602.995 145.859 602.312C145.401 601.625 145.172 600.891 145.172 600.109V599.75H146.93V600.109ZM151.234 600.422H140.633V598.852H151.234V600.422ZM146.906 599.391H144.93V597.234H146.906V599.391ZM164.5 611.414H162.5V597.203H164.5V611.414ZM166.508 604.312H163.984V602.672H166.508V604.312ZM160.703 598.672C160.698 600.151 160.484 601.518 160.062 602.773C159.646 604.029 158.961 605.182 158.008 606.234C157.055 607.286 155.805 608.193 154.258 608.953L153.133 607.43C154.404 606.789 155.453 606.062 156.281 605.25C157.109 604.432 157.727 603.513 158.133 602.492C158.539 601.466 158.745 600.312 158.75 599.031V598.672H160.703ZM159.75 600.305H153.93V598.672H159.75V600.305Z" fill="#56555A"/> -<path d="M386 584H231C224.373 584 219 589.373 219 596V612C219 618.627 224.373 624 231 624H386C392.627 624 398 618.627 398 612V596C398 589.373 392.627 584 386 584Z" fill="#B575FF"/> -<path d="M268.828 601.086C268.823 602.206 268.664 603.273 268.352 604.289C268.039 605.305 267.578 606.206 266.969 606.992C266.359 607.773 265.625 608.365 264.766 608.766L263.625 607.195C264.391 606.852 265.042 606.357 265.578 605.711C266.12 605.06 266.526 604.336 266.797 603.539C267.073 602.737 267.211 601.919 267.211 601.086V599.43H268.828V601.086ZM269.242 601.086C269.242 601.883 269.378 602.659 269.648 603.414C269.919 604.164 270.32 604.844 270.852 605.453C271.388 606.057 272.042 606.518 272.812 606.836L271.734 608.398C270.854 608.029 270.109 607.474 269.5 606.734C268.891 605.99 268.432 605.133 268.125 604.164C267.818 603.195 267.667 602.169 267.672 601.086V599.43H269.242V601.086ZM272.227 600.219H264.195V598.594H272.227V600.219ZM275.641 611.437H273.617V597.203H275.641V611.437ZM285.023 606.5H283.062V604.43H285.023V606.5ZM290.508 604.727H277.594V603.273H290.508V604.727ZM285.016 598.922H283.039V597.203H285.016V598.922ZM284.664 599.289C284.664 599.977 284.435 600.578 283.977 601.094C283.518 601.609 282.836 602.023 281.93 602.336C281.029 602.643 279.932 602.831 278.641 602.898L278.102 601.43C279.195 601.378 280.102 601.25 280.82 601.047C281.544 600.839 282.073 600.583 282.406 600.281C282.745 599.979 282.914 599.648 282.914 599.289V599H284.664V599.289ZM285.148 599.289C285.143 599.648 285.31 599.979 285.648 600.281C285.987 600.583 286.518 600.839 287.242 601.047C287.966 601.25 288.88 601.378 289.984 601.43L289.406 602.898C288.12 602.831 287.026 602.641 286.125 602.328C285.229 602.016 284.549 601.604 284.086 601.094C283.622 600.578 283.393 599.977 283.398 599.289V599H285.148V599.289ZM289.281 599.805H278.812V598.328H289.281V599.805ZM288.953 609.086H281.031V610.469H279.07V607.75H286.984V607.055H279.062V605.625H288.953V609.086ZM289.328 611.336H279.07V609.875H289.328V611.336ZM307.359 611.437H305.437V597.203H307.359V611.437ZM305.961 604.328H303.547V602.711H305.961V604.328ZM304.109 610.75H302.242V597.461H304.109V610.75ZM297.664 607.008H295.672V598.797H297.664V607.008ZM296.625 606.242C297.448 606.242 298.247 606.214 299.023 606.156C299.805 606.099 300.607 605.99 301.43 605.828L301.641 607.547C300.74 607.703 299.878 607.815 299.055 607.883C298.237 607.945 297.427 607.974 296.625 607.969H295.672V606.242H296.625ZM319.523 600.734H315.289V599.125H319.523V600.734ZM319.523 603.82H315.289V602.227H319.523V603.82ZM320.906 611.437H318.922V607.836H311.141V606.258H320.906V611.437ZM320.906 605.625H318.922V597.203H320.906V605.625ZM312.891 597.977C313.589 597.977 314.224 598.125 314.797 598.422C315.375 598.719 315.828 599.135 316.156 599.672C316.484 600.203 316.651 600.799 316.656 601.461C316.651 602.138 316.484 602.745 316.156 603.281C315.828 603.818 315.378 604.237 314.805 604.539C314.232 604.841 313.594 604.992 312.891 604.992C312.177 604.992 311.531 604.841 310.953 604.539C310.38 604.237 309.927 603.818 309.594 603.281C309.266 602.74 309.102 602.133 309.102 601.461C309.102 600.799 309.266 600.203 309.594 599.672C309.927 599.135 310.38 598.719 310.953 598.422C311.531 598.125 312.177 597.977 312.891 597.977ZM312.891 599.664C312.521 599.664 312.193 599.734 311.906 599.875C311.62 600.016 311.396 600.224 311.234 600.5C311.073 600.776 310.992 601.096 310.992 601.461C310.992 601.836 311.073 602.161 311.234 602.437C311.396 602.714 311.62 602.927 311.906 603.078C312.193 603.229 312.521 603.305 312.891 603.305C313.245 603.305 313.562 603.229 313.844 603.078C314.125 602.927 314.346 602.714 314.508 602.437C314.669 602.161 314.75 601.836 314.75 601.461C314.75 601.096 314.669 600.776 314.508 600.5C314.346 600.224 314.122 600.016 313.836 599.875C313.555 599.734 313.24 599.664 312.891 599.664ZM333.906 611.453H331.93V606.297H333.906V611.453ZM339.43 607.359H326.461V605.727H339.43V607.359ZM333.68 600.109C333.68 600.917 333.448 601.664 332.984 602.352C332.526 603.034 331.854 603.607 330.969 604.07C330.089 604.534 329.044 604.836 327.836 604.977L327.109 603.422C328.125 603.297 328.997 603.06 329.727 602.711C330.456 602.362 331.005 601.958 331.375 601.5C331.745 601.042 331.93 600.578 331.93 600.109V599.75H333.68V600.109ZM333.93 600.109C333.93 600.568 334.112 601.026 334.477 601.484C334.846 601.943 335.393 602.349 336.117 602.703C336.846 603.057 337.716 603.297 338.727 603.422L338.008 604.977C336.805 604.836 335.76 604.529 334.875 604.055C333.995 603.576 333.323 602.995 332.859 602.312C332.401 601.625 332.172 600.891 332.172 600.109V599.75H333.93V600.109ZM338.234 600.422H327.633V598.852H338.234V600.422ZM333.906 599.391H331.93V597.234H333.906V599.391ZM351.5 611.414H349.5V597.203H351.5V611.414ZM353.508 604.312H350.984V602.672H353.508V604.312ZM347.703 598.672C347.698 600.151 347.484 601.518 347.062 602.773C346.646 604.029 345.961 605.182 345.008 606.234C344.055 607.286 342.805 608.193 341.258 608.953L340.133 607.43C341.404 606.789 342.453 606.062 343.281 605.25C344.109 604.432 344.727 603.513 345.133 602.492C345.539 601.466 345.745 600.312 345.75 599.031V598.672H347.703ZM346.75 600.305H340.93V598.672H346.75V600.305Z" fill="white"/> -<path d="M80.2334 43.1544C81.0801 43.1599 81.8548 43.3508 82.5576 43.7272C83.2604 44.1035 83.8276 44.7232 84.2593 45.5865C84.6965 46.4498 84.915 47.5759 84.915 48.9649C84.915 50.3263 84.7214 51.4994 84.334 52.4845C83.9466 53.464 83.3877 54.2138 82.6572 54.734C81.9323 55.2486 81.0801 55.506 80.1006 55.506C79.3369 55.506 78.6535 55.3593 78.0503 55.066C77.4526 54.7672 76.9684 54.3605 76.5977 53.8458C76.2324 53.3312 76.0055 52.7418 75.917 52.0777H78.042C78.1195 52.3932 78.2523 52.6671 78.4404 52.8995C78.6286 53.1319 78.861 53.3118 79.1377 53.4391C79.4199 53.5663 79.7409 53.63 80.1006 53.63C80.6761 53.63 81.1659 53.4667 81.5698 53.1402C81.9793 52.8137 82.2892 52.3434 82.4995 51.7291C82.7098 51.1148 82.8177 50.3788 82.8232 49.5211H82.6987C82.4995 49.8642 82.2422 50.1603 81.9268 50.4093C81.6169 50.6528 81.2627 50.8409 80.8643 50.9737C80.4714 51.1065 80.0563 51.173 79.6191 51.173C78.9053 51.173 78.2578 51.0069 77.6768 50.6749C77.1012 50.3373 76.6447 49.8725 76.3071 49.2804C75.9696 48.6883 75.8008 48.0214 75.8008 47.2799C75.8008 46.4941 75.9834 45.7885 76.3486 45.1632C76.7194 44.5323 77.2396 44.0398 77.9092 43.6856C78.5843 43.3259 79.359 43.1489 80.2334 43.1544ZM80.2334 44.8976C79.7962 44.8976 79.3978 45.0027 79.0381 45.213C78.6839 45.4177 78.4045 45.7 78.1997 46.0597C77.995 46.4138 77.8953 46.8012 77.9009 47.2218C77.9009 47.6479 78.0005 48.038 78.1997 48.3922C78.3989 48.7408 78.6729 49.0175 79.0215 49.2223C79.3701 49.427 79.7658 49.5294 80.2085 49.5294C80.6401 49.5294 81.0358 49.4215 81.3955 49.2057C81.7607 48.9898 82.0485 48.7049 82.2588 48.3507C82.4691 47.9965 82.5742 47.6147 82.5742 47.2052C82.5742 46.7957 82.4718 46.4138 82.2671 46.0597C82.0623 45.7055 81.7829 45.4233 81.4287 45.213C81.0745 45.0027 80.6761 44.8976 80.2334 44.8976ZM88.0444 53.8375C87.8065 53.8375 87.5879 53.7794 87.3887 53.6632C87.195 53.547 87.04 53.3893 86.9238 53.19C86.8076 52.9908 86.7523 52.775 86.7578 52.5426C86.7523 52.3157 86.8076 52.1054 86.9238 51.9117C87.04 51.7125 87.195 51.5576 87.3887 51.4469C87.5879 51.3307 87.8065 51.2726 88.0444 51.2726C88.2713 51.2726 88.4816 51.3307 88.6753 51.4469C88.8745 51.5576 89.0322 51.7125 89.1484 51.9117C89.2646 52.1054 89.3228 52.3157 89.3228 52.5426C89.3228 52.775 89.2646 52.9908 89.1484 53.19C89.0322 53.3893 88.8745 53.547 88.6753 53.6632C88.4816 53.7794 88.2713 53.8375 88.0444 53.8375ZM88.0444 47.3961C87.8065 47.3961 87.5879 47.338 87.3887 47.2218C87.195 47.1056 87.04 46.9479 86.9238 46.7486C86.8076 46.5494 86.7523 46.3336 86.7578 46.1012C86.7523 45.8743 86.8076 45.664 86.9238 45.4703C87.04 45.2711 87.195 45.1161 87.3887 45.0055C87.5879 44.8893 87.8065 44.8312 88.0444 44.8312C88.2713 44.8312 88.4816 44.8893 88.6753 45.0055C88.8745 45.1161 89.0322 45.2711 89.1484 45.4703C89.2646 45.664 89.3228 45.8743 89.3228 46.1012C89.3228 46.3336 89.2646 46.5494 89.1484 46.7486C89.0322 46.9479 88.8745 47.1056 88.6753 47.2218C88.4816 47.338 88.2713 47.3961 88.0444 47.3961ZM91.124 51.3805L96.3203 43.3204H97.748V45.7774H96.8599L93.3403 51.2311V51.3307H100.595V53.0987H91.124V51.3805ZM96.9595 52.5841L96.9844 51.8038V43.3204H99.0264V55.3399H96.9595V52.5841ZM107.053 55.3399H104.878V45.4288H104.812L101.998 47.2301V45.2462L104.978 43.3204H107.053V55.3399Z" fill="black"/> -<path opacity="0.35" d="M369.133 43.5H352.733C350.634 43.5 348.933 45.2013 348.933 47.3V51.7C348.933 53.7987 350.634 55.5 352.733 55.5H369.133C371.232 55.5 372.933 53.7987 372.933 51.7V47.3C372.933 45.2013 371.232 43.5 369.133 43.5Z" stroke="black"/> -<path opacity="0.4" d="M374.433 47.7812V51.8568C375.237 51.5117 375.761 50.7086 375.761 49.819C375.761 48.9294 375.237 48.1265 374.433 47.7812Z" fill="black"/> -<path d="M368.933 45H352.933C351.552 45 350.433 46.1193 350.433 47.5V51.5C350.433 52.8807 351.552 54 352.933 54H368.933C370.314 54 371.433 52.8807 371.433 51.5V47.5C371.433 46.1193 370.314 45 368.933 45Z" fill="black"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M332.703 46.104C335.19 46.1041 337.582 47.0262 339.385 48.6796C339.52 48.8073 339.737 48.8057 339.871 48.676L341.169 47.4126C341.236 47.3468 341.274 47.2577 341.273 47.165C341.273 47.0724 341.234 46.9837 341.166 46.9187C336.435 42.544 328.971 42.544 324.24 46.9187C324.171 46.9837 324.132 47.0723 324.132 47.165C324.131 47.2577 324.169 47.3468 324.237 47.4126L325.534 48.676C325.668 48.8059 325.885 48.8075 326.021 48.6796C327.824 47.0261 330.216 46.104 332.703 46.104ZM332.7 50.3243C334.057 50.3242 335.366 50.8359 336.372 51.76C336.508 51.8912 336.723 51.8883 336.855 51.7536L338.142 50.4343C338.21 50.3651 338.248 50.2712 338.247 50.1737C338.246 50.0761 338.206 49.9831 338.137 49.9153C335.073 47.0244 330.329 47.0244 327.265 49.9153C327.196 49.9831 327.156 50.0762 327.155 50.1738C327.154 50.2713 327.192 50.3652 327.26 50.4343L328.547 51.7536C328.68 51.8883 328.894 51.8912 329.03 51.76C330.036 50.8365 331.343 50.3248 332.7 50.3243ZM335.224 53.1178C335.226 53.2232 335.189 53.3247 335.122 53.3985L332.945 55.8533C332.881 55.9254 332.794 55.966 332.704 55.966C332.613 55.966 332.526 55.9254 332.462 55.8533L330.285 53.3985C330.218 53.3247 330.181 53.2231 330.183 53.1177C330.185 53.0124 330.225 52.9126 330.295 52.842C331.686 51.5281 333.721 51.5281 335.112 52.842C335.182 52.9127 335.222 53.0125 335.224 53.1178Z" fill="black"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M316.633 44.6819C316.633 44.0488 316.155 43.5356 315.566 43.5356H314.499C313.91 43.5356 313.433 44.0488 313.433 44.6819V54.6158C313.433 55.2489 313.91 55.7621 314.499 55.7621H315.566C316.155 55.7621 316.633 55.2489 316.633 54.6158V44.6819ZM309.199 45.9809H310.265C310.854 45.9809 311.332 46.5064 311.332 47.1547V54.5883C311.332 55.2366 310.854 55.7621 310.265 55.7621H309.199C308.609 55.7621 308.132 55.2366 308.132 54.5883V47.1547C308.132 46.5064 308.609 45.9809 309.199 45.9809ZM304.867 48.63H303.8C303.211 48.63 302.733 49.1622 302.733 49.8187V54.5734C302.733 55.2299 303.211 55.762 303.8 55.762H304.867C305.456 55.762 305.933 55.2299 305.933 54.5734V49.8187C305.933 49.1622 305.456 48.63 304.867 48.63ZM299.566 51.0753H298.499C297.91 51.0753 297.433 51.5999 297.433 52.247V54.5904C297.433 55.2375 297.91 55.7621 298.499 55.7621H299.566C300.155 55.7621 300.633 55.2375 300.633 54.5904V52.247C300.633 51.5999 300.155 51.0753 299.566 51.0753Z" fill="black"/> -</g> -</g> -</g> -<mask id="mask5_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="426" y="221" width="3" height="105"> -<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="white"/> -</mask> -<g mask="url(#mask5_1835_8259)"> -<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="url(#paint0_linear_1835_8259)"/> -</g> -<mask id="mask6_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="428" y="221" width="2" height="105"> -<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="white"/> -</mask> -<g mask="url(#mask6_1835_8259)"> -<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="url(#paint1_linear_1835_8259)"/> -</g> -<mask id="mask7_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="3" height="67"> -<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="white"/> -</mask> -<g mask="url(#mask7_1835_8259)"> -<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="url(#paint2_linear_1835_8259)"/> -</g> -<mask id="mask8_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="1" height="67"> -<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.354 0 200.307L0.706443 199.448V265.633V265.637Z" fill="white"/> -</mask> -<g mask="url(#mask8_1835_8259)"> -<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.354 0 200.307L0.706443 199.448V265.633V265.637Z" fill="url(#paint3_linear_1835_8259)"/> -</g> -<mask id="mask9_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="199" width="2" height="67"> -<path d="M2.11914 265.653H3.63295V199.447H2.11914V265.653Z" fill="white"/> -</mask> -<g mask="url(#mask9_1835_8259)"> -<path d="M2.11914 265.653H3.63295V199.447H2.11914V265.653Z" fill="url(#paint4_linear_1835_8259)"/> -</g> -<mask id="mask10_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="3" height="67"> -<path d="M2.11943 348.924H0.706543V282.72H2.11943V348.924Z" fill="white"/> -</mask> -<g mask="url(#mask10_1835_8259)"> -<path d="M2.11943 348.924H0.706543V282.72H2.11943V348.924Z" fill="url(#paint5_linear_1835_8259)"/> -</g> -<mask id="mask11_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="1" height="67"> -<path d="M0.706443 348.928L0 348.068C0.333038 341.036 0.357259 290.645 0 283.598L0.706443 282.738V348.924V348.928Z" fill="white"/> -</mask> -<g mask="url(#mask11_1835_8259)"> -<path d="M0.706443 348.928L0 348.068C0.333038 341.036 0.357259 290.645 0 283.598L0.706443 282.738V348.924V348.928Z" fill="url(#paint6_linear_1835_8259)"/> -</g> -<mask id="mask12_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="282" width="2" height="67"> -<path d="M2.11914 348.944H3.63295V282.738H2.11914V348.944Z" fill="white"/> -</mask> -<g mask="url(#mask12_1835_8259)"> -<path d="M2.11914 348.944H3.63295V282.738H2.11914V348.944Z" fill="url(#paint7_linear_1835_8259)"/> -</g> -<mask id="mask13_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="3" height="35"> -<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="white"/> -</mask> -<g mask="url(#mask13_1835_8259)"> -<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="url(#paint8_linear_1835_8259)"/> -</g> -<mask id="mask14_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="1" height="35"> -<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="white"/> -</mask> -<g mask="url(#mask14_1835_8259)"> -<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="url(#paint9_linear_1835_8259)"/> -</g> -<mask id="mask15_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="136" width="2" height="35"> -<path d="M2.11914 170.878H3.63295V136.895H2.11914V170.878Z" fill="white"/> -</mask> -<g mask="url(#mask15_1835_8259)"> -<path d="M2.11914 170.878H3.63295V136.895H2.11914V170.878Z" fill="url(#paint10_linear_1835_8259)"/> -</g> -<path d="M246.886 60.5405H179.37C171.773 60.5405 165.615 54.3824 165.615 46.7851C165.615 39.1878 171.773 33.0295 179.37 33.0295H246.886C254.483 33.0295 260.641 39.1878 260.641 46.7851C260.641 54.3824 254.483 60.5405 246.886 60.5405ZM243.083 40.7803C239.767 40.7803 237.079 43.4688 237.079 46.7851C237.079 50.1033 239.767 52.7899 243.083 52.7899C246.4 52.7899 249.088 50.1033 249.088 46.7851C249.088 43.4688 246.4 40.7803 243.083 40.7803Z" fill="#1D1D1B"/> -<mask id="mask16_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="40" width="13" height="13"> -<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="white"/> -</mask> -<g mask="url(#mask16_1835_8259)"> -<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="url(#paint11_linear_1835_8259)"/> -</g> -<mask id="mask17_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="41" width="12" height="12"> -<path d="M243.063 52.3916C242.504 52.3916 241.943 52.3089 241.4 52.1373C240.526 51.8628 239.747 51.3804 239.117 50.7526C238.473 50.1067 238.011 49.3216 237.746 48.4779C237.294 47.0347 237.419 45.422 238.182 44.0535C238.437 43.5994 238.75 43.1836 239.115 42.8203C239.745 42.1886 240.524 41.7082 241.398 41.4317C241.941 41.2621 242.502 41.1794 243.061 41.1794C243.715 41.1794 244.367 41.2924 244.982 41.5124C245.751 41.7889 246.464 42.2289 247.053 42.8203C247.419 43.1836 247.734 43.5994 247.986 44.0535C248.749 45.422 248.874 47.0347 248.42 48.4779C248.155 49.3216 247.697 50.1067 247.051 50.7526C246.462 51.342 245.749 51.782 244.98 52.0565C244.367 52.2765 243.717 52.3916 243.063 52.3916ZM243.083 43.3532C241.19 43.3532 239.654 44.8892 239.654 46.7845C239.654 48.6798 241.19 50.2158 243.083 50.2158C244.978 50.2158 246.516 48.6798 246.516 46.7845C246.516 44.8892 244.978 43.3532 243.083 43.3532Z" fill="white"/> -</mask> -<g mask="url(#mask17_1835_8259)"> -<rect x="235.513" y="39.4111" width="14.7748" height="14.7748" fill="url(#pattern0_1835_8259)"/> -</g> -<mask id="mask18_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="239" y="43" width="8" height="8"> -<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="white"/> -</mask> -<g mask="url(#mask18_1835_8259)"> -<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="url(#paint12_linear_1835_8259)"/> -</g> -<mask id="mask19_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="240" y="43" width="7" height="7"> -<path d="M243.081 49.7905C241.416 49.7905 240.08 48.4463 240.08 46.7892C240.08 45.124 241.416 43.7838 243.081 43.7838C244.74 43.7838 246.084 45.124 246.084 46.7892C246.084 47.2636 245.973 47.7156 245.778 48.1153C245.669 47.6369 245.241 47.2817 244.732 47.2817C244.139 47.2817 243.66 47.7621 243.66 48.3535C243.66 48.8823 244.042 49.3223 244.546 49.4091C244.112 49.6513 243.612 49.7905 243.081 49.7905Z" fill="white"/> -</mask> -<g mask="url(#mask19_1835_8259)"> -<rect x="238.337" y="42.2378" width="8.92141" height="8.92141" fill="url(#pattern1_1835_8259)"/> -</g> -<mask id="mask20_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="244" y="48" width="2" height="2"> -<path d="M244.732 49.4263C244.668 49.4263 244.607 49.4182 244.546 49.4081C245.077 49.1114 245.507 48.6593 245.778 48.1143C245.794 48.189 245.804 48.2698 245.804 48.3525C245.804 48.9439 245.324 49.4263 244.732 49.4263Z" fill="white"/> -</mask> -<g mask="url(#mask20_1835_8259)"> -<rect x="243.182" y="46.2739" width="4.07723" height="4.88459" fill="url(#pattern2_1835_8259)"/> -</g> -<mask id="mask21_1835_8259" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="243" y="47" width="3" height="3"> -<path d="M244.547 49.4082C244.042 49.3214 243.661 48.8814 243.661 48.3526C243.661 47.7612 244.139 47.2808 244.732 47.2808C245.241 47.2808 245.669 47.636 245.778 48.1144C245.507 48.6593 245.078 49.1115 244.547 49.4082Z" fill="white"/> -</mask> -<g mask="url(#mask21_1835_8259)"> -<rect x="242.173" y="46.2739" width="5.08643" height="4.88459" fill="url(#pattern3_1835_8259)"/> -</g> -<defs> -<pattern id="pattern0_1835_8259" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image0_1835_8259" transform="scale(0.0666667)"/> -</pattern> -<pattern id="pattern1_1835_8259" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image1_1835_8259" transform="scale(0.111111)"/> -</pattern> -<pattern id="pattern2_1835_8259" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image2_1835_8259" transform="scale(0.25 0.2)"/> -</pattern> -<pattern id="pattern3_1835_8259" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image3_1835_8259" transform="scale(0.2)"/> -</pattern> -<linearGradient id="paint0_linear_1835_8259" x1="427.525" y1="221.428" x2="427.525" y2="325.938" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2B1D2A"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2B1D2A"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint1_linear_1835_8259" x1="429.38" y1="221.455" x2="429.38" y2="325.943" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint2_linear_1835_8259" x1="1.41299" y1="199.429" x2="1.41299" y2="265.633" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint3_linear_1835_8259" x1="0.353221" y1="199.448" x2="0.353221" y2="265.637" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint4_linear_1835_8259" x1="2.87604" y1="265.653" x2="2.87604" y2="199.446" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint5_linear_1835_8259" x1="1.41299" y1="282.72" x2="1.41299" y2="348.924" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint6_linear_1835_8259" x1="0.353221" y1="282.738" x2="0.353221" y2="348.928" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint7_linear_1835_8259" x1="2.87604" y1="348.944" x2="2.87604" y2="282.737" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint8_linear_1835_8259" x1="1.41299" y1="136.878" x2="1.41299" y2="170.859" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint9_linear_1835_8259" x1="0.353222" y1="136.895" x2="0.353222" y2="170.862" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint10_linear_1835_8259" x1="2.87604" y1="170.878" x2="2.87604" y2="136.895" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint11_linear_1835_8259" x1="243.083" y1="52.4197" x2="243.083" y2="40.5892" gradientUnits="userSpaceOnUse"> -<stop stop-color="#666666"/> -<stop offset="1" stop-color="#010104"/> -</linearGradient> -<linearGradient id="paint12_linear_1835_8259" x1="243.083" y1="43.5652" x2="243.083" y2="50.325" gradientUnits="userSpaceOnUse"> -<stop stop-color="#0B131C"/> -<stop offset="1" stop-color="#354039"/> -</linearGradient> -<clipPath id="clip0_1835_8259"> -<rect width="382" height="827" fill="white" transform="translate(24 20)"/> -</clipPath> -<image id="image0_1835_8259" width="15" height="15" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAUBJREFUKJGFks1S3TAMhT/JshPndl8ehIH3X8LQ9m1uAP+IhXMbAs1U2nhkHR0dSfLz7s45sTRNRItYtEP8slz48/sXegb8n90/PGJnnxoCACKCqo4O7Jh+Cr6ZM1SJCuEL+LTtoIFoEdm81kop70dms/iNxbtz87C1b2aEYOAOIiOmYSd3902vYmbkJRMtEmMkpUQpdVBseSZbFWBLKExpIsaIiCIiXC4/iDHy+rrSWuO9lAFeluUvuJRCnjPIkJBzZkoJVSGEwDxn1vW6a/7K/Pk9pYSZMc8ZC4E3d1R3mWZhH7/70KOq4OCAqtJ756011nXluq47eJrnw/i9d2qt4yB8FCy1YMEIQdGt0+7+/UhEFdUxqNYq12uh9T628EkinFzY7ZJqa4d4v61ShJfnJwTw+4fHf9U4tZfnJwA+AH+jc5A39zmDAAAAAElFTkSuQmCC"/> -<image id="image1_1835_8259" width="9" height="9" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAABHNCSVQICAgIfAhkiAAAAMRJREFUGJWF0LFKA1EQheH/3GxW4qIkogSCjUGstLDQKnUqKx9CH0vs8kYhxNJCElJkCSy6985YhDUoQqb+ivmP2lnm/HOWF6SDI5Rqwj4g+4sUiJcPpPELGoyQ1SjF36i+fcavn2D9hp9c4Wc3yCJZA+LgHoaPaPqKVlP88BRvd8DSFlle4P07WM+hWsJXCXIgIjfCz5OzCVQLyAu808Ptk1C+A47onXtTIbWw7gXEDWHzQajKbY+O+95UyCJYQm7Abr5vonZV760IjhkAAAAASUVORK5CYII="/> -<image id="image2_1835_8259" width="4" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAFCAYAAABirU3bAAAABHNCSVQICAgIfAhkiAAAAEVJREFUCJljlFHV+M+ABFjY2FkYUAXYWBg8XFwZPnz8yHDi9CkGRj1Lk/+srKwMf//+Zfj37x9EBQPDfwYWFiYGBgYmBgAtwhBN2erPwAAAAABJRU5ErkJggg=="/> -<image id="image3_1835_8259" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABHNCSVQICAgIfAhkiAAAAGJJREFUCJk1wbEKglAAheH/yE0rp8A18A1samxpa+4BfNMew7EHEBPkgiBeT5PfJzWtNXT4XGES4fshMPewTCADK/JGRl7i04X368HzVgNGut7NGjkuPxxHUkooHArLG2B2f3kOIpEJnXBlAAAAAElFTkSuQmCC"/> -</defs> -</svg> diff --git a/client/src/assets/image/addMemberMockup.svg b/client/src/assets/image/addMemberMockup.svg deleted file mode 100644 index 1bf5892d3..000000000 --- a/client/src/assets/image/addMemberMockup.svg +++ /dev/null @@ -1,317 +0,0 @@ -<svg width="100%" height="100%" viewBox="0 0 430 867" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<path d="M358.532 867H71.3893C33.968 867 3.6333 836.665 3.6333 799.244V348.944V282.739V265.653V199.447V170.878V136.894V67.6347C3.6333 30.2134 33.968 -0.12131 71.3893 -0.12131H358.532C395.954 -0.12131 426.288 30.2134 426.288 67.6347V799.244C426.288 836.665 395.954 867 358.532 867ZM71.9202 1.8971C35.3203 1.8971 5.65171 31.5657 5.65171 68.1655V798.713C5.65171 835.312 35.3203 864.982 71.9202 864.982H358.001C394.601 864.982 424.27 835.312 424.27 798.713V68.1655C424.27 31.5657 394.601 1.8971 358.001 1.8971H71.9202ZM357.471 862.963H72.451C36.6727 862.963 7.67012 833.96 7.67012 798.182V68.6964C7.67012 32.9181 36.6727 3.91551 72.451 3.91551H357.471C393.247 3.91551 422.251 32.9181 422.251 68.6964V798.182C422.251 833.96 393.247 862.963 357.471 862.963ZM73.0908 6.49706C38.683 6.49706 10.7906 34.3895 10.7906 68.7973V798.081C10.7906 832.489 38.683 860.381 73.0908 860.381H356.831C391.239 860.381 419.131 832.489 419.131 798.081V68.7973C419.131 34.3895 391.239 6.49706 356.831 6.49706H73.0908Z" fill="#5E465D"/> -<path d="M358.001 864.981H71.9193C35.3195 864.981 5.65088 835.312 5.65088 798.713V68.1653C5.65088 31.5655 35.3195 1.89689 71.9193 1.89689H358.001C394.6 1.89689 424.269 31.5655 424.269 68.1653V798.713C424.269 835.312 394.6 864.981 358.001 864.981ZM72.4502 3.9153C36.6718 3.9153 7.66929 32.9179 7.66929 68.6962V798.181C7.66929 833.96 36.6718 862.963 72.4502 862.963H357.47C393.246 862.963 422.251 833.96 422.251 798.181V68.6962C422.251 32.9179 393.246 3.9153 357.47 3.9153H72.4502Z" fill="#A597A4"/> -<path d="M356.831 860.381H73.0908C38.6829 860.381 10.7905 832.489 10.7905 798.08V68.7972C10.7905 34.3893 38.6829 6.49689 73.0908 6.49689H356.831C391.239 6.49689 419.131 34.3893 419.131 68.7972V798.08C419.131 832.489 391.239 860.381 356.831 860.381ZM72.7739 20.3169C45.9593 20.3169 24.223 42.0552 24.223 68.8698V798.008C24.223 824.823 45.9593 846.561 72.7759 846.561H357.146C383.962 846.561 405.698 824.823 405.698 798.008V68.8698C405.698 42.0552 383.962 20.3169 357.146 20.3169H324.147H105.383C94.1145 20.3169 83.421 20.3169 72.7739 20.3169Z" fill="#1D1D1B"/> -<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> -<mask id="mask0_1837_9941" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> -<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> -</mask> -<g mask="url(#mask0_1837_9941)"> -<g clip-path="url(#clip0_1837_9941)"> -<mask id="mask1_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> -<path d="M406 20H24V847H406V20Z" fill="white"/> -</mask> -<g mask="url(#mask1_1837_9941)"> -<path d="M406 20H24V847H406V20Z" fill="#F1F0F5"/> -<path d="M51.8437 93.2812H41.9297V89.1094H51.8437V93.2812ZM43.8906 91.7892H49.8906V90.5937H43.8906V91.7892ZM52.7109 81.7267H41.0391V80.2345H52.7109V81.7267ZM46.9062 82.1017C48.4583 82.1017 49.6406 82.2734 50.4531 82.6172C51.2708 82.9557 51.6797 83.4583 51.6797 84.125C51.6797 84.7917 51.2708 85.297 50.4531 85.6407C49.6406 85.9845 48.4583 86.1562 46.9062 86.1562C45.3594 86.1562 44.1745 85.9845 43.3516 85.6407C42.5286 85.297 42.1172 84.7917 42.1172 84.125C42.1172 83.4583 42.5286 82.9557 43.3516 82.6172C44.1745 82.2734 45.3594 82.1017 46.9062 82.1017ZM46.9062 83.4375C46.2708 83.4375 45.7656 83.461 45.3906 83.5079C45.0156 83.5548 44.7318 83.6277 44.5391 83.7267C44.3464 83.8256 44.25 83.9583 44.25 84.125C44.25 84.2865 44.3464 84.4168 44.5391 84.5157C44.7318 84.6147 45.0208 84.6902 45.4062 84.7423C45.7917 84.7944 46.2917 84.8203 46.9062 84.8203C47.5312 84.8203 48.0339 84.7944 48.4141 84.7423C48.7995 84.6902 49.0859 84.6147 49.2734 84.5157C49.4609 84.4168 49.5547 84.2865 49.5547 84.125C49.5547 83.9583 49.4609 83.8256 49.2734 83.7267C49.0859 83.6277 48.8047 83.5548 48.4297 83.5079C48.0547 83.461 47.5469 83.4375 46.9062 83.4375ZM47.8984 81.3047H45.8984V79.0938H47.8984V81.3047ZM53.3984 88.3907H40.4297V86.8359H53.3984V88.3907ZM47.8984 87.6798H45.8984V85.6484H47.8984V87.6798Z" fill="#B2B1B6"/> -<path d="M73.2187 81.875H67.0781V80.25H73.2187V81.875ZM70.8594 87.1094H68.875V83.5312H70.8594V87.1094ZM74.3984 81.2344C74.3932 81.9687 74.3724 82.6458 74.3359 83.2656C74.2995 83.8854 74.2135 84.5651 74.0781 85.3047L72.1094 85.1328C72.25 84.388 72.3385 83.737 72.375 83.1797C72.4167 82.6224 72.4427 81.9818 72.4531 81.2578V81.1328V80.25H74.3984V81.1328V81.2344ZM77.875 89.8516H75.8281V79.2031H77.875V89.8516ZM79.6016 85.2187H77.0703V83.5547H79.6016V85.2187ZM78.3203 93.1953H68.3281V91.5859H78.3203V93.1953ZM70.3281 92.0937H68.3281V88.9062H70.3281V92.0937ZM66.2344 86.3437C67.9375 86.3437 69.513 86.3151 70.9609 86.2578C72.4141 86.2005 73.7839 86.0781 75.0703 85.8906L75.1641 87.3281C73.8464 87.5729 72.4635 87.7344 71.0156 87.8125C69.5677 87.8906 68.0312 87.9297 66.4062 87.9297L66.2344 86.3437ZM92.1719 93.4766H90.1797V79.2031H92.1719V93.4766ZM82.2891 88.5C83.6276 88.5104 84.8281 88.4818 85.8906 88.4141C86.9583 88.3411 88.0495 88.2135 89.1641 88.0312L89.3437 89.6406C88.2448 89.8333 87.1484 89.9661 86.0547 90.0391C84.9661 90.1068 83.7109 90.1406 82.2891 90.1406H81.0156V88.5H82.2891ZM87.7578 85.8828H83.0703V89.125H81.0156V84.3203H85.7266V82.0156H81V80.4062H87.7578V85.8828Z" fill="#56555A"/> -<path d="M406 114H24V270H406V114Z" fill="white"/> -<path d="M60.9609 151.188H58.1133V137.805H60.9609V151.188ZM58.875 145.551H55.3828V143.113H58.875V145.551ZM56.4141 150.496H53.625V138.215H56.4141V150.496ZM52.9922 142.34H42.5273V140.008H52.9922V142.34ZM47.7891 143.066C48.6875 143.066 49.4883 143.219 50.1914 143.523C50.9023 143.828 51.457 144.266 51.8555 144.836C52.2539 145.398 52.4531 146.051 52.4531 146.793C52.4531 147.512 52.2539 148.152 51.8555 148.715C51.457 149.27 50.9023 149.703 50.1914 150.016C49.4883 150.32 48.6875 150.473 47.7891 150.473C46.9062 150.473 46.1133 150.32 45.4102 150.016C44.7148 149.703 44.168 149.27 43.7695 148.715C43.3711 148.152 43.1719 147.512 43.1719 146.793C43.1719 146.051 43.3711 145.398 43.7695 144.836C44.168 144.266 44.7148 143.828 45.4102 143.523C46.1133 143.219 46.9062 143.066 47.7891 143.066ZM47.7891 145.211C47.4062 145.203 47.0664 145.262 46.7695 145.387C46.4805 145.512 46.2539 145.695 46.0898 145.938C45.9258 146.18 45.8438 146.465 45.8438 146.793C45.8438 147.113 45.9219 147.391 46.0781 147.625C46.2422 147.859 46.4688 148.043 46.7578 148.176C47.0547 148.301 47.3984 148.363 47.7891 148.363C48.1797 148.363 48.5234 148.301 48.8203 148.176C49.1172 148.043 49.3477 147.859 49.5117 147.625C49.6758 147.391 49.7578 147.113 49.7578 146.793C49.7578 146.465 49.6758 146.18 49.5117 145.938C49.3477 145.695 49.1172 145.512 48.8203 145.387C48.5234 145.262 48.1797 145.203 47.7891 145.211ZM49.2656 141.625H46.2773V138.016H49.2656V141.625ZM53.6719 151.41C55.2031 151.41 56.5234 151.562 57.6328 151.867C58.7422 152.164 59.5898 152.605 60.1758 153.191C60.7695 153.777 61.0664 154.477 61.0664 155.289C61.0664 156.109 60.7695 156.805 60.1758 157.375C59.5898 157.953 58.7422 158.395 57.6328 158.699C56.5234 159.004 55.2031 159.156 53.6719 159.156C52.1484 159.156 50.832 159.004 49.7227 158.699C48.6211 158.395 47.7734 157.953 47.1797 157.375C46.5859 156.805 46.2891 156.109 46.2891 155.289C46.2891 154.477 46.5859 153.777 47.1797 153.191C47.7734 152.605 48.6211 152.164 49.7227 151.867C50.832 151.562 52.1484 151.41 53.6719 151.41ZM53.6719 153.648C52.6953 153.641 51.8828 153.695 51.2344 153.812C50.5938 153.93 50.1055 154.113 49.7695 154.363C49.4414 154.613 49.2812 154.922 49.2891 155.289C49.2812 155.641 49.4414 155.938 49.7695 156.18C50.1055 156.414 50.5977 156.594 51.2461 156.719C51.8945 156.844 52.7031 156.906 53.6719 156.906C54.6406 156.906 55.4492 156.844 56.0977 156.719C56.7539 156.594 57.2422 156.414 57.5625 156.18C57.8906 155.945 58.0586 155.648 58.0664 155.289C58.0586 154.914 57.8906 154.605 57.5625 154.363C57.2422 154.113 56.7578 153.93 56.1094 153.812C55.4609 153.695 54.6484 153.641 53.6719 153.648ZM82.875 150.262H63.3867V147.895H82.875V150.262ZM74.5898 148.832H71.6602V144.684H74.5898V148.832ZM80.6484 146.066H65.7422V143.723H80.6484V146.066ZM80.5312 141.098H68.707V145.258H65.7422V138.766H80.5312V141.098ZM73.0781 151.316C74.6172 151.316 75.9414 151.473 77.0508 151.785C78.1602 152.09 79.0117 152.539 79.6055 153.133C80.1992 153.719 80.5 154.43 80.5078 155.266C80.5 156.094 80.1992 156.797 79.6055 157.375C79.0195 157.961 78.168 158.406 77.0508 158.711C75.9414 159.023 74.6172 159.184 73.0781 159.191C71.5234 159.184 70.1875 159.023 69.0703 158.711C67.9531 158.406 67.0938 157.961 66.4922 157.375C65.8984 156.789 65.6016 156.086 65.6016 155.266C65.6016 154.43 65.8984 153.719 66.4922 153.133C67.0938 152.539 67.9531 152.09 69.0703 151.785C70.1875 151.473 71.5234 151.316 73.0781 151.316ZM73.0781 153.602C72.0859 153.602 71.2617 153.664 70.6055 153.789C69.957 153.906 69.4648 154.09 69.1289 154.34C68.8008 154.59 68.6406 154.898 68.6484 155.266C68.6406 155.641 68.8008 155.949 69.1289 156.191C69.4648 156.434 69.957 156.613 70.6055 156.73C71.2617 156.848 72.0859 156.906 73.0781 156.906C74.0547 156.906 74.8672 156.848 75.5156 156.73C76.1719 156.613 76.6641 156.434 76.9922 156.191C77.3281 155.949 77.4961 155.641 77.4961 155.266C77.4961 154.906 77.3281 154.602 76.9922 154.352C76.6641 154.094 76.1719 153.906 75.5156 153.789C74.8594 153.664 74.0469 153.602 73.0781 153.602ZM102.551 159.156H99.7383V137.805H102.551V159.156ZM100.418 148.457H96.7969V146.066H100.418V148.457ZM97.6758 158.125H94.9336V138.191H97.6758V158.125ZM86.2148 151.832C87.7773 151.832 89.1172 151.797 90.2344 151.727C91.3516 151.656 92.5 151.516 93.6797 151.305L93.8906 153.73C92.7031 153.965 91.5352 154.121 90.3867 154.199C89.2461 154.27 87.8555 154.312 86.2148 154.328H84.7148V151.832H86.2148ZM92.6836 142.703H87.7148V153.039H84.7148V140.301H92.6836V142.703ZM112.16 141.59C112.152 142.98 111.926 144.277 111.481 145.48C111.035 146.676 110.352 147.719 109.43 148.609C108.516 149.5 107.391 150.16 106.055 150.59L104.555 148.234C105.695 147.867 106.652 147.34 107.426 146.652C108.199 145.957 108.77 145.176 109.137 144.309C109.512 143.441 109.703 142.535 109.711 141.59V140.195H112.16V141.59ZM112.734 141.578C112.734 142.445 112.91 143.27 113.262 144.051C113.613 144.824 114.156 145.52 114.891 146.137C115.625 146.746 116.543 147.215 117.645 147.543L116.238 149.875C114.926 149.484 113.828 148.879 112.945 148.059C112.063 147.23 111.398 146.266 110.953 145.164C110.516 144.055 110.297 142.859 110.297 141.578V140.195H112.734V141.578ZM116.988 141.637H105.363V139.246H116.988V141.637ZM121.781 150.473H118.793V137.805H121.781V150.473ZM124.664 145.211H120.938V142.773H124.664V145.211ZM114.785 150.895C116.262 150.895 117.539 151.059 118.617 151.387C119.703 151.707 120.535 152.176 121.113 152.793C121.691 153.41 121.981 154.148 121.981 155.008C121.981 155.867 121.691 156.605 121.113 157.223C120.535 157.848 119.703 158.324 118.617 158.652C117.539 158.988 116.262 159.156 114.785 159.156C113.293 159.156 111.996 158.988 110.895 158.652C109.793 158.324 108.945 157.848 108.352 157.223C107.766 156.605 107.473 155.867 107.473 155.008C107.473 154.148 107.766 153.41 108.352 152.793C108.945 152.176 109.789 151.707 110.883 151.387C111.984 151.059 113.285 150.895 114.785 150.895ZM114.785 153.215C113.856 153.215 113.066 153.281 112.418 153.414C111.777 153.547 111.293 153.75 110.965 154.023C110.637 154.289 110.477 154.617 110.484 155.008C110.477 155.414 110.637 155.754 110.965 156.027C111.293 156.293 111.777 156.496 112.418 156.637C113.059 156.77 113.848 156.836 114.785 156.836C115.715 156.836 116.492 156.77 117.117 156.637C117.75 156.496 118.227 156.293 118.547 156.027C118.875 155.754 119.039 155.414 119.039 155.008C119.039 154.609 118.875 154.277 118.547 154.012C118.227 153.746 117.75 153.547 117.117 153.414C116.492 153.281 115.715 153.215 114.785 153.215ZM136.91 139.316C137.988 139.316 138.949 139.629 139.793 140.254C140.645 140.871 141.312 141.758 141.797 142.914C142.281 144.062 142.527 145.398 142.535 146.922C142.527 148.453 142.281 149.797 141.797 150.953C141.312 152.102 140.645 152.984 139.793 153.602C138.949 154.219 137.988 154.527 136.91 154.527C135.816 154.527 134.844 154.219 133.992 153.602C133.141 152.984 132.473 152.102 131.988 150.953C131.512 149.797 131.273 148.453 131.273 146.922C131.273 145.398 131.512 144.062 131.988 142.914C132.473 141.758 133.141 140.871 133.992 140.254C134.844 139.629 135.816 139.316 136.91 139.316ZM136.91 142.023C136.363 142.016 135.883 142.203 135.469 142.586C135.055 142.969 134.73 143.527 134.496 144.262C134.27 144.996 134.156 145.883 134.156 146.922C134.156 147.961 134.27 148.848 134.496 149.582C134.73 150.316 135.055 150.875 135.469 151.258C135.883 151.633 136.363 151.82 136.91 151.82C137.465 151.82 137.949 151.633 138.363 151.258C138.777 150.875 139.094 150.316 139.312 149.582C139.539 148.848 139.652 147.961 139.652 146.922C139.652 145.883 139.539 144.996 139.312 144.262C139.094 143.52 138.777 142.961 138.363 142.586C137.949 142.203 137.465 142.016 136.91 142.023ZM150.996 145.281H147.176V142.785H150.996V145.281ZM150.996 151.504H147.176V149.078H150.996V151.504ZM147.984 159.156H144.984V137.805H147.984V159.156ZM159.41 159.156H156.34V151.27H159.41V159.156ZM166.816 159.156H163.781V151.27H166.816V159.156ZM171.387 152.102H151.887V149.688H171.387V152.102ZM161.578 138.531C163.094 138.531 164.441 138.73 165.621 139.129C166.801 139.527 167.715 140.09 168.363 140.816C169.02 141.543 169.348 142.387 169.348 143.348C169.348 144.293 169.02 145.121 168.363 145.832C167.715 146.535 166.801 147.082 165.621 147.473C164.441 147.863 163.094 148.059 161.578 148.059C160.062 148.059 158.719 147.863 157.547 147.473C156.375 147.082 155.461 146.535 154.805 145.832C154.156 145.121 153.832 144.293 153.832 143.348C153.832 142.387 154.156 141.543 154.805 140.816C155.461 140.09 156.375 139.527 157.547 139.129C158.719 138.73 160.062 138.531 161.578 138.531ZM161.578 140.922C160.617 140.93 159.785 141.027 159.082 141.215C158.387 141.395 157.852 141.668 157.477 142.035C157.102 142.395 156.918 142.832 156.926 143.348C156.918 143.84 157.102 144.262 157.477 144.613C157.852 144.965 158.387 145.234 159.082 145.422C159.785 145.602 160.617 145.691 161.578 145.691C162.539 145.691 163.371 145.602 164.074 145.422C164.777 145.234 165.316 144.969 165.691 144.625C166.074 144.273 166.266 143.848 166.266 143.348C166.266 142.832 166.074 142.395 165.691 142.035C165.316 141.668 164.777 141.395 164.074 141.215C163.379 141.027 162.547 140.93 161.578 140.922ZM181.137 154.258H178.16V150.777H181.137V154.258ZM190.559 159.156H187.594V137.805H190.559V159.156ZM173.578 153.133C176.234 153.117 178.57 153.074 180.586 153.004C182.609 152.926 184.555 152.762 186.422 152.512L186.609 154.727C184.547 155.086 182.426 155.32 180.246 155.43C178.066 155.531 175.695 155.582 173.133 155.582L172.734 153.133H173.578ZM186.117 142.551H173.156V140.207H186.117V142.551ZM179.625 143.395C180.672 143.395 181.602 143.562 182.414 143.898C183.234 144.227 183.867 144.695 184.312 145.305C184.766 145.914 184.992 146.613 184.992 147.402C184.992 148.184 184.766 148.879 184.312 149.488C183.867 150.09 183.234 150.559 182.414 150.895C181.602 151.23 180.672 151.398 179.625 151.398C178.594 151.398 177.676 151.23 176.871 150.895C176.066 150.559 175.438 150.09 174.984 149.488C174.539 148.879 174.316 148.184 174.316 147.402C174.316 146.613 174.539 145.914 174.984 145.305C175.438 144.695 176.066 144.227 176.871 143.898C177.676 143.562 178.594 143.395 179.625 143.395ZM179.625 145.656C179.141 145.656 178.711 145.727 178.336 145.867C177.969 146 177.68 146.199 177.469 146.465C177.258 146.73 177.152 147.043 177.152 147.402C177.152 147.77 177.254 148.082 177.457 148.34C177.668 148.59 177.961 148.785 178.336 148.926C178.711 149.059 179.141 149.125 179.625 149.125C180.125 149.125 180.566 149.059 180.949 148.926C181.332 148.785 181.625 148.59 181.828 148.34C182.031 148.082 182.133 147.77 182.133 147.402C182.133 147.043 182.031 146.73 181.828 146.465C181.625 146.199 181.332 146 180.949 145.867C180.566 145.727 180.125 145.656 179.625 145.656ZM181.16 141.543H178.16V137.91H181.16V141.543Z" fill="#56555A"/> -<path d="M47.3125 183.641C47.3125 184.599 47.1302 185.544 46.7656 186.477C46.401 187.409 45.9115 188.237 45.2969 188.961C44.6875 189.685 44.0208 190.229 43.2969 190.594L42.5625 189.625C43.224 189.307 43.8385 188.828 44.4062 188.188C44.9792 187.542 45.4375 186.818 45.7812 186.016C46.125 185.214 46.2969 184.422 46.2969 183.641V181.344H47.3125V183.641ZM47.5312 183.641C47.5312 184.406 47.7031 185.169 48.0469 185.93C48.3906 186.685 48.849 187.359 49.4219 187.953C49.9948 188.547 50.6198 188.99 51.2969 189.281L50.6094 190.25C49.8542 189.906 49.1667 189.396 48.5469 188.719C47.9323 188.042 47.4427 187.263 47.0781 186.383C46.7188 185.497 46.5417 184.583 46.5469 183.641V181.344H47.5312V183.641ZM50.8438 181.828H43.0156V180.812H50.8438V181.828ZM54.0156 193.266H52.7812V179.375H54.0156V193.266ZM63.3125 188.391H62.1094V186.281H63.3125V188.391ZM69.0469 186.516H56.4062V185.562H69.0469V186.516ZM63.3125 180.984H62.1094V179.297H63.3125V180.984ZM63.125 181.312C63.125 182.016 62.8698 182.625 62.3594 183.141C61.849 183.651 61.1641 184.055 60.3047 184.352C59.4505 184.643 58.4948 184.833 57.4375 184.922L57.0781 183.984C57.9948 183.927 58.8307 183.784 59.5859 183.555C60.3411 183.32 60.9401 183.013 61.3828 182.633C61.8255 182.247 62.0469 181.807 62.0469 181.312V181.109H63.125V181.312ZM63.3906 181.312C63.3854 181.807 63.6042 182.247 64.0469 182.633C64.4948 183.013 65.0938 183.32 65.8438 183.555C66.599 183.784 67.4375 183.927 68.3594 183.984L67.9844 184.922C66.9323 184.833 65.9792 184.643 65.125 184.352C64.2708 184.055 63.5885 183.651 63.0781 183.141C62.5677 182.625 62.3125 182.016 62.3125 181.312V181.109H63.3906V181.312ZM67.7656 181.562H57.7031V180.594H67.7656V181.562ZM67.4219 190.812H59.1719V192.516H57.9531V189.938H66.2188V188.734H57.9219V187.812H67.4219V190.812ZM67.8438 193.109H57.9531V192.172H67.8438V193.109ZM86.0938 193.266H84.8906V179.375H86.0938V193.266ZM85.25 186.078H82.5312V185.031H85.25V186.078ZM82.8906 192.547H81.7344V179.688H82.8906V192.547ZM76.1562 189.078H74.9375V181.078H76.1562V189.078ZM75.7969 188.578C76.625 188.583 77.4349 188.555 78.2266 188.492C79.0234 188.424 79.849 188.302 80.7031 188.125L80.8594 189.219C79.9427 189.385 79.0755 189.503 78.2578 189.57C77.4453 189.638 76.625 189.672 75.7969 189.672H74.9375V188.578H75.7969ZM98.7188 182.438H94.4688V181.422H98.7188V182.438ZM98.7188 185.562H94.4688V184.547H98.7188V185.562ZM99.5781 193.266H98.3438V189.312H90.2344V188.328H99.5781V193.266ZM99.5781 187.562H98.3438V179.375H99.5781V187.562ZM91.8906 180.172C92.5677 180.172 93.1797 180.312 93.7266 180.594C94.2734 180.875 94.7005 181.268 95.0078 181.773C95.3203 182.279 95.4792 182.849 95.4844 183.484C95.4792 184.135 95.3203 184.714 95.0078 185.219C94.7005 185.719 94.2734 186.112 93.7266 186.398C93.1797 186.68 92.5677 186.818 91.8906 186.812C91.2031 186.818 90.5859 186.68 90.0391 186.398C89.4922 186.112 89.0625 185.716 88.75 185.211C88.4375 184.706 88.2812 184.13 88.2812 183.484C88.2812 182.849 88.4375 182.279 88.75 181.773C89.0625 181.268 89.4922 180.875 90.0391 180.594C90.5859 180.312 91.2031 180.172 91.8906 180.172ZM91.8906 181.219C91.4219 181.219 91.0026 181.315 90.6328 181.508C90.263 181.701 89.974 181.971 89.7656 182.32C89.5573 182.664 89.4531 183.052 89.4531 183.484C89.4531 183.927 89.5573 184.323 89.7656 184.672C89.974 185.016 90.263 185.286 90.6328 185.484C91.0026 185.682 91.4219 185.781 91.8906 185.781C92.3438 185.781 92.7526 185.682 93.1172 185.484C93.487 185.286 93.776 185.016 93.9844 184.672C94.1927 184.323 94.2969 183.927 94.2969 183.484C94.2969 183.057 94.1927 182.669 93.9844 182.32C93.776 181.971 93.487 181.701 93.1172 181.508C92.7474 181.315 92.3385 181.219 91.8906 181.219ZM113.156 185.938H106.641V180.281H113.156V185.938ZM107.844 184.969H111.953V181.281H107.844V184.969ZM117.359 187.359H116.156V179.375H117.359V187.359ZM113.391 189.266C113.391 189.911 113.146 190.513 112.656 191.07C112.167 191.628 111.516 192.091 110.703 192.461C109.891 192.836 109.016 193.089 108.078 193.219L107.641 192.266C108.432 192.177 109.19 191.982 109.914 191.68C110.638 191.372 111.221 191.005 111.664 190.578C112.107 190.151 112.328 189.714 112.328 189.266V188.984H113.391V189.266ZM113.594 189.266C113.594 189.703 113.81 190.135 114.242 190.562C114.675 190.99 115.245 191.357 115.953 191.664C116.667 191.966 117.417 192.167 118.203 192.266L117.781 193.219C116.849 193.089 115.979 192.831 115.172 192.445C114.37 192.065 113.727 191.596 113.242 191.039C112.763 190.482 112.526 189.891 112.531 189.266V188.984H113.594V189.266ZM117.719 189.266H108.219V188.312H117.719V189.266ZM113.562 188.75H112.344V186.953H113.562V188.75ZM135.219 189.547H134V179.391H135.219V189.547ZM135.656 192.969H126.25V191.938H135.656V192.969ZM127.469 192.281H126.25V188.516H127.469V192.281ZM127.719 180.359C128.406 180.359 129.026 180.505 129.578 180.797C130.13 181.089 130.565 181.492 130.883 182.008C131.201 182.523 131.359 183.109 131.359 183.766C131.359 184.427 131.201 185.018 130.883 185.539C130.565 186.055 130.13 186.458 129.578 186.75C129.026 187.042 128.406 187.188 127.719 187.188C127.031 187.188 126.411 187.042 125.859 186.75C125.307 186.458 124.872 186.055 124.555 185.539C124.237 185.018 124.078 184.427 124.078 183.766C124.078 183.109 124.237 182.523 124.555 182.008C124.872 181.492 125.307 181.089 125.859 180.797C126.411 180.505 127.031 180.359 127.719 180.359ZM127.719 181.438C127.255 181.438 126.836 181.536 126.461 181.734C126.091 181.932 125.799 182.208 125.586 182.562C125.378 182.917 125.276 183.318 125.281 183.766C125.276 184.219 125.378 184.625 125.586 184.984C125.799 185.339 126.091 185.615 126.461 185.812C126.836 186.01 127.255 186.109 127.719 186.109C128.177 186.109 128.591 186.01 128.961 185.812C129.331 185.615 129.622 185.339 129.836 184.984C130.049 184.625 130.156 184.219 130.156 183.766C130.156 183.318 130.049 182.917 129.836 182.562C129.622 182.208 129.331 181.932 128.961 181.734C128.591 181.536 128.177 181.438 127.719 181.438ZM142.812 189.453H141.578V186.359H142.812V189.453ZM149.031 189.938H147.797V179.391H149.031V189.938ZM149.375 192.969H139.5V191.938H149.375V192.969ZM140.734 192.234H139.5V188.906H140.734V192.234ZM137.5 185.828C139.359 185.818 141.005 185.789 142.438 185.742C143.87 185.69 145.24 185.583 146.547 185.422L146.625 186.312C145.276 186.526 143.862 186.667 142.383 186.734C140.904 186.802 139.333 186.833 137.672 186.828L137.5 185.828ZM148.125 188.5H144.922V187.609H148.125V188.5ZM142.062 179.953C142.734 179.953 143.331 180.052 143.852 180.25C144.378 180.448 144.784 180.732 145.07 181.102C145.357 181.471 145.5 181.896 145.5 182.375C145.5 182.865 145.357 183.289 145.07 183.648C144.784 184.008 144.38 184.286 143.859 184.484C143.339 184.682 142.74 184.781 142.062 184.781C141.38 184.781 140.779 184.682 140.258 184.484C139.742 184.286 139.341 184.008 139.055 183.648C138.768 183.289 138.625 182.865 138.625 182.375C138.625 181.896 138.768 181.471 139.055 181.102C139.341 180.732 139.745 180.448 140.266 180.25C140.786 180.052 141.385 179.953 142.062 179.953ZM142.062 180.891C141.615 180.885 141.219 180.945 140.875 181.07C140.531 181.19 140.263 181.365 140.07 181.594C139.883 181.823 139.792 182.083 139.797 182.375C139.792 182.672 139.883 182.935 140.07 183.164C140.263 183.388 140.531 183.562 140.875 183.688C141.219 183.812 141.615 183.875 142.062 183.875C142.5 183.875 142.891 183.812 143.234 183.688C143.578 183.562 143.846 183.388 144.039 183.164C144.232 182.935 144.328 182.672 144.328 182.375C144.328 182.083 144.232 181.823 144.039 181.594C143.846 181.365 143.578 181.19 143.234 181.07C142.891 180.945 142.5 180.885 142.062 180.891ZM166.156 182.969H162.109V181.938H166.156V182.969ZM166.203 185.938H162.109V184.922H166.203V185.938ZM166.938 189.672H165.703V179.391H166.938V189.672ZM167.25 192.969H157.953V191.938H167.25V192.969ZM159.188 192.438H157.953V188.656H159.188V192.438ZM157.344 182.781H161.219V180.312H162.422V187.297H156.125V180.312H157.344V182.781ZM161.219 186.281V183.75H157.344V186.281H161.219ZM181.922 187.234H169.25V186.25H181.922V187.234ZM176.172 186.672H174.984V184.016H176.172V186.672ZM180.438 184.625H170.859V183.625H180.438V184.625ZM180.344 181.016H172.062V184.234H170.859V180.031H180.344V181.016ZM175.578 188.25C176.568 188.25 177.419 188.349 178.133 188.547C178.846 188.745 179.393 189.031 179.773 189.406C180.159 189.776 180.354 190.224 180.359 190.75C180.354 191.281 180.161 191.732 179.781 192.102C179.406 192.471 178.859 192.755 178.141 192.953C177.422 193.156 176.568 193.26 175.578 193.266C174.578 193.26 173.719 193.156 173 192.953C172.281 192.755 171.732 192.469 171.352 192.094C170.971 191.724 170.781 191.276 170.781 190.75C170.781 190.224 170.971 189.776 171.352 189.406C171.732 189.031 172.281 188.745 173 188.547C173.719 188.349 174.578 188.25 175.578 188.25ZM175.578 189.219C174.839 189.219 174.203 189.279 173.672 189.398C173.141 189.518 172.732 189.695 172.445 189.93C172.164 190.159 172.026 190.432 172.031 190.75C172.026 191.073 172.164 191.349 172.445 191.578C172.732 191.807 173.141 191.982 173.672 192.102C174.203 192.221 174.839 192.281 175.578 192.281C176.307 192.281 176.938 192.221 177.469 192.102C178 191.982 178.409 191.807 178.695 191.578C178.982 191.349 179.125 191.073 179.125 190.75C179.125 190.432 178.982 190.159 178.695 189.93C178.409 189.695 178 189.518 177.469 189.398C176.938 189.279 176.307 189.219 175.578 189.219ZM189.406 179.625C190.432 179.625 191.312 179.716 192.047 179.898C192.786 180.081 193.349 180.352 193.734 180.711C194.12 181.07 194.312 181.505 194.312 182.016C194.312 182.536 194.12 182.979 193.734 183.344C193.349 183.708 192.789 183.984 192.055 184.172C191.32 184.354 190.438 184.448 189.406 184.453C188.37 184.448 187.484 184.354 186.75 184.172C186.021 183.984 185.461 183.708 185.07 183.344C184.68 182.979 184.484 182.536 184.484 182.016C184.484 181.505 184.68 181.07 185.07 180.711C185.461 180.352 186.023 180.081 186.758 179.898C187.492 179.716 188.375 179.625 189.406 179.625ZM189.406 180.547C188.641 180.547 187.984 180.607 187.438 180.727C186.896 180.846 186.479 181.016 186.188 181.234C185.901 181.453 185.76 181.714 185.766 182.016C185.76 182.333 185.901 182.607 186.188 182.836C186.479 183.06 186.896 183.229 187.438 183.344C187.984 183.458 188.641 183.516 189.406 183.516C190.172 183.516 190.828 183.458 191.375 183.344C191.927 183.229 192.346 183.06 192.633 182.836C192.919 182.612 193.062 182.339 193.062 182.016C193.062 181.714 192.919 181.453 192.633 181.234C192.346 181.016 191.927 180.846 191.375 180.727C190.823 180.607 190.167 180.547 189.406 180.547ZM195.734 186.391H183.078V185.391H195.734V186.391ZM194.109 190.703H185.859V192.391H184.641V189.797H192.906V188.531H184.609V187.594H194.109V190.703ZM194.531 193.109H184.641V192.141H194.531V193.109ZM207.844 193.297H206.641V188.188H207.844V193.297ZM213.578 188.812H200.922V187.781H213.578V188.812ZM207.719 182.125C207.719 182.896 207.461 183.602 206.945 184.242C206.43 184.883 205.747 185.417 204.898 185.844C204.055 186.266 203.146 186.552 202.172 186.703L201.719 185.719C202.552 185.604 203.346 185.37 204.102 185.016C204.857 184.661 205.469 184.232 205.938 183.727C206.406 183.221 206.641 182.688 206.641 182.125V181.75H207.719V182.125ZM207.859 182.125C207.859 182.682 208.091 183.216 208.555 183.727C209.018 184.232 209.628 184.661 210.383 185.016C211.138 185.37 211.932 185.604 212.766 185.719L212.312 186.703C211.339 186.557 210.43 186.268 209.586 185.836C208.747 185.404 208.073 184.867 207.562 184.227C207.052 183.581 206.797 182.88 206.797 182.125V181.75H207.859V182.125ZM212.359 182.109H202.156V181.109H212.359V182.109ZM207.844 181.453H206.641V179.375H207.844V181.453ZM225.5 193.266H224.281V179.375H225.5V193.266ZM227.75 186.062H225.188V185.031H227.75V186.062ZM221.906 180.875C221.901 182.224 221.677 183.5 221.234 184.703C220.797 185.901 220.104 187.008 219.156 188.023C218.208 189.034 217 189.901 215.531 190.625L214.844 189.656C216.13 189.016 217.208 188.263 218.078 187.398C218.953 186.529 219.607 185.565 220.039 184.508C220.477 183.451 220.698 182.307 220.703 181.078V180.875H221.906ZM221.328 181.906H215.484V180.875H221.328V181.906ZM235.516 182.781H228.547V181.781H235.516V182.781ZM232.031 183.719C232.609 183.719 233.125 183.854 233.578 184.125C234.036 184.396 234.393 184.771 234.648 185.25C234.909 185.724 235.042 186.266 235.047 186.875C235.042 187.49 234.909 188.036 234.648 188.516C234.393 188.995 234.036 189.372 233.578 189.648C233.125 189.924 232.609 190.062 232.031 190.062C231.464 190.062 230.951 189.924 230.492 189.648C230.039 189.372 229.685 188.995 229.43 188.516C229.174 188.036 229.047 187.49 229.047 186.875C229.047 186.271 229.177 185.729 229.438 185.25C229.698 184.771 230.052 184.396 230.5 184.125C230.953 183.854 231.464 183.719 232.031 183.719ZM232.031 184.75C231.667 184.755 231.341 184.852 231.055 185.039C230.768 185.221 230.544 185.474 230.383 185.797C230.221 186.115 230.141 186.474 230.141 186.875C230.141 187.281 230.221 187.643 230.383 187.961C230.544 188.279 230.768 188.529 231.055 188.711C231.341 188.893 231.667 188.984 232.031 188.984C232.396 188.984 232.724 188.893 233.016 188.711C233.307 188.529 233.536 188.279 233.703 187.961C233.87 187.643 233.953 187.281 233.953 186.875C233.953 186.474 233.87 186.115 233.703 185.797C233.536 185.474 233.307 185.221 233.016 185.039C232.724 184.852 232.396 184.755 232.031 184.75ZM240.406 193.266H239.234V179.375H240.406V193.266ZM239.625 186.25H236.969V185.234H239.625V186.25ZM237.391 192.578H236.234V179.719H237.391V192.578ZM232.656 182.391H231.438V179.797H232.656V182.391ZM253.141 181.344C253.141 182.141 252.883 182.872 252.367 183.539C251.852 184.201 251.174 184.755 250.336 185.203C249.497 185.646 248.604 185.948 247.656 186.109L247.172 185.141C247.99 185.021 248.773 184.776 249.523 184.406C250.279 184.031 250.891 183.576 251.359 183.039C251.828 182.503 252.062 181.938 252.062 181.344V180.75H253.141V181.344ZM253.438 181.344C253.438 181.938 253.672 182.503 254.141 183.039C254.609 183.576 255.219 184.031 255.969 184.406C256.724 184.776 257.51 185.021 258.328 185.141L257.875 186.109C256.917 185.948 256.018 185.646 255.18 185.203C254.341 184.755 253.664 184.201 253.148 183.539C252.633 182.872 252.375 182.141 252.375 181.344V180.75H253.438V181.344ZM253.328 193.266H252.125V187.953H253.328V193.266ZM259.078 188.312H246.422V187.297H259.078V188.312ZM257.875 181.25H247.609V180.25H257.875V181.25ZM268.5 185.406H265.766V184.359H268.5V185.406ZM264.156 183.375C264.156 184.328 264.023 185.258 263.758 186.164C263.492 187.065 263.109 187.875 262.609 188.594C262.115 189.307 261.536 189.865 260.875 190.266L260.094 189.344C260.719 188.979 261.266 188.479 261.734 187.844C262.203 187.208 262.562 186.505 262.812 185.734C263.062 184.958 263.188 184.172 263.188 183.375V180.688H264.156V183.375ZM264.375 183.328C264.375 184.073 264.492 184.815 264.727 185.555C264.961 186.289 265.297 186.961 265.734 187.57C266.177 188.18 266.698 188.661 267.297 189.016L266.594 189.969C265.938 189.573 265.37 189.023 264.891 188.32C264.411 187.617 264.047 186.833 263.797 185.969C263.552 185.104 263.432 184.224 263.438 183.328V180.688H264.375V183.328ZM272.156 193.266H270.969V179.375H272.156V193.266ZM269.281 192.562H268.125V179.672H269.281V192.562ZM278.438 190.703H277.234V186.547H278.438V190.703ZM283.641 190.703H282.406V186.547H283.641V190.703ZM286.797 191.484H274.078V190.453H286.797V191.484ZM280.406 180.25C281.391 180.255 282.266 180.406 283.031 180.703C283.802 180.995 284.404 181.414 284.836 181.961C285.268 182.503 285.484 183.125 285.484 183.828C285.484 184.536 285.268 185.159 284.836 185.695C284.404 186.232 283.802 186.648 283.031 186.945C282.266 187.242 281.391 187.391 280.406 187.391C279.422 187.391 278.544 187.242 277.773 186.945C277.008 186.648 276.409 186.232 275.977 185.695C275.544 185.159 275.328 184.536 275.328 183.828C275.328 183.125 275.544 182.503 275.977 181.961C276.409 181.414 277.008 180.995 277.773 180.703C278.544 180.406 279.422 180.255 280.406 180.25ZM280.406 181.266C279.651 181.26 278.977 181.365 278.383 181.578C277.794 181.786 277.336 182.086 277.008 182.477C276.68 182.867 276.516 183.318 276.516 183.828C276.516 184.339 276.68 184.789 277.008 185.18C277.336 185.57 277.794 185.875 278.383 186.094C278.977 186.312 279.651 186.422 280.406 186.422C281.156 186.422 281.826 186.312 282.414 186.094C283.003 185.875 283.464 185.57 283.797 185.18C284.13 184.789 284.297 184.339 284.297 183.828C284.297 183.318 284.13 182.867 283.797 182.477C283.464 182.086 283.003 181.786 282.414 181.578C281.826 181.365 281.156 181.26 280.406 181.266ZM54.0312 213.547H52.8125V203.391H54.0312V213.547ZM54.4688 216.969H45.0625V215.938H54.4688V216.969ZM46.2812 216.281H45.0625V212.516H46.2812V216.281ZM46.5312 204.359C47.2188 204.359 47.8385 204.505 48.3906 204.797C48.9427 205.089 49.3776 205.492 49.6953 206.008C50.013 206.523 50.1719 207.109 50.1719 207.766C50.1719 208.427 50.013 209.018 49.6953 209.539C49.3776 210.055 48.9427 210.458 48.3906 210.75C47.8385 211.042 47.2188 211.188 46.5312 211.188C45.8438 211.188 45.224 211.042 44.6719 210.75C44.1198 210.458 43.6849 210.055 43.3672 209.539C43.0495 209.018 42.8906 208.427 42.8906 207.766C42.8906 207.109 43.0495 206.523 43.3672 206.008C43.6849 205.492 44.1198 205.089 44.6719 204.797C45.224 204.505 45.8438 204.359 46.5312 204.359ZM46.5312 205.438C46.0677 205.438 45.6484 205.536 45.2734 205.734C44.9036 205.932 44.612 206.208 44.3984 206.562C44.1901 206.917 44.0885 207.318 44.0938 207.766C44.0885 208.219 44.1901 208.625 44.3984 208.984C44.612 209.339 44.9036 209.615 45.2734 209.812C45.6484 210.01 46.0677 210.109 46.5312 210.109C46.9896 210.109 47.4036 210.01 47.7734 209.812C48.1432 209.615 48.4349 209.339 48.6484 208.984C48.862 208.625 48.9688 208.219 48.9688 207.766C48.9688 207.318 48.862 206.917 48.6484 206.562C48.4349 206.208 48.1432 205.932 47.7734 205.734C47.4036 205.536 46.9896 205.438 46.5312 205.438ZM61.625 213.453H60.3906V210.359H61.625V213.453ZM67.8438 213.938H66.6094V203.391H67.8438V213.938ZM68.1875 216.969H58.3125V215.938H68.1875V216.969ZM59.5469 216.234H58.3125V212.906H59.5469V216.234ZM56.3125 209.828C58.1719 209.818 59.8177 209.789 61.25 209.742C62.6823 209.69 64.0521 209.583 65.3594 209.422L65.4375 210.312C64.0885 210.526 62.6745 210.667 61.1953 210.734C59.7161 210.802 58.1458 210.833 56.4844 210.828L56.3125 209.828ZM66.9375 212.5H63.7344V211.609H66.9375V212.5ZM60.875 203.953C61.5469 203.953 62.1432 204.052 62.6641 204.25C63.1901 204.448 63.5964 204.732 63.8828 205.102C64.1693 205.471 64.3125 205.896 64.3125 206.375C64.3125 206.865 64.1693 207.289 63.8828 207.648C63.5964 208.008 63.1927 208.286 62.6719 208.484C62.151 208.682 61.5521 208.781 60.875 208.781C60.1927 208.781 59.5911 208.682 59.0703 208.484C58.5547 208.286 58.1536 208.008 57.8672 207.648C57.5807 207.289 57.4375 206.865 57.4375 206.375C57.4375 205.896 57.5807 205.471 57.8672 205.102C58.1536 204.732 58.5573 204.448 59.0781 204.25C59.599 204.052 60.1979 203.953 60.875 203.953ZM60.875 204.891C60.4271 204.885 60.0312 204.945 59.6875 205.07C59.3438 205.19 59.0755 205.365 58.8828 205.594C58.6953 205.823 58.6042 206.083 58.6094 206.375C58.6042 206.672 58.6953 206.935 58.8828 207.164C59.0755 207.388 59.3438 207.562 59.6875 207.688C60.0312 207.812 60.4271 207.875 60.875 207.875C61.3125 207.875 61.7031 207.812 62.0469 207.688C62.3906 207.562 62.6589 207.388 62.8516 207.164C63.0443 206.935 63.1406 206.672 63.1406 206.375C63.1406 206.083 63.0443 205.823 62.8516 205.594C62.6589 205.365 62.3906 205.19 62.0469 205.07C61.7031 204.945 61.3125 204.885 60.875 204.891ZM84.9688 206.969H80.9219V205.938H84.9688V206.969ZM85.0156 209.938H80.9219V208.922H85.0156V209.938ZM85.75 213.672H84.5156V203.391H85.75V213.672ZM86.0625 216.969H76.7656V215.938H86.0625V216.969ZM78 216.438H76.7656V212.656H78V216.438ZM76.1562 206.781H80.0312V204.312H81.2344V211.297H74.9375V204.312H76.1562V206.781ZM80.0312 210.281V207.75H76.1562V210.281H80.0312ZM100.734 211.234H88.0625V210.25H100.734V211.234ZM94.9844 210.672H93.7969V208.016H94.9844V210.672ZM99.25 208.625H89.6719V207.625H99.25V208.625ZM99.1562 205.016H90.875V208.234H89.6719V204.031H99.1562V205.016ZM94.3906 212.25C95.3802 212.25 96.2318 212.349 96.9453 212.547C97.6589 212.745 98.2057 213.031 98.5859 213.406C98.9714 213.776 99.1667 214.224 99.1719 214.75C99.1667 215.281 98.974 215.732 98.5938 216.102C98.2188 216.471 97.6719 216.755 96.9531 216.953C96.2344 217.156 95.3802 217.26 94.3906 217.266C93.3906 217.26 92.5312 217.156 91.8125 216.953C91.0938 216.755 90.5443 216.469 90.1641 216.094C89.7839 215.724 89.5938 215.276 89.5938 214.75C89.5938 214.224 89.7839 213.776 90.1641 213.406C90.5443 213.031 91.0938 212.745 91.8125 212.547C92.5312 212.349 93.3906 212.25 94.3906 212.25ZM94.3906 213.219C93.651 213.219 93.0156 213.279 92.4844 213.398C91.9531 213.518 91.5443 213.695 91.2578 213.93C90.9766 214.159 90.8385 214.432 90.8438 214.75C90.8385 215.073 90.9766 215.349 91.2578 215.578C91.5443 215.807 91.9531 215.982 92.4844 216.102C93.0156 216.221 93.651 216.281 94.3906 216.281C95.1198 216.281 95.75 216.221 96.2812 216.102C96.8125 215.982 97.2214 215.807 97.5078 215.578C97.7943 215.349 97.9375 215.073 97.9375 214.75C97.9375 214.432 97.7943 214.159 97.5078 213.93C97.2214 213.695 96.8125 213.518 96.2812 213.398C95.75 213.279 95.1198 213.219 94.3906 213.219ZM108.219 203.625C109.245 203.625 110.125 203.716 110.859 203.898C111.599 204.081 112.161 204.352 112.547 204.711C112.932 205.07 113.125 205.505 113.125 206.016C113.125 206.536 112.932 206.979 112.547 207.344C112.161 207.708 111.602 207.984 110.867 208.172C110.133 208.354 109.25 208.448 108.219 208.453C107.182 208.448 106.297 208.354 105.562 208.172C104.833 207.984 104.273 207.708 103.883 207.344C103.492 206.979 103.297 206.536 103.297 206.016C103.297 205.505 103.492 205.07 103.883 204.711C104.273 204.352 104.836 204.081 105.57 203.898C106.305 203.716 107.188 203.625 108.219 203.625ZM108.219 204.547C107.453 204.547 106.797 204.607 106.25 204.727C105.708 204.846 105.292 205.016 105 205.234C104.713 205.453 104.573 205.714 104.578 206.016C104.573 206.333 104.713 206.607 105 206.836C105.292 207.06 105.708 207.229 106.25 207.344C106.797 207.458 107.453 207.516 108.219 207.516C108.984 207.516 109.641 207.458 110.188 207.344C110.74 207.229 111.159 207.06 111.445 206.836C111.732 206.612 111.875 206.339 111.875 206.016C111.875 205.714 111.732 205.453 111.445 205.234C111.159 205.016 110.74 204.846 110.188 204.727C109.635 204.607 108.979 204.547 108.219 204.547ZM114.547 210.391H101.891V209.391H114.547V210.391ZM112.922 214.703H104.672V216.391H103.453V213.797H111.719V212.531H103.422V211.594H112.922V214.703ZM113.344 217.109H103.453V216.141H113.344V217.109ZM131.219 217.266H129.984V203.375H131.219V217.266ZM127.109 204.891C127.104 206.266 126.875 207.552 126.422 208.75C125.974 209.948 125.266 211.052 124.297 212.062C123.328 213.068 122.089 213.932 120.578 214.656L119.906 213.656C121.245 213.021 122.357 212.271 123.242 211.406C124.133 210.542 124.794 209.583 125.227 208.531C125.664 207.474 125.885 206.323 125.891 205.078V204.891H127.109ZM126.391 205.891H120.547V204.891H126.391V205.891ZM140.188 205.109C140.188 205.865 139.94 206.552 139.445 207.172C138.951 207.786 138.292 208.297 137.469 208.703C136.651 209.104 135.76 209.375 134.797 209.516L134.344 208.547C135.167 208.432 135.943 208.208 136.672 207.875C137.401 207.542 137.987 207.135 138.43 206.656C138.872 206.177 139.094 205.661 139.094 205.109V204.688H140.188V205.109ZM140.688 205.109C140.688 205.661 140.911 206.177 141.359 206.656C141.807 207.135 142.396 207.542 143.125 207.875C143.859 208.208 144.641 208.432 145.469 208.547L144.984 209.516C144.026 209.375 143.135 209.104 142.312 208.703C141.49 208.297 140.831 207.786 140.336 207.172C139.841 206.552 139.594 205.865 139.594 205.109V204.688H140.688V205.109ZM145.094 205.078H134.719V204.078H145.094V205.078ZM146.266 211.547H133.547V210.531H146.266V211.547ZM140.609 214.391H139.391V211.156H140.609V214.391ZM144.844 216.969H135.172V215.938H144.844V216.969ZM136.406 216.328H135.172V213H136.406V216.328ZM153.719 204.281C154.682 204.281 155.549 204.44 156.32 204.758C157.096 205.076 157.703 205.523 158.141 206.102C158.578 206.68 158.797 207.344 158.797 208.094C158.797 208.849 158.578 209.518 158.141 210.102C157.703 210.68 157.096 211.128 156.32 211.445C155.549 211.758 154.682 211.911 153.719 211.906C152.755 211.911 151.888 211.758 151.117 211.445C150.352 211.128 149.747 210.68 149.305 210.102C148.862 209.518 148.641 208.849 148.641 208.094C148.641 207.344 148.862 206.68 149.305 206.102C149.747 205.523 150.352 205.076 151.117 204.758C151.888 204.44 152.755 204.281 153.719 204.281ZM153.719 205.281C152.979 205.281 152.312 205.398 151.719 205.633C151.125 205.867 150.656 206.201 150.312 206.633C149.974 207.06 149.807 207.547 149.812 208.094C149.807 208.646 149.974 209.135 150.312 209.562C150.656 209.99 151.122 210.32 151.711 210.555C152.305 210.789 152.974 210.906 153.719 210.906C154.458 210.906 155.125 210.789 155.719 210.555C156.312 210.32 156.776 209.99 157.109 209.562C157.443 209.135 157.609 208.646 157.609 208.094C157.609 207.547 157.44 207.06 157.102 206.633C156.763 206.201 156.297 205.867 155.703 205.633C155.115 205.398 154.453 205.281 153.719 205.281ZM160.109 215.422H147.391V214.391H160.109V215.422ZM173.938 215.547H161.219V214.516H173.938V215.547ZM168.141 214.969H166.938V211.531H168.141V214.969ZM172.328 208.609H164.031V211.422H162.812V207.609H171.125V205.422H162.781V204.406H172.328V208.609ZM172.656 211.891H162.812V210.875H172.656V211.891ZM189.719 206.344H185.734V205.359H189.719V206.344ZM189.75 208.953H185.734V207.984H189.75V208.953ZM186.172 210.125H179.719V204.234H186.172V210.125ZM180.938 209.156H184.969V205.219H180.938V209.156ZM190.562 211.375H189.344V203.375H190.562V211.375ZM186.562 213.266C186.562 213.911 186.318 214.51 185.828 215.062C185.339 215.615 184.688 216.078 183.875 216.453C183.068 216.828 182.198 217.078 181.266 217.203L180.844 216.266C181.635 216.177 182.393 215.984 183.117 215.688C183.841 215.385 184.424 215.021 184.867 214.594C185.31 214.161 185.531 213.719 185.531 213.266V212.984H186.562V213.266ZM186.781 213.266C186.776 213.703 186.99 214.135 187.422 214.562C187.859 214.99 188.432 215.357 189.141 215.664C189.854 215.966 190.604 216.167 191.391 216.266L190.969 217.203C190.036 217.073 189.169 216.815 188.367 216.43C187.57 216.049 186.93 215.583 186.445 215.031C185.961 214.479 185.719 213.891 185.719 213.266V212.984H186.781V213.266ZM190.891 213.266H181.406V212.297H190.891V213.266ZM186.781 212.844H185.531V210.953H186.781V212.844ZM201.328 207.906C201.323 208.859 201.154 209.781 200.82 210.672C200.492 211.557 200.036 212.341 199.453 213.023C198.87 213.706 198.214 214.224 197.484 214.578L196.781 213.625C197.453 213.312 198.06 212.857 198.602 212.258C199.148 211.659 199.576 210.982 199.883 210.227C200.19 209.466 200.344 208.693 200.344 207.906V206.656H201.328V207.906ZM201.531 207.906C201.531 208.641 201.682 209.367 201.984 210.086C202.286 210.799 202.698 211.448 203.219 212.031C203.745 212.609 204.339 213.057 205 213.375L204.281 214.328C203.562 213.974 202.924 213.466 202.367 212.805C201.81 212.143 201.372 211.388 201.055 210.539C200.737 209.685 200.578 208.807 200.578 207.906V206.656H201.531V207.906ZM204.688 206.797H197.156V205.797H204.688V206.797ZM201.562 206.359H200.328V203.641H201.562V206.359ZM207.656 217.266H206.438V203.375H207.656V217.266ZM209.984 210.125H207.375V209.078H209.984V210.125ZM222.203 213.547H220.984V203.391H222.203V213.547ZM222.641 216.969H213.234V215.938H222.641V216.969ZM214.453 216.281H213.234V212.516H214.453V216.281ZM214.703 204.359C215.391 204.359 216.01 204.505 216.562 204.797C217.115 205.089 217.549 205.492 217.867 206.008C218.185 206.523 218.344 207.109 218.344 207.766C218.344 208.427 218.185 209.018 217.867 209.539C217.549 210.055 217.115 210.458 216.562 210.75C216.01 211.042 215.391 211.188 214.703 211.188C214.016 211.188 213.396 211.042 212.844 210.75C212.292 210.458 211.857 210.055 211.539 209.539C211.221 209.018 211.062 208.427 211.062 207.766C211.062 207.109 211.221 206.523 211.539 206.008C211.857 205.492 212.292 205.089 212.844 204.797C213.396 204.505 214.016 204.359 214.703 204.359ZM214.703 205.438C214.24 205.438 213.82 205.536 213.445 205.734C213.076 205.932 212.784 206.208 212.57 206.562C212.362 206.917 212.26 207.318 212.266 207.766C212.26 208.219 212.362 208.625 212.57 208.984C212.784 209.339 213.076 209.615 213.445 209.812C213.82 210.01 214.24 210.109 214.703 210.109C215.161 210.109 215.576 210.01 215.945 209.812C216.315 209.615 216.607 209.339 216.82 208.984C217.034 208.625 217.141 208.219 217.141 207.766C217.141 207.318 217.034 206.917 216.82 206.562C216.607 206.208 216.315 205.932 215.945 205.734C215.576 205.536 215.161 205.438 214.703 205.438ZM229.312 207.641C229.312 208.599 229.13 209.544 228.766 210.477C228.401 211.409 227.911 212.237 227.297 212.961C226.688 213.685 226.021 214.229 225.297 214.594L224.562 213.625C225.224 213.307 225.839 212.828 226.406 212.188C226.979 211.542 227.438 210.818 227.781 210.016C228.125 209.214 228.297 208.422 228.297 207.641V205.344H229.312V207.641ZM229.531 207.641C229.531 208.406 229.703 209.169 230.047 209.93C230.391 210.685 230.849 211.359 231.422 211.953C231.995 212.547 232.62 212.99 233.297 213.281L232.609 214.25C231.854 213.906 231.167 213.396 230.547 212.719C229.932 212.042 229.443 211.263 229.078 210.383C228.719 209.497 228.542 208.583 228.547 207.641V205.344H229.531V207.641ZM232.844 205.828H225.016V204.812H232.844V205.828ZM236.016 217.266H234.781V203.375H236.016V217.266ZM255.406 209.953H252.844V208.922H255.406V209.953ZM253.156 217.266H251.938V203.375H253.156V217.266ZM244.203 213.344H242.984V204.75H244.203V213.344ZM244.094 212.703C245.193 212.708 246.273 212.661 247.336 212.562C248.398 212.464 249.484 212.297 250.594 212.062L250.75 213.109C249.62 213.339 248.513 213.5 247.43 213.594C246.346 213.688 245.234 213.734 244.094 213.734H242.984V212.703H244.094ZM261.453 216.844H260.219V211.219H261.453V216.844ZM267.734 217.281H266.516V203.391H267.734V217.281ZM256.484 210.828C258.167 210.823 259.755 210.794 261.25 210.742C262.745 210.685 264.156 210.583 265.484 210.438L265.547 211.359C264.177 211.557 262.755 211.69 261.281 211.758C259.807 211.826 258.214 211.865 256.5 211.875H256.328L256.172 210.828H256.484ZM264.312 208.859H257.547V207.828H264.312V208.859ZM258.766 208.125H257.547V204.328H258.766V208.125ZM273.797 204.453C274.469 204.453 275.068 204.651 275.594 205.047C276.125 205.443 276.536 206.008 276.828 206.742C277.12 207.477 277.266 208.328 277.266 209.297C277.266 210.271 277.12 211.122 276.828 211.852C276.536 212.576 276.125 213.135 275.594 213.531C275.068 213.927 274.469 214.125 273.797 214.125C273.115 214.125 272.508 213.927 271.977 213.531C271.451 213.135 271.042 212.576 270.75 211.852C270.458 211.122 270.312 210.271 270.312 209.297C270.312 208.328 270.458 207.477 270.75 206.742C271.042 206.008 271.451 205.443 271.977 205.047C272.508 204.651 273.115 204.453 273.797 204.453ZM273.797 205.547C273.344 205.547 272.943 205.703 272.594 206.016C272.25 206.328 271.979 206.768 271.781 207.336C271.583 207.898 271.484 208.552 271.484 209.297C271.484 210.042 271.583 210.698 271.781 211.266C271.979 211.828 272.25 212.263 272.594 212.57C272.943 212.878 273.344 213.031 273.797 213.031C274.245 213.031 274.646 212.878 275 212.57C275.354 212.263 275.628 211.826 275.82 211.258C276.013 210.69 276.109 210.036 276.109 209.297C276.109 208.557 276.013 207.904 275.82 207.336C275.628 206.768 275.354 206.328 275 206.016C274.646 205.703 274.245 205.547 273.797 205.547ZM281.578 217.297H280.359V203.375H281.578V217.297ZM280.906 209.703H276.859V208.688H280.906V209.703ZM295.406 217.266H294.172V203.375H295.406V217.266ZM288.469 207.5C288.464 208.469 288.286 209.424 287.938 210.367C287.594 211.31 287.125 212.151 286.531 212.891C285.943 213.625 285.302 214.188 284.609 214.578L283.797 213.641C284.453 213.312 285.062 212.82 285.625 212.164C286.188 211.503 286.635 210.763 286.969 209.945C287.302 209.122 287.469 208.307 287.469 207.5V205.344H288.469V207.5ZM288.703 207.5C288.703 208.214 288.87 208.958 289.203 209.734C289.536 210.505 289.979 211.211 290.531 211.852C291.089 212.487 291.693 212.969 292.344 213.297L291.609 214.234C290.906 213.87 290.258 213.328 289.664 212.609C289.076 211.891 288.604 211.081 288.25 210.18C287.896 209.279 287.719 208.385 287.719 207.5V205.344H288.703V207.5ZM291.875 205.828H284.297V204.812H291.875V205.828ZM294.969 208.328H291.328V207.297H294.969V208.328ZM294.969 211.281H291.328V210.25H294.969V211.281ZM302.078 214.703H300.875V210.547H302.078V214.703ZM307.281 214.703H306.047V210.547H307.281V214.703ZM310.438 215.484H297.719V214.453H310.438V215.484ZM304.047 204.25C305.031 204.255 305.906 204.406 306.672 204.703C307.443 204.995 308.044 205.414 308.477 205.961C308.909 206.503 309.125 207.125 309.125 207.828C309.125 208.536 308.909 209.159 308.477 209.695C308.044 210.232 307.443 210.648 306.672 210.945C305.906 211.242 305.031 211.391 304.047 211.391C303.062 211.391 302.185 211.242 301.414 210.945C300.648 210.648 300.049 210.232 299.617 209.695C299.185 209.159 298.969 208.536 298.969 207.828C298.969 207.125 299.185 206.503 299.617 205.961C300.049 205.414 300.648 204.995 301.414 204.703C302.185 204.406 303.062 204.255 304.047 204.25ZM304.047 205.266C303.292 205.26 302.617 205.365 302.023 205.578C301.435 205.786 300.977 206.086 300.648 206.477C300.32 206.867 300.156 207.318 300.156 207.828C300.156 208.339 300.32 208.789 300.648 209.18C300.977 209.57 301.435 209.875 302.023 210.094C302.617 210.312 303.292 210.422 304.047 210.422C304.797 210.422 305.466 210.312 306.055 210.094C306.643 209.875 307.104 209.57 307.438 209.18C307.771 208.789 307.938 208.339 307.938 207.828C307.938 207.318 307.771 206.867 307.438 206.477C307.104 206.086 306.643 205.786 306.055 205.578C305.466 205.365 304.797 205.26 304.047 205.266Z" fill="#929195"/> -<path d="M380 230H50C45.5817 230 42 233.582 42 238V246C42 250.418 45.5817 254 50 254H380C384.418 254 388 250.418 388 246V238C388 233.582 384.418 230 380 230Z" fill="white"/> -<path d="M50.6602 243.188H47.9883V242.426H50.6602V243.188ZM51.0585 247.184H50.1327V239.543H51.0585V247.184ZM51.3516 249.727H44.3672V248.953H51.3516V249.727ZM45.2929 249.328H44.3672V246.492H45.2929V249.328ZM45.8789 241.688C45.8789 242.309 45.7559 242.896 45.5098 243.451C45.2637 244.002 44.918 244.486 44.4727 244.904C44.0312 245.318 43.5234 245.633 42.9492 245.848L42.4688 245.098C42.9765 244.918 43.4316 244.654 43.834 244.307C44.2363 243.959 44.5508 243.559 44.7773 243.105C45.0039 242.648 45.1172 242.176 45.1172 241.688V240.832H45.8789V241.688ZM46.0429 241.688C46.0429 242.133 46.1522 242.566 46.371 242.988C46.5897 243.41 46.8926 243.785 47.2793 244.113C47.666 244.441 48.1094 244.691 48.6094 244.863L48.1289 245.602C47.5703 245.398 47.0762 245.1 46.6465 244.705C46.2207 244.311 45.8887 243.854 45.6504 243.334C45.4121 242.814 45.2929 242.266 45.2929 241.688V240.832H46.0429V241.688ZM48.375 241.148H42.7617V240.387H48.375V241.148ZM59.0858 244.43H57.082V243.645H59.0858V244.43ZM55.6875 242.742C55.6836 243.438 55.584 244.117 55.3887 244.781C55.1973 245.445 54.918 246.043 54.5508 246.574C54.1875 247.102 53.7578 247.516 53.2617 247.816L52.7108 247.113C53.1718 246.848 53.5723 246.482 53.9121 246.018C54.252 245.553 54.5117 245.035 54.6914 244.465C54.875 243.895 54.9688 243.32 54.9727 242.742V242.191H55.6875V242.742ZM55.8398 242.742C55.8438 243.305 55.9355 243.855 56.1152 244.395C56.2988 244.934 56.5625 245.424 56.9062 245.865C57.25 246.303 57.6523 246.645 58.1133 246.891L57.5858 247.582C57.0819 247.309 56.6444 246.92 56.2733 246.416C55.9061 245.912 55.6229 245.342 55.4237 244.705C55.2284 244.068 55.1328 243.414 55.1367 242.742V242.191H55.8398V242.742ZM57.7969 242.227H52.9922V241.465H57.7969V242.227ZM55.8516 242.039H54.9727V239.918H55.8516V242.039ZM61.6992 249.949H60.8203V239.531H61.6992V249.949ZM59.5898 249.41H58.7226V239.789H59.5898V249.41ZM69.7383 242.73C69.7383 243.449 69.6015 244.158 69.328 244.857C69.0546 245.557 68.6875 246.178 68.2266 246.721C67.7695 247.264 67.2695 247.672 66.7266 247.945L66.1758 247.219C66.6719 246.98 67.1328 246.621 67.5586 246.141C67.9883 245.656 68.332 245.113 68.5898 244.512C68.8477 243.91 68.9766 243.316 68.9766 242.73V241.008H69.7383V242.73ZM69.9023 242.73C69.9023 243.305 70.0312 243.877 70.2891 244.447C70.5469 245.014 70.8906 245.52 71.3203 245.965C71.75 246.41 72.2188 246.742 72.7266 246.961L72.2108 247.688C71.6444 247.43 71.1289 247.047 70.6641 246.539C70.2031 246.031 69.8359 245.447 69.5625 244.787C69.293 244.123 69.1602 243.438 69.1641 242.73V241.008H69.9023V242.73ZM72.3867 241.371H66.5155V240.609H72.3867V241.371ZM74.7655 249.949H73.8398V239.531H74.7655V249.949ZM81.7383 246.293H80.8358V244.711H81.7383V246.293ZM86.0391 244.887H76.5586V244.172H86.0391V244.887ZM81.7383 240.738H80.8358V239.473H81.7383V240.738ZM81.5976 240.984C81.5976 241.512 81.4061 241.969 81.0233 242.355C80.6405 242.738 80.1269 243.041 79.4823 243.264C78.8417 243.482 78.125 243.625 77.332 243.691L77.0625 242.988C77.75 242.945 78.377 242.838 78.9434 242.666C79.5098 242.49 79.959 242.26 80.291 241.975C80.623 241.686 80.7891 241.355 80.7891 240.984V240.832H81.5976V240.984ZM81.7969 240.984C81.793 241.355 81.957 241.686 82.2891 241.975C82.625 242.26 83.0742 242.49 83.6367 242.666C84.2031 242.838 84.8319 242.945 85.5233 242.988L85.2421 243.691C84.453 243.625 83.7382 243.482 83.0976 243.264C82.4569 243.041 81.9453 242.738 81.5625 242.355C81.1797 241.969 80.9883 241.512 80.9883 240.984V240.832H81.7969V240.984ZM85.078 241.172H77.5312V240.445H85.078V241.172ZM84.8203 248.109H78.6328V249.387H77.7188V247.453H83.9179V246.551H77.6953V245.859H84.8203V248.109ZM85.1367 249.832H77.7188V249.129H85.1367V249.832ZM97.9102 240.855H91.1367V240.094H97.9102V240.855ZM99.4688 244.688H89.9297V243.926H99.4688V244.688ZM98.2147 240.867C98.2147 241.473 98.1952 242.023 98.1561 242.52C98.1171 243.012 98.0234 243.578 97.875 244.219L96.9608 244.16C97.0663 243.73 97.1425 243.326 97.1894 242.947C97.2401 242.568 97.2715 242.236 97.2832 241.951C97.2949 241.662 97.3007 241.324 97.3007 240.938V240.867V240.094H98.2147V240.867ZM98.2617 249.809H91.1016V246.129H98.2617V249.809ZM92.0156 249.059H97.3477V246.855H92.0156V249.059ZM102.797 240.188C103.25 240.188 103.658 240.291 104.021 240.498C104.385 240.705 104.67 240.996 104.877 241.371C105.084 241.746 105.187 242.172 105.187 242.648C105.187 243.125 105.084 243.547 104.877 243.914C104.67 244.281 104.385 244.568 104.021 244.775C103.662 244.982 103.254 245.086 102.797 245.086C102.336 245.086 101.926 244.982 101.566 244.775C101.207 244.568 100.926 244.281 100.723 243.914C100.519 243.547 100.418 243.125 100.418 242.648C100.418 242.172 100.519 241.746 100.723 241.371C100.926 240.996 101.207 240.705 101.566 240.498C101.926 240.291 102.336 240.188 102.797 240.188ZM102.797 240.984C102.5 240.984 102.234 241.055 102 241.195C101.766 241.336 101.58 241.535 101.443 241.793C101.31 242.047 101.246 242.332 101.25 242.648C101.246 242.965 101.31 243.25 101.443 243.504C101.58 243.754 101.766 243.951 102 244.096C102.234 244.24 102.5 244.312 102.797 244.312C103.09 244.312 103.353 244.24 103.588 244.096C103.826 243.951 104.012 243.754 104.144 243.504C104.277 243.25 104.344 242.965 104.344 242.648C104.344 242.332 104.277 242.047 104.144 241.793C104.012 241.535 103.826 241.336 103.588 241.195C103.353 241.055 103.09 240.984 102.797 240.984ZM109.148 245.742H108.269V239.543H109.148V245.742ZM108.551 242.988H106.547V242.227H108.551V242.988ZM106.887 245.672H106.019V239.742H106.887V245.672ZM109.148 249.949H108.246V247.066H102.129V246.328H109.148V249.949Z" fill="#B2B1B6"/> -<path d="M309.047 246.969L312.906 242.906C313.411 242.365 313.797 241.927 314.062 241.594C314.333 241.26 314.539 240.943 314.68 240.641C314.82 240.333 314.891 240.01 314.891 239.672C314.891 239.292 314.792 238.958 314.594 238.672C314.396 238.38 314.125 238.154 313.781 237.992C313.443 237.831 313.062 237.75 312.641 237.75C312.198 237.75 311.81 237.839 311.477 238.016C311.148 238.193 310.893 238.443 310.711 238.766C310.529 239.083 310.438 239.453 310.438 239.875H309.109C309.104 239.219 309.255 238.638 309.562 238.133C309.875 237.628 310.305 237.234 310.852 236.953C311.398 236.672 312.01 236.531 312.688 236.531C313.359 236.531 313.961 236.669 314.492 236.945C315.029 237.221 315.448 237.599 315.75 238.078C316.052 238.557 316.203 239.089 316.203 239.672C316.198 240.104 316.117 240.518 315.961 240.914C315.81 241.305 315.549 241.74 315.18 242.219C314.81 242.698 314.286 243.286 313.609 243.984L311.016 246.656V246.75H316.406V248H309.062L309.047 246.969ZM322.219 236.531C322.938 236.542 323.607 236.714 324.227 237.047C324.846 237.38 325.352 237.945 325.742 238.742C326.133 239.534 326.328 240.583 326.328 241.891C326.328 243.214 326.156 244.344 325.812 245.281C325.469 246.219 324.974 246.932 324.328 247.422C323.682 247.911 322.917 248.156 322.031 248.156C321.375 248.156 320.786 248.029 320.266 247.773C319.745 247.518 319.32 247.167 318.992 246.719C318.664 246.266 318.453 245.74 318.359 245.141H319.75C319.833 245.49 319.977 245.797 320.18 246.062C320.383 246.323 320.641 246.529 320.953 246.68C321.266 246.831 321.625 246.906 322.031 246.906C322.646 246.906 323.177 246.734 323.625 246.391C324.073 246.047 324.414 245.552 324.648 244.906C324.888 244.255 325.01 243.474 325.016 242.562H324.859C324.641 242.875 324.383 243.143 324.086 243.367C323.789 243.591 323.461 243.763 323.102 243.883C322.742 244.003 322.365 244.062 321.969 244.062C321.297 244.062 320.677 243.901 320.109 243.578C319.547 243.255 319.099 242.81 318.766 242.242C318.432 241.674 318.266 241.036 318.266 240.328C318.266 239.625 318.43 238.984 318.758 238.406C319.086 237.823 319.549 237.365 320.148 237.031C320.747 236.693 321.438 236.526 322.219 236.531ZM322.219 237.766C321.734 237.766 321.294 237.88 320.898 238.109C320.508 238.339 320.198 238.648 319.969 239.039C319.745 239.43 319.635 239.854 319.641 240.312C319.641 240.776 319.75 241.201 319.969 241.586C320.188 241.966 320.487 242.268 320.867 242.492C321.253 242.716 321.688 242.828 322.172 242.828C322.651 242.828 323.091 242.708 323.492 242.469C323.893 242.229 324.211 241.914 324.445 241.523C324.68 241.133 324.797 240.719 324.797 240.281C324.797 239.849 324.685 239.44 324.461 239.055C324.237 238.664 323.927 238.352 323.531 238.117C323.141 237.883 322.703 237.766 322.219 237.766ZM327.984 244.531L333.078 236.688H333.922V238.469H333.328L329.5 244.359V244.453H336.391V245.688H327.984V244.531ZM333.469 245.344V244.797V236.688H334.812V248H333.469V245.344ZM338.297 251.203H337.141L338 246.953H339.516L338.297 251.203ZM345.281 248.156C344.5 248.156 343.805 248.021 343.195 247.75C342.586 247.479 342.112 247.104 341.773 246.625C341.435 246.146 341.266 245.604 341.266 245C341.266 244.521 341.367 244.073 341.57 243.656C341.773 243.24 342.049 242.898 342.398 242.633C342.747 242.362 343.135 242.193 343.562 242.125V242.062C343.193 241.979 342.867 241.815 342.586 241.57C342.31 241.326 342.094 241.026 341.938 240.672C341.781 240.318 341.703 239.938 341.703 239.531C341.703 238.964 341.857 238.453 342.164 238C342.471 237.542 342.896 237.182 343.438 236.922C343.984 236.661 344.599 236.531 345.281 236.531C345.958 236.531 346.57 236.661 347.117 236.922C347.664 237.182 348.091 237.542 348.398 238C348.711 238.453 348.87 238.964 348.875 239.531C348.87 239.938 348.786 240.318 348.625 240.672C348.469 241.026 348.25 241.326 347.969 241.57C347.688 241.815 347.365 241.979 347 242.062V242.125C347.422 242.193 347.807 242.362 348.156 242.633C348.51 242.898 348.789 243.24 348.992 243.656C349.201 244.073 349.307 244.521 349.312 245C349.307 245.604 349.133 246.146 348.789 246.625C348.451 247.104 347.974 247.479 347.359 247.75C346.75 248.021 346.057 248.156 345.281 248.156ZM345.281 246.922C345.812 246.922 346.276 246.836 346.672 246.664C347.068 246.492 347.372 246.258 347.586 245.961C347.799 245.664 347.906 245.318 347.906 244.922C347.906 244.51 347.794 244.141 347.57 243.812C347.346 243.479 347.034 243.219 346.633 243.031C346.232 242.844 345.781 242.75 345.281 242.75C344.781 242.75 344.333 242.844 343.938 243.031C343.542 243.219 343.229 243.479 343 243.812C342.776 244.141 342.667 244.51 342.672 244.922C342.667 245.318 342.768 245.664 342.977 245.961C343.19 246.258 343.492 246.492 343.883 246.664C344.279 246.836 344.745 246.922 345.281 246.922ZM345.281 241.562C345.708 241.562 346.091 241.479 346.43 241.312C346.768 241.146 347.031 240.919 347.219 240.633C347.406 240.346 347.5 240.016 347.5 239.641C347.5 239.266 347.409 238.935 347.227 238.648C347.044 238.362 346.784 238.141 346.445 237.984C346.107 237.828 345.719 237.75 345.281 237.75C344.839 237.75 344.451 237.828 344.117 237.984C343.789 238.141 343.531 238.362 343.344 238.648C343.156 238.935 343.062 239.266 343.062 239.641C343.062 240.016 343.159 240.346 343.352 240.633C343.544 240.919 343.807 241.146 344.141 241.312C344.474 241.479 344.854 241.562 345.281 241.562ZM354.906 248.156C354.073 248.156 353.362 247.93 352.773 247.477C352.185 247.023 351.734 246.362 351.422 245.492C351.109 244.622 350.953 243.573 350.953 242.344C350.953 241.13 351.109 240.089 351.422 239.219C351.734 238.344 352.185 237.677 352.773 237.219C353.367 236.76 354.078 236.531 354.906 236.531C355.729 236.531 356.438 236.76 357.031 237.219C357.625 237.677 358.078 238.344 358.391 239.219C358.703 240.089 358.859 241.13 358.859 242.344C358.859 243.573 358.706 244.622 358.398 245.492C358.091 246.362 357.641 247.023 357.047 247.477C356.453 247.93 355.74 248.156 354.906 248.156ZM354.906 246.906C355.448 246.906 355.914 246.729 356.305 246.375C356.695 246.021 356.99 245.503 357.188 244.82C357.385 244.138 357.484 243.312 357.484 242.344C357.484 241.375 357.383 240.547 357.18 239.859C356.977 239.172 356.682 238.648 356.297 238.289C355.911 237.93 355.448 237.75 354.906 237.75C354.365 237.75 353.901 237.93 353.516 238.289C353.13 238.648 352.833 239.172 352.625 239.859C352.417 240.547 352.312 241.375 352.312 242.344C352.312 243.312 352.417 244.138 352.625 244.82C352.833 245.503 353.128 246.021 353.508 246.375C353.893 246.729 354.359 246.906 354.906 246.906ZM364.438 248.156C363.604 248.156 362.893 247.93 362.305 247.477C361.716 247.023 361.266 246.362 360.953 245.492C360.641 244.622 360.484 243.573 360.484 242.344C360.484 241.13 360.641 240.089 360.953 239.219C361.266 238.344 361.716 237.677 362.305 237.219C362.898 236.76 363.609 236.531 364.438 236.531C365.26 236.531 365.969 236.76 366.562 237.219C367.156 237.677 367.609 238.344 367.922 239.219C368.234 240.089 368.391 241.13 368.391 242.344C368.391 243.573 368.237 244.622 367.93 245.492C367.622 246.362 367.172 247.023 366.578 247.477C365.984 247.93 365.271 248.156 364.438 248.156ZM364.438 246.906C364.979 246.906 365.445 246.729 365.836 246.375C366.227 246.021 366.521 245.503 366.719 244.82C366.917 244.138 367.016 243.312 367.016 242.344C367.016 241.375 366.914 240.547 366.711 239.859C366.508 239.172 366.214 238.648 365.828 238.289C365.443 237.93 364.979 237.75 364.438 237.75C363.896 237.75 363.432 237.93 363.047 238.289C362.661 238.648 362.365 239.172 362.156 239.859C361.948 240.547 361.844 241.375 361.844 242.344C361.844 243.312 361.948 244.138 362.156 244.82C362.365 245.503 362.659 246.021 363.039 246.375C363.424 246.729 363.891 246.906 364.438 246.906ZM379.016 245.453H377.781V242.359H379.016V245.453ZM385.234 245.938H384V235.391H385.234V245.938ZM385.578 248.969H375.703V247.938H385.578V248.969ZM376.938 248.234H375.703V244.906H376.938V248.234ZM373.703 241.828C375.562 241.818 377.208 241.789 378.641 241.742C380.073 241.69 381.443 241.583 382.75 241.422L382.828 242.312C381.479 242.526 380.065 242.667 378.586 242.734C377.107 242.802 375.536 242.833 373.875 242.828L373.703 241.828ZM384.328 244.5H381.125V243.609H384.328V244.5ZM378.266 235.953C378.938 235.953 379.534 236.052 380.055 236.25C380.581 236.448 380.987 236.732 381.273 237.102C381.56 237.471 381.703 237.896 381.703 238.375C381.703 238.865 381.56 239.289 381.273 239.648C380.987 240.008 380.583 240.286 380.062 240.484C379.542 240.682 378.943 240.781 378.266 240.781C377.583 240.781 376.982 240.682 376.461 240.484C375.945 240.286 375.544 240.008 375.258 239.648C374.971 239.289 374.828 238.865 374.828 238.375C374.828 237.896 374.971 237.471 375.258 237.102C375.544 236.732 375.948 236.448 376.469 236.25C376.99 236.052 377.589 235.953 378.266 235.953ZM378.266 236.891C377.818 236.885 377.422 236.945 377.078 237.07C376.734 237.19 376.466 237.365 376.273 237.594C376.086 237.823 375.995 238.083 376 238.375C375.995 238.672 376.086 238.935 376.273 239.164C376.466 239.388 376.734 239.562 377.078 239.688C377.422 239.812 377.818 239.875 378.266 239.875C378.703 239.875 379.094 239.812 379.438 239.688C379.781 239.562 380.049 239.388 380.242 239.164C380.435 238.935 380.531 238.672 380.531 238.375C380.531 238.083 380.435 237.823 380.242 237.594C380.049 237.365 379.781 237.19 379.438 237.07C379.094 236.945 378.703 236.885 378.266 236.891Z" fill="#56555A"/> -<path d="M24 270H399V300H24V270Z" fill="white"/> -<mask id="mask2_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="270" width="375" height="30"> -<path d="M24 270H399V300H24V270Z" fill="white"/> -</mask> -<g mask="url(#mask2_1837_9941)"> -<path d="M24 271H399V269H24V271Z" fill="#F1F0F5"/> -</g> -<path d="M48.7266 283.187H46.0547V282.426H48.7266V283.187ZM49.125 287.184H48.1992V279.543H49.125V287.184ZM49.418 289.727H42.4336V288.953H49.418V289.727ZM43.3594 289.328H42.4336V286.492H43.3594V289.328ZM43.9453 281.687C43.9453 282.309 43.8223 282.896 43.5762 283.451C43.3301 284.002 42.9844 284.486 42.5391 284.904C42.0977 285.318 41.5898 285.633 41.0156 285.848L40.5352 285.098C41.043 284.918 41.498 284.654 41.9004 284.307C42.3027 283.959 42.6172 283.559 42.8437 283.105C43.0703 282.648 43.1836 282.176 43.1836 281.687V280.832H43.9453V281.687ZM44.1094 281.687C44.1094 282.133 44.2187 282.566 44.4375 282.988C44.6562 283.41 44.959 283.785 45.3457 284.113C45.7324 284.441 46.1758 284.691 46.6758 284.863L46.1953 285.602C45.6367 285.398 45.1426 285.1 44.7129 284.705C44.2871 284.311 43.9551 283.854 43.7168 283.334C43.4785 282.814 43.3594 282.266 43.3594 281.687V280.832H44.1094V281.687ZM46.4414 281.148H40.8281V280.387H46.4414V281.148ZM57.1523 284.43H55.1484V283.645H57.1523V284.43ZM53.7539 282.742C53.75 283.437 53.6504 284.117 53.4551 284.781C53.2637 285.445 52.9844 286.043 52.6172 286.574C52.2539 287.102 51.8242 287.516 51.3281 287.816L50.7773 287.113C51.2383 286.848 51.6387 286.482 51.9785 286.018C52.3184 285.553 52.5781 285.035 52.7578 284.465C52.9414 283.895 53.0352 283.32 53.0391 282.742V282.191H53.7539V282.742ZM53.9062 282.742C53.9102 283.305 54.002 283.855 54.1816 284.395C54.3652 284.934 54.6289 285.424 54.9727 285.865C55.3164 286.303 55.7187 286.645 56.1797 286.891L55.6523 287.582C55.1484 287.309 54.7109 286.92 54.3398 286.416C53.9727 285.912 53.6895 285.342 53.4902 284.705C53.2949 284.068 53.1992 283.414 53.2031 282.742V282.191H53.9062V282.742ZM55.8633 282.227H51.0586V281.465H55.8633V282.227ZM53.918 282.039H53.0391V279.918H53.918V282.039ZM59.7656 289.949H58.8867V279.531H59.7656V289.949ZM57.6562 289.41H56.7891V279.789H57.6562V289.41ZM67.6406 281.699C67.6406 282.285 67.5176 282.832 67.2715 283.34C67.0254 283.848 66.6797 284.287 66.2344 284.658C65.7891 285.029 65.2773 285.309 64.6992 285.496L64.2422 284.77C64.7578 284.613 65.2168 284.381 65.6191 284.072C66.0215 283.764 66.334 283.406 66.5566 283C66.7793 282.59 66.8906 282.156 66.8906 281.699V281.254H67.6406V281.699ZM67.793 281.699C67.793 282.121 67.9023 282.521 68.1211 282.9C68.3398 283.279 68.6426 283.615 69.0293 283.908C69.4199 284.197 69.8711 284.418 70.3828 284.57L69.9492 285.297C69.3711 285.117 68.8633 284.85 68.4258 284.494C67.9883 284.139 67.6484 283.723 67.4062 283.246C67.1641 282.766 67.043 282.25 67.043 281.699V281.254H67.793V281.699ZM70.1484 281.512H64.5352V280.773H70.1484V281.512ZM67.8164 281.066H66.8906V279.484H67.8164V281.066ZM72.3867 285.707H71.4727V279.531H72.3867V285.707ZM73.957 282.953H72.1289V282.18H73.957V282.953ZM72.3867 289.809H65.8125V286.187H72.3867V289.809ZM66.7148 289.059H71.4727V286.914H66.7148V289.059ZM82.5586 282.637H79.3477V281.863H82.5586V282.637ZM82.5586 285.93H79.3477V285.168H82.5586V285.93ZM77.4141 280.34C77.918 280.34 78.3672 280.488 78.7617 280.785C79.1602 281.082 79.4687 281.506 79.6875 282.057C79.9062 282.607 80.0156 283.246 80.0156 283.973C80.0156 284.703 79.9062 285.342 79.6875 285.889C79.4687 286.432 79.1602 286.852 78.7617 287.148C78.3672 287.445 77.918 287.594 77.4141 287.594C76.9023 287.594 76.4473 287.445 76.0488 287.148C75.6543 286.852 75.3477 286.432 75.1289 285.889C74.9102 285.342 74.8008 284.703 74.8008 283.973C74.8008 283.246 74.9102 282.607 75.1289 282.057C75.3477 281.506 75.6543 281.082 76.0488 280.785C76.4473 280.488 76.9023 280.34 77.4141 280.34ZM77.4141 281.16C77.0742 281.16 76.7734 281.277 76.5117 281.512C76.2539 281.746 76.0508 282.076 75.9023 282.502C75.7539 282.924 75.6797 283.414 75.6797 283.973C75.6797 284.531 75.7539 285.023 75.9023 285.449C76.0508 285.871 76.2539 286.197 76.5117 286.428C76.7734 286.658 77.0742 286.773 77.4141 286.773C77.75 286.773 78.0508 286.658 78.3164 286.428C78.582 286.197 78.7871 285.869 78.9316 285.443C79.0762 285.018 79.1484 284.527 79.1484 283.973C79.1484 283.418 79.0762 282.928 78.9316 282.502C78.7871 282.076 78.582 281.746 78.3164 281.512C78.0508 281.277 77.75 281.16 77.4141 281.16ZM83.25 289.973H82.3359V279.531H83.25V289.973ZM88.3359 282.73C88.3359 283.437 88.2031 284.141 87.9375 284.84C87.6719 285.535 87.3105 286.158 86.8535 286.709C86.3965 287.26 85.9023 287.672 85.3711 287.945L84.8086 287.219C85.3047 286.977 85.7656 286.613 86.1914 286.129C86.6211 285.645 86.9629 285.102 87.2168 284.5C87.4746 283.898 87.6055 283.309 87.6094 282.73V281.008H88.3359V282.73ZM88.5117 282.73C88.5078 283.277 88.625 283.832 88.8633 284.395C89.1055 284.957 89.4336 285.467 89.8477 285.924C90.2617 286.377 90.7187 286.723 91.2187 286.961L90.6914 287.687C90.1484 287.422 89.6543 287.029 89.209 286.51C88.7676 285.99 88.418 285.4 88.1602 284.74C87.9023 284.076 87.7734 283.406 87.7734 282.73V281.008H88.5117V282.73ZM90.8555 281.371H85.1836V280.609H90.8555V281.371ZM93.0469 289.949H92.1328V279.531H93.0469V289.949ZM94.793 284.535H92.8359V283.75H94.793V284.535Z" fill="#B2B1B6"/> -<path d="M352.809 289.117C352.223 289.117 351.701 289.016 351.244 288.812C350.787 288.609 350.432 288.328 350.178 287.969C349.924 287.609 349.797 287.203 349.797 286.75C349.797 286.391 349.873 286.055 350.025 285.742C350.178 285.43 350.385 285.174 350.646 284.975C350.908 284.771 351.199 284.645 351.52 284.594V284.547C351.242 284.484 350.998 284.361 350.787 284.178C350.58 283.994 350.418 283.77 350.301 283.504C350.184 283.238 350.125 282.953 350.125 282.648C350.125 282.223 350.24 281.84 350.471 281.5C350.701 281.156 351.02 280.887 351.426 280.691C351.836 280.496 352.297 280.398 352.809 280.398C353.316 280.398 353.775 280.496 354.186 280.691C354.596 280.887 354.916 281.156 355.146 281.5C355.381 281.84 355.5 282.223 355.504 282.648C355.5 282.953 355.437 283.238 355.316 283.504C355.199 283.77 355.035 283.994 354.824 284.178C354.613 284.361 354.371 284.484 354.098 284.547V284.594C354.414 284.645 354.703 284.771 354.965 284.975C355.23 285.174 355.439 285.43 355.592 285.742C355.748 286.055 355.828 286.391 355.832 286.75C355.828 287.203 355.697 287.609 355.439 287.969C355.186 288.328 354.828 288.609 354.367 288.812C353.91 289.016 353.391 289.117 352.809 289.117ZM352.809 288.191C353.207 288.191 353.555 288.127 353.852 287.998C354.148 287.869 354.377 287.693 354.537 287.471C354.697 287.248 354.777 286.988 354.777 286.691C354.777 286.383 354.693 286.105 354.525 285.859C354.357 285.609 354.123 285.414 353.822 285.273C353.521 285.133 353.184 285.062 352.809 285.062C352.434 285.062 352.098 285.133 351.801 285.273C351.504 285.414 351.27 285.609 351.098 285.859C350.93 286.105 350.848 286.383 350.852 286.691C350.848 286.988 350.924 287.248 351.08 287.471C351.24 287.693 351.467 287.869 351.76 287.998C352.057 288.127 352.406 288.191 352.809 288.191ZM352.809 284.172C353.129 284.172 353.416 284.109 353.67 283.984C353.924 283.859 354.121 283.689 354.262 283.475C354.402 283.26 354.473 283.012 354.473 282.73C354.473 282.449 354.404 282.201 354.268 281.986C354.131 281.771 353.936 281.605 353.682 281.488C353.428 281.371 353.137 281.312 352.809 281.312C352.477 281.312 352.186 281.371 351.936 281.488C351.689 281.605 351.496 281.771 351.355 281.986C351.215 282.201 351.145 282.449 351.145 282.73C351.145 283.012 351.217 283.26 351.361 283.475C351.506 283.689 351.703 283.859 351.953 283.984C352.203 284.109 352.488 284.172 352.809 284.172ZM364.949 281.992H361.879V281.23H364.949V281.992ZM364.961 284.066H361.879V283.293H364.961V284.066ZM365.512 285.707H364.586V279.531H365.512V285.707ZM362.148 284.957H357.367V280.328H362.148V284.957ZM358.281 284.207H361.246V281.078H358.281V284.207ZM362.055 286.012C362.773 286.012 363.395 286.088 363.918 286.24C364.441 286.393 364.844 286.617 365.125 286.914C365.406 287.211 365.547 287.566 365.547 287.98C365.547 288.391 365.406 288.74 365.125 289.029C364.844 289.322 364.441 289.545 363.918 289.697C363.395 289.85 362.773 289.926 362.055 289.926C361.332 289.926 360.709 289.85 360.186 289.697C359.666 289.545 359.266 289.322 358.984 289.029C358.703 288.74 358.562 288.391 358.562 287.98C358.562 287.566 358.703 287.211 358.984 286.914C359.266 286.617 359.666 286.393 360.186 286.24C360.709 286.088 361.332 286.012 362.055 286.012ZM362.055 286.727C361.523 286.73 361.064 286.783 360.678 286.885C360.291 286.982 359.994 287.125 359.787 287.312C359.58 287.5 359.477 287.723 359.477 287.98C359.477 288.23 359.58 288.447 359.787 288.631C359.994 288.814 360.291 288.955 360.678 289.053C361.064 289.15 361.523 289.199 362.055 289.199C362.582 289.199 363.039 289.15 363.426 289.053C363.816 288.955 364.115 288.814 364.322 288.631C364.529 288.447 364.633 288.23 364.633 287.98C364.633 287.723 364.529 287.5 364.322 287.312C364.115 287.125 363.818 286.982 363.432 286.885C363.045 286.783 362.586 286.73 362.055 286.727Z" fill="#B2B1B6"/> -<mask id="mask3_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="375" y="279" width="8" height="12"> -<path d="M383 283C383 280.791 381.209 279 379 279C376.791 279 375 280.791 375 283V287C375 289.209 376.791 291 379 291C381.209 291 383 289.209 383 287V283Z" fill="white"/> -</mask> -<g mask="url(#mask3_1837_9941)"> -<path d="M377 281L381 285L377 289" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -</g> -<path d="M390 316H40C35.5817 316 32 319.582 32 324V348C32 352.418 35.5817 356 40 356H390C394.418 356 398 352.418 398 348V324C398 319.582 394.418 316 390 316Z" fill="white"/> -<path d="M52.4062 339.633H50.4219V329.234H52.4062V339.633ZM50.7031 334.977H47.875V333.352H50.7031V334.977ZM48.0078 330.273C48.0026 331.539 47.7422 332.693 47.2266 333.734C46.7109 334.771 45.9609 335.669 44.9766 336.43C43.9922 337.185 42.8073 337.779 41.4219 338.211L40.6016 336.617C41.6953 336.273 42.638 335.831 43.4297 335.289C44.2266 334.742 44.8333 334.12 45.25 333.422C45.6719 332.724 45.8854 331.974 45.8906 331.172V330.273H48.0078ZM47.1641 331.906H41.3437V330.273H47.1641V331.906ZM52.7734 343.195H43.0234V341.586H52.7734V343.195ZM45.0469 342.508H43.0234V338.57H45.0469V342.508ZM59.0547 331.258C59.0547 332.227 58.9089 333.125 58.6172 333.953C58.3307 334.781 57.8932 335.503 57.3047 336.117C56.7161 336.727 55.987 337.18 55.1172 337.477L54.0469 335.914C54.8073 335.654 55.4401 335.286 55.9453 334.812C56.4505 334.333 56.8229 333.792 57.0625 333.187C57.3021 332.583 57.4245 331.94 57.4297 331.258V329.969H59.0547V331.258ZM59.4297 331.453C59.4297 332.052 59.5469 332.617 59.7812 333.148C60.0208 333.68 60.3828 334.154 60.8672 334.57C61.3568 334.982 61.9635 335.302 62.6875 335.531L61.625 337.078C60.7917 336.802 60.0911 336.388 59.5234 335.836C58.9557 335.279 58.5286 334.628 58.2422 333.883C57.9557 333.138 57.8151 332.328 57.8203 331.453V329.969H59.4297V331.453ZM65.5312 337.648H63.5391V329.203H65.5312V337.648ZM67.4531 334.203H64.9687V332.539H67.4531V334.203ZM60.8672 337.937C61.8464 337.937 62.6953 338.047 63.4141 338.266C64.138 338.479 64.6927 338.794 65.0781 339.211C65.4687 339.622 65.6641 340.112 65.6641 340.68C65.6641 341.258 65.4687 341.753 65.0781 342.164C64.6927 342.576 64.138 342.891 63.4141 343.109C62.6953 343.328 61.8464 343.437 60.8672 343.437C59.8724 343.437 59.0078 343.328 58.2734 343.109C57.5443 342.891 56.9818 342.576 56.5859 342.164C56.1901 341.753 55.9922 341.258 55.9922 340.68C55.9922 340.112 56.1901 339.622 56.5859 339.211C56.9818 338.794 57.5443 338.479 58.2734 338.266C59.0078 338.047 59.8724 337.937 60.8672 337.937ZM60.8672 339.5C60.2474 339.495 59.724 339.539 59.2969 339.633C58.8698 339.721 58.5443 339.854 58.3203 340.031C58.1016 340.208 57.9948 340.424 58 340.68C57.9948 340.945 58.1016 341.167 58.3203 341.344C58.5391 341.521 58.8594 341.654 59.2812 341.742C59.7083 341.831 60.237 341.875 60.8672 341.875C61.487 341.875 62.0078 341.831 62.4297 341.742C62.8516 341.654 63.1693 341.521 63.3828 341.344C63.5964 341.167 63.7031 340.945 63.7031 340.68C63.7031 340.424 63.5937 340.208 63.375 340.031C63.1615 339.849 62.8437 339.714 62.4219 339.625C62 339.536 61.4818 339.495 60.8672 339.5ZM69.7266 345.297H68.0703L68.8437 340.852H71.0781L69.7266 345.297ZM82.9297 331.227C82.9297 332.07 82.7031 332.841 82.25 333.539C81.8021 334.232 81.1484 334.815 80.2891 335.289C79.4297 335.758 78.4115 336.073 77.2344 336.234L76.4922 334.68C77.487 334.56 78.3385 334.323 79.0469 333.969C79.7604 333.609 80.2969 333.193 80.6562 332.719C81.0156 332.24 81.1953 331.742 81.1953 331.227V330.797H82.9297V331.227ZM83.5 331.227C83.5 331.742 83.6771 332.24 84.0312 332.719C84.3906 333.193 84.9245 333.609 85.6328 333.969C86.3464 334.323 87.2083 334.56 88.2187 334.68L87.5 336.234C86.3125 336.073 85.2865 335.758 84.4219 335.289C83.5573 334.815 82.8984 334.232 82.4453 333.539C81.9922 332.841 81.7656 332.07 81.7656 331.227V330.797H83.5V331.227ZM83.2969 343.445H81.3203V338.203H83.2969V343.445ZM88.8359 338.656H75.8672V337.07H88.8359V338.656ZM87.6641 331.523H77.0312V329.969H87.6641V331.523ZM101.062 340.32H99.0547V329.203H101.062V340.32ZM102.883 335.531H100.352V333.891H102.883V335.531ZM101.547 343.195H91.5234V341.586H101.547V343.195ZM93.5391 342.062H91.5234V339.586H93.5391V342.062ZM94.9687 338.125H92.9844V336.039H94.9687V338.125ZM89.5391 337.391C91.1849 337.391 92.7474 337.359 94.2266 337.297C95.7057 337.229 97.0964 337.102 98.3984 336.914L98.5469 338.281C97.2969 338.521 96.0078 338.682 94.6797 338.766C93.3516 338.849 91.8385 338.904 90.1406 338.93C90.0625 338.93 89.9948 338.93 89.9375 338.93C89.8802 338.93 89.8125 338.93 89.7344 338.93L89.5391 337.391ZM98.0391 331.805H89.8984V330.367H98.0391V331.805ZM93.9687 332.195C94.6615 332.195 95.2708 332.284 95.7969 332.461C96.3229 332.633 96.7292 332.888 97.0156 333.227C97.3021 333.56 97.4479 333.958 97.4531 334.422C97.4479 334.859 97.3021 335.242 97.0156 335.57C96.7292 335.893 96.3229 336.146 95.7969 336.328C95.2708 336.505 94.6615 336.594 93.9687 336.594C93.2708 336.594 92.6589 336.505 92.1328 336.328C91.6068 336.151 91.1979 335.901 90.9062 335.578C90.6198 335.25 90.4766 334.865 90.4766 334.422C90.4766 333.958 90.6198 333.56 90.9062 333.227C91.1979 332.888 91.6042 332.633 92.125 332.461C92.651 332.284 93.2656 332.195 93.9687 332.195ZM93.9687 333.531C93.625 333.531 93.3359 333.562 93.1016 333.625C92.8672 333.687 92.6875 333.786 92.5625 333.922C92.4427 334.057 92.3828 334.224 92.3828 334.422C92.3828 334.594 92.4427 334.745 92.5625 334.875C92.6875 335 92.8672 335.096 93.1016 335.164C93.3411 335.227 93.6302 335.258 93.9687 335.258C94.2969 335.258 94.5781 335.227 94.8125 335.164C95.0521 335.096 95.2318 335 95.3516 334.875C95.4766 334.745 95.5391 334.594 95.5391 334.422C95.5391 334.224 95.4792 334.057 95.3594 333.922C95.2396 333.786 95.0599 333.687 94.8203 333.625C94.5859 333.562 94.3021 333.531 93.9687 333.531ZM94.9687 331.008H92.9844V329.164H94.9687V331.008ZM105.164 345.297H103.508L104.281 340.852H106.516L105.164 345.297ZM123.687 332.609H111.852V331.016H123.687V332.609ZM124.305 341.992H111.305V340.383H124.305V341.992ZM118.75 341.008H116.773V338.469H118.75V341.008ZM117.766 333.227C118.745 333.227 119.599 333.336 120.328 333.555C121.062 333.773 121.625 334.094 122.016 334.516C122.411 334.932 122.609 335.424 122.609 335.992C122.609 336.57 122.411 337.07 122.016 337.492C121.625 337.909 121.065 338.232 120.336 338.461C119.607 338.685 118.75 338.799 117.766 338.805C116.766 338.799 115.901 338.685 115.172 338.461C114.443 338.232 113.88 337.909 113.484 337.492C113.094 337.07 112.901 336.57 112.906 335.992C112.901 335.419 113.094 334.924 113.484 334.508C113.88 334.091 114.443 333.773 115.172 333.555C115.906 333.336 116.771 333.227 117.766 333.227ZM117.766 334.781C117.141 334.786 116.62 334.833 116.203 334.922C115.792 335.005 115.479 335.138 115.266 335.32C115.052 335.497 114.948 335.721 114.953 335.992C114.948 336.263 115.052 336.49 115.266 336.672C115.479 336.849 115.792 336.984 116.203 337.078C116.62 337.167 117.141 337.211 117.766 337.211C118.375 337.211 118.885 337.167 119.297 337.078C119.713 336.984 120.029 336.849 120.242 336.672C120.456 336.49 120.562 336.263 120.562 335.992C120.562 335.721 120.456 335.497 120.242 335.32C120.029 335.138 119.713 335.005 119.297 334.922C118.885 334.833 118.375 334.786 117.766 334.781ZM118.75 332.008H116.773V329.359H118.75V332.008ZM137.109 339.633H135.125V329.234H137.109V339.633ZM135.406 334.977H132.578V333.352H135.406V334.977ZM132.711 330.273C132.706 331.539 132.445 332.693 131.93 333.734C131.414 334.771 130.664 335.669 129.68 336.43C128.695 337.185 127.51 337.779 126.125 338.211L125.305 336.617C126.398 336.273 127.341 335.831 128.133 335.289C128.93 334.742 129.536 334.12 129.953 333.422C130.375 332.724 130.589 331.974 130.594 331.172V330.273H132.711ZM131.867 331.906H126.047V330.273H131.867V331.906ZM137.477 343.195H127.727V341.586H137.477V343.195ZM129.75 342.508H127.727V338.57H129.75V342.508ZM140.602 345.297H138.945L139.719 340.852H141.953L140.602 345.297ZM153.805 331.227C153.805 332.07 153.578 332.841 153.125 333.539C152.677 334.232 152.023 334.815 151.164 335.289C150.305 335.758 149.286 336.073 148.109 336.234L147.367 334.68C148.362 334.56 149.214 334.323 149.922 333.969C150.635 333.609 151.172 333.193 151.531 332.719C151.891 332.24 152.07 331.742 152.07 331.227V330.797H153.805V331.227ZM154.375 331.227C154.375 331.742 154.552 332.24 154.906 332.719C155.266 333.193 155.799 333.609 156.508 333.969C157.221 334.323 158.083 334.56 159.094 334.68L158.375 336.234C157.187 336.073 156.161 335.758 155.297 335.289C154.432 334.815 153.773 334.232 153.32 333.539C152.867 332.841 152.641 332.07 152.641 331.227V330.797H154.375V331.227ZM154.172 343.445H152.195V338.203H154.172V343.445ZM159.711 338.656H146.742V337.07H159.711V338.656ZM158.539 331.523H147.906V329.969H158.539V331.523ZM171.781 343.437H169.812V329.203H171.781V343.437ZM173.891 336.422H171.344V334.789H173.891V336.422ZM168.844 332.937H160.492V331.336H168.844V332.937ZM164.703 333.727C165.385 333.727 166.003 333.872 166.555 334.164C167.112 334.451 167.547 334.852 167.859 335.367C168.177 335.883 168.339 336.466 168.344 337.117C168.339 337.773 168.177 338.359 167.859 338.875C167.547 339.385 167.112 339.786 166.555 340.078C166.003 340.365 165.385 340.508 164.703 340.508C164.01 340.508 163.388 340.365 162.836 340.078C162.284 339.786 161.852 339.385 161.539 338.875C161.227 338.359 161.07 337.773 161.07 337.117C161.07 336.466 161.227 335.883 161.539 335.367C161.852 334.852 162.284 334.451 162.836 334.164C163.388 333.872 164.01 333.727 164.703 333.727ZM164.703 335.352C164.37 335.357 164.073 335.43 163.812 335.57C163.552 335.711 163.346 335.917 163.195 336.187C163.049 336.453 162.977 336.763 162.977 337.117C162.977 337.482 163.049 337.797 163.195 338.062C163.346 338.323 163.552 338.523 163.812 338.664C164.073 338.805 164.37 338.878 164.703 338.883C165.036 338.878 165.333 338.805 165.594 338.664C165.859 338.523 166.062 338.323 166.203 338.062C166.349 337.797 166.422 337.482 166.422 337.117C166.422 336.763 166.349 336.453 166.203 336.187C166.062 335.917 165.859 335.711 165.594 335.57C165.333 335.43 165.036 335.357 164.703 335.352ZM165.695 331.945H163.711V329.43H165.695V331.945ZM191.094 336.336H178.102V334.773H191.094V336.336ZM189.539 333.984H179.711V332.414H189.539V333.984ZM189.437 331.086H181.703V333.75H179.711V329.508H189.437V331.086ZM189.484 340.883H181.562V342.164H179.602V339.469H187.516V338.672H179.594V337.172H189.484V340.883ZM189.859 343.32H179.602V341.773H189.859V343.32ZM195.844 330.211C196.552 330.211 197.185 330.419 197.742 330.836C198.305 331.247 198.742 331.839 199.055 332.609C199.367 333.375 199.523 334.266 199.523 335.281C199.523 336.302 199.367 337.198 199.055 337.969C198.742 338.734 198.305 339.323 197.742 339.734C197.185 340.146 196.552 340.352 195.844 340.352C195.125 340.352 194.487 340.146 193.93 339.734C193.372 339.323 192.935 338.734 192.617 337.969C192.299 337.198 192.141 336.302 192.141 335.281C192.141 334.266 192.299 333.375 192.617 332.609C192.935 331.839 193.372 331.247 193.93 330.836C194.487 330.419 195.125 330.211 195.844 330.211ZM195.844 332.016C195.484 332.01 195.172 332.135 194.906 332.391C194.641 332.646 194.432 333.018 194.281 333.508C194.13 333.997 194.057 334.589 194.062 335.281C194.057 335.974 194.13 336.565 194.281 337.055C194.432 337.544 194.641 337.917 194.906 338.172C195.172 338.422 195.484 338.547 195.844 338.547C196.203 338.547 196.518 338.422 196.789 338.172C197.06 337.917 197.268 337.544 197.414 337.055C197.56 336.565 197.633 335.974 197.633 335.281C197.633 334.589 197.56 333.997 197.414 333.508C197.268 333.013 197.06 332.641 196.789 332.391C196.518 332.135 196.203 332.01 195.844 332.016ZM203.922 343.477H201.945V329.203H203.922V343.477ZM202.797 335.953H198.93V334.352H202.797V335.953ZM213.187 336.516H211.227V334.398H213.187V336.516ZM212.234 329.422C213.281 329.422 214.193 329.534 214.969 329.758C215.75 329.977 216.349 330.294 216.766 330.711C217.187 331.128 217.398 331.617 217.398 332.18C217.398 332.742 217.187 333.232 216.766 333.648C216.349 334.065 215.753 334.385 214.977 334.609C214.201 334.828 213.286 334.935 212.234 334.93C211.187 334.935 210.273 334.828 209.492 334.609C208.711 334.385 208.107 334.065 207.68 333.648C207.258 333.232 207.047 332.742 207.047 332.18C207.047 331.617 207.26 331.128 207.687 330.711C208.115 330.294 208.716 329.977 209.492 329.758C210.273 329.534 211.187 329.422 212.234 329.422ZM212.234 330.953C211.573 330.953 211.008 331 210.539 331.094C210.076 331.182 209.721 331.32 209.477 331.508C209.237 331.69 209.117 331.914 209.117 332.18C209.117 332.456 209.237 332.687 209.477 332.875C209.721 333.057 210.073 333.195 210.531 333.289C210.995 333.378 211.562 333.422 212.234 333.422C212.896 333.422 213.458 333.378 213.922 333.289C214.391 333.195 214.745 333.057 214.984 332.875C215.224 332.687 215.344 332.456 215.344 332.18C215.344 331.914 215.221 331.69 214.977 331.508C214.732 331.32 214.378 331.182 213.914 331.094C213.451 331 212.891 330.953 212.234 330.953ZM217.172 343.281H207.258V338.43H217.172V343.281ZM209.219 341.68H215.219V340.008H209.219V341.68ZM218.727 337.492H205.758V335.914H218.727V337.492Z" fill="#56555A"/> -<path d="M386 364H44C37.3726 364 32 369.373 32 376V508C32 514.627 37.3726 520 44 520H386C392.627 520 398 514.627 398 508V376C398 369.373 392.627 364 386 364Z" fill="white"/> -<path d="M52.3184 385H50.5488V378.191H50.502L48.5625 379.422V377.852L50.6602 376.516H52.3184V385ZM57.4922 378.76C57.4883 379.525 57.375 380.262 57.1523 380.969C56.9297 381.676 56.5977 382.307 56.1562 382.861C55.7187 383.412 55.1875 383.824 54.5625 384.098L53.7422 382.937C54.2969 382.695 54.7676 382.35 55.1543 381.9C55.5449 381.447 55.8359 380.949 56.0273 380.406C56.2187 379.863 56.3145 379.314 56.3145 378.76V378.15H57.4922V378.76ZM57.7969 378.76C57.793 379.283 57.8828 379.803 58.0664 380.318C58.2539 380.83 58.5332 381.305 58.9043 381.742C59.2754 382.176 59.7324 382.521 60.2754 382.779L59.4492 383.916C58.8437 383.643 58.3301 383.238 57.9082 382.703C57.4863 382.164 57.168 381.555 56.9531 380.875C56.7383 380.191 56.6328 379.486 56.6367 378.76V378.15H57.7969V378.76ZM59.9766 378.344H54.1055V377.154H59.9766V378.344ZM57.8086 377.775H56.3086V375.648H57.8086V377.775ZM62.3555 386.078H60.8555V375.402H62.3555V386.078ZM63.9375 380.805H62.0273V379.551H63.9375V380.805Z" fill="#56555A"/> -<path d="M364.586 382.398L368.406 376.516H369.039V377.852H368.594L365.723 382.27V382.34H370.891V383.266H364.586V382.398ZM368.699 383.008V382.598V376.516H369.707V385H368.699V383.008ZM379.984 377.992H376.914V377.23H379.984V377.992ZM379.996 380.066H376.914V379.293H379.996V380.066ZM380.547 381.707H379.621V375.531H380.547V381.707ZM377.184 380.957H372.402V376.328H377.184V380.957ZM373.316 380.207H376.281V377.078H373.316V380.207ZM377.09 382.012C377.809 382.012 378.43 382.088 378.953 382.24C379.477 382.393 379.879 382.617 380.16 382.914C380.441 383.211 380.582 383.566 380.582 383.98C380.582 384.391 380.441 384.74 380.16 385.029C379.879 385.322 379.477 385.545 378.953 385.697C378.43 385.85 377.809 385.926 377.09 385.926C376.367 385.926 375.744 385.85 375.221 385.697C374.701 385.545 374.301 385.322 374.02 385.029C373.738 384.74 373.598 384.391 373.598 383.98C373.598 383.566 373.738 383.211 374.02 382.914C374.301 382.617 374.701 382.393 375.221 382.24C375.744 382.088 376.367 382.012 377.09 382.012ZM377.09 382.727C376.559 382.73 376.1 382.783 375.713 382.885C375.326 382.982 375.029 383.125 374.822 383.312C374.615 383.5 374.512 383.723 374.512 383.98C374.512 384.23 374.615 384.447 374.822 384.631C375.029 384.814 375.326 384.955 375.713 385.053C376.1 385.15 376.559 385.199 377.09 385.199C377.617 385.199 378.074 385.15 378.461 385.053C378.852 384.955 379.15 384.814 379.357 384.631C379.564 384.447 379.668 384.23 379.668 383.98C379.668 383.723 379.564 383.5 379.357 383.312C379.15 383.125 378.854 382.982 378.467 382.885C378.08 382.783 377.621 382.73 377.09 382.727Z" fill="#B2B1B6"/> -<path d="M364 386.916H381.859V387.73H364V386.916Z" fill="#B2B1B6"/> -<path d="M382 398H48C43.5817 398 40 401.582 40 406V430C40 434.418 43.5817 438 48 438H382C386.418 438 390 434.418 390 430V406C390 401.582 386.418 398 382 398Z" fill="#F9F8FD"/> -<path d="M51.3203 412.82H52.6406V411.625H54.4844V417.078H49.4375V411.625H51.3203V412.82ZM52.6406 415.477V414.328H51.3203V415.477H52.6406ZM57.2109 412.82H58.4766V411.625H60.375V417.078H55.3125V411.625H57.2109V412.82ZM58.4766 415.477V414.328H57.2109V415.477H58.4766ZM61.3984 419.719H48.4297V418.125H61.3984V419.719ZM55.8906 418.703H53.8828V416.641H55.8906V418.703ZM54.8906 420.414C55.9167 420.414 56.7995 420.513 57.5391 420.711C58.2839 420.909 58.8542 421.195 59.25 421.57C59.6458 421.945 59.8464 422.396 59.8516 422.922C59.8464 423.458 59.6458 423.914 59.25 424.289C58.8594 424.669 58.2917 424.956 57.5469 425.148C56.8021 425.346 55.9167 425.443 54.8906 425.437C53.849 425.437 52.9557 425.341 52.2109 425.148C51.4714 424.956 50.9036 424.672 50.5078 424.297C50.1172 423.922 49.9219 423.464 49.9219 422.922C49.9219 422.396 50.1172 421.945 50.5078 421.57C50.9036 421.195 51.4714 420.909 52.2109 420.711C52.9557 420.513 53.849 420.414 54.8906 420.414ZM54.8906 421.898C54.2187 421.898 53.6615 421.937 53.2187 422.016C52.7812 422.089 52.4531 422.203 52.2344 422.359C52.0208 422.51 51.9167 422.698 51.9219 422.922C51.9167 423.151 52.0234 423.341 52.2422 423.492C52.4661 423.643 52.7943 423.758 53.2266 423.836C53.6641 423.914 54.2187 423.953 54.8906 423.953C55.5417 423.953 56.0833 423.914 56.5156 423.836C56.9531 423.758 57.2812 423.643 57.5 423.492C57.7187 423.341 57.8281 423.151 57.8281 422.922C57.8281 422.698 57.7187 422.51 57.5 422.359C57.2812 422.203 56.9557 422.089 56.5234 422.016C56.0911 421.937 55.5469 421.898 54.8906 421.898ZM66.3594 413.992C66.3542 414.831 66.237 415.615 66.0078 416.344C65.7839 417.073 65.4297 417.719 64.9453 418.281C64.4661 418.844 63.8594 419.271 63.125 419.562L62.0547 418.039C62.6797 417.784 63.1979 417.445 63.6094 417.023C64.0208 416.602 64.3203 416.135 64.5078 415.625C64.7005 415.109 64.7969 414.565 64.7969 413.992V413.07H66.3594V413.992ZM66.7031 413.992C66.7031 414.539 66.7917 415.049 66.9687 415.523C67.1458 415.992 67.4219 416.414 67.7969 416.789C68.1771 417.159 68.6615 417.458 69.25 417.687L68.2109 419.211C67.513 418.935 66.9401 418.542 66.4922 418.031C66.0495 417.516 65.7214 416.917 65.5078 416.234C65.2995 415.552 65.1979 414.805 65.2031 413.992V413.07H66.7031V413.992ZM68.8828 413.859H62.5234V412.273H68.8828V413.859ZM74.4687 419.844H72.5703V411.234H74.4687V419.844ZM73.0937 416.289H70.8125V414.68H73.0937V416.289ZM71.4453 419.406H69.5547V411.477H71.4453V419.406ZM69.6094 420.055C70.6094 420.055 71.4792 420.164 72.2187 420.383C72.9635 420.596 73.5365 420.906 73.9375 421.312C74.3385 421.714 74.5391 422.19 74.5391 422.742C74.5391 423.294 74.3385 423.773 73.9375 424.18C73.5365 424.586 72.9635 424.896 72.2187 425.109C71.474 425.328 70.6042 425.437 69.6094 425.437C68.6094 425.437 67.7396 425.328 67 425.109C66.2604 424.896 65.6901 424.586 65.2891 424.18C64.888 423.773 64.6875 423.294 64.6875 422.742C64.6875 422.19 64.888 421.714 65.2891 421.312C65.6901 420.906 66.2604 420.596 67 420.383C67.7396 420.164 68.6094 420.055 69.6094 420.055ZM69.6094 421.57C68.9896 421.57 68.4609 421.615 68.0234 421.703C67.5911 421.786 67.2578 421.919 67.0234 422.102C66.7943 422.279 66.6823 422.492 66.6875 422.742C66.6823 423.003 66.7943 423.221 67.0234 423.398C67.2526 423.57 67.5833 423.701 68.0156 423.789C68.4479 423.872 68.9792 423.917 69.6094 423.922C70.2396 423.917 70.7708 423.872 71.2031 423.789C71.6354 423.701 71.9635 423.57 72.1875 423.398C72.4167 423.221 72.5339 423.003 72.5391 422.742C72.5339 422.492 72.4167 422.279 72.1875 422.102C71.9635 421.919 71.6302 421.786 71.1875 421.703C70.75 421.615 70.224 421.57 69.6094 421.57ZM87.9844 425.477H85.9609V411.203H87.9844V425.477ZM80.2578 412.211C80.9714 412.211 81.612 412.419 82.1797 412.836C82.7526 413.247 83.1979 413.839 83.5156 414.609C83.8385 415.375 84 416.266 84 417.281C84 418.302 83.8385 419.198 83.5156 419.969C83.1979 420.734 82.7526 421.323 82.1797 421.734C81.612 422.146 80.9714 422.352 80.2578 422.352C79.5339 422.357 78.8854 422.154 78.3125 421.742C77.7448 421.326 77.2995 420.734 76.9766 419.969C76.6536 419.198 76.4922 418.302 76.4922 417.281C76.4922 416.266 76.6536 415.375 76.9766 414.609C77.2995 413.839 77.7448 413.247 78.3125 412.836C78.8854 412.419 79.5339 412.211 80.2578 412.211ZM80.2578 414.016C79.888 414.01 79.5625 414.135 79.2812 414.391C79.0052 414.641 78.7917 415.013 78.6406 415.508C78.4948 415.997 78.4245 416.589 78.4297 417.281C78.4245 417.974 78.4948 418.565 78.6406 419.055C78.7917 419.544 79.0052 419.917 79.2812 420.172C79.5625 420.422 79.888 420.547 80.2578 420.547C80.6172 420.547 80.9349 420.422 81.2109 420.172C81.487 419.917 81.7005 419.544 81.8516 419.055C82.0026 418.565 82.0781 417.974 82.0781 417.281C82.0781 416.589 82.0026 415.997 81.8516 415.508C81.7005 415.018 81.487 414.646 81.2109 414.391C80.9349 414.135 80.6172 414.01 80.2578 414.016ZM100.484 412.898C100.479 413.628 100.26 414.292 99.8281 414.891C99.401 415.49 98.7656 415.99 97.9219 416.391C97.0781 416.792 96.0651 417.052 94.8828 417.172L94.1875 415.609C95.1667 415.516 95.9974 415.328 96.6797 415.047C97.3672 414.766 97.8776 414.437 98.2109 414.062C98.5495 413.687 98.7214 413.299 98.7266 412.898V412.492H100.484V412.898ZM101.453 412.898C101.453 413.305 101.622 413.695 101.961 414.07C102.305 414.445 102.82 414.773 103.508 415.055C104.195 415.331 105.036 415.516 106.031 415.609L105.312 417.172C104.13 417.052 103.115 416.794 102.266 416.398C101.422 415.997 100.779 415.497 100.336 414.898C99.8932 414.294 99.6693 413.628 99.6641 412.898V412.492H101.453V412.898ZM105.414 413.312H94.7891V411.734H105.414V413.312ZM106.586 419.734H93.6172V418.148H106.586V419.734ZM101.062 418.852H99.0859V416.273H101.062V418.852ZM105 425.437H103.016V422.344H95.0469V420.758H105V425.437ZM109.836 413.547H112.75V411.852H114.75V418.062H107.859V411.852H109.836V413.547ZM112.75 416.492V415.039H109.836V416.492H112.75ZM118.719 418.453H116.727V411.203H118.719V418.453ZM120.641 415.602H117.891V413.984H120.641V415.602ZM118.719 422.852H111.273V424.555H109.312V421.422H116.734V420.531H109.289V418.992H118.719V422.852ZM119.133 425.336H109.312V423.773H119.133V425.336Z" fill="#56555A"/> -<path d="M314.078 424H312.656V414.156H312.594L309.844 415.984V414.562L312.656 412.687H314.078V424ZM320.797 424.156C319.964 424.156 319.253 423.93 318.664 423.477C318.076 423.023 317.625 422.362 317.312 421.492C317 420.622 316.844 419.573 316.844 418.344C316.844 417.13 317 416.089 317.312 415.219C317.625 414.344 318.076 413.677 318.664 413.219C319.258 412.76 319.969 412.531 320.797 412.531C321.62 412.531 322.328 412.76 322.922 413.219C323.516 413.677 323.969 414.344 324.281 415.219C324.594 416.089 324.75 417.13 324.75 418.344C324.75 419.573 324.596 420.622 324.289 421.492C323.982 422.362 323.531 423.023 322.937 423.477C322.344 423.93 321.63 424.156 320.797 424.156ZM320.797 422.906C321.339 422.906 321.805 422.729 322.195 422.375C322.586 422.021 322.88 421.503 323.078 420.82C323.276 420.138 323.375 419.312 323.375 418.344C323.375 417.375 323.273 416.547 323.07 415.859C322.867 415.172 322.573 414.648 322.187 414.289C321.802 413.93 321.339 413.75 320.797 413.75C320.255 413.75 319.792 413.93 319.406 414.289C319.021 414.648 318.724 415.172 318.516 415.859C318.307 416.547 318.203 417.375 318.203 418.344C318.203 419.312 318.307 420.138 318.516 420.82C318.724 421.503 319.018 422.021 319.398 422.375C319.784 422.729 320.25 422.906 320.797 422.906ZM330.328 424.156C329.495 424.156 328.784 423.93 328.195 423.477C327.607 423.023 327.156 422.362 326.844 421.492C326.531 420.622 326.375 419.573 326.375 418.344C326.375 417.13 326.531 416.089 326.844 415.219C327.156 414.344 327.607 413.677 328.195 413.219C328.789 412.76 329.5 412.531 330.328 412.531C331.151 412.531 331.859 412.76 332.453 413.219C333.047 413.677 333.5 414.344 333.812 415.219C334.125 416.089 334.281 417.13 334.281 418.344C334.281 419.573 334.128 420.622 333.82 421.492C333.513 422.362 333.062 423.023 332.469 423.477C331.875 423.93 331.161 424.156 330.328 424.156ZM330.328 422.906C330.87 422.906 331.336 422.729 331.727 422.375C332.117 422.021 332.411 421.503 332.609 420.82C332.807 420.138 332.906 419.312 332.906 418.344C332.906 417.375 332.805 416.547 332.602 415.859C332.398 415.172 332.104 414.648 331.719 414.289C331.333 413.93 330.87 413.75 330.328 413.75C329.786 413.75 329.323 413.93 328.937 414.289C328.552 414.648 328.255 415.172 328.047 415.859C327.839 416.547 327.734 417.375 327.734 418.344C327.734 419.312 327.839 420.138 328.047 420.82C328.255 421.503 328.549 422.021 328.93 422.375C329.315 422.729 329.781 422.906 330.328 422.906ZM336.312 427.203H335.156L336.016 422.953H337.531L336.312 427.203ZM343.172 424.156C342.339 424.156 341.628 423.93 341.039 423.477C340.451 423.023 340 422.362 339.687 421.492C339.375 420.622 339.219 419.573 339.219 418.344C339.219 417.13 339.375 416.089 339.687 415.219C340 414.344 340.451 413.677 341.039 413.219C341.633 412.76 342.344 412.531 343.172 412.531C343.995 412.531 344.703 412.76 345.297 413.219C345.891 413.677 346.344 414.344 346.656 415.219C346.969 416.089 347.125 417.13 347.125 418.344C347.125 419.573 346.971 420.622 346.664 421.492C346.357 422.362 345.906 423.023 345.312 423.477C344.719 423.93 344.005 424.156 343.172 424.156ZM343.172 422.906C343.714 422.906 344.18 422.729 344.57 422.375C344.961 422.021 345.255 421.503 345.453 420.82C345.651 420.138 345.75 419.312 345.75 418.344C345.75 417.375 345.648 416.547 345.445 415.859C345.242 415.172 344.948 414.648 344.562 414.289C344.177 413.93 343.714 413.75 343.172 413.75C342.63 413.75 342.167 413.93 341.781 414.289C341.396 414.648 341.099 415.172 340.891 415.859C340.682 416.547 340.578 417.375 340.578 418.344C340.578 419.312 340.682 420.138 340.891 420.82C341.099 421.503 341.393 422.021 341.773 422.375C342.159 422.729 342.625 422.906 343.172 422.906ZM352.703 424.156C351.87 424.156 351.159 423.93 350.57 423.477C349.982 423.023 349.531 422.362 349.219 421.492C348.906 420.622 348.75 419.573 348.75 418.344C348.75 417.13 348.906 416.089 349.219 415.219C349.531 414.344 349.982 413.677 350.57 413.219C351.164 412.76 351.875 412.531 352.703 412.531C353.526 412.531 354.234 412.76 354.828 413.219C355.422 413.677 355.875 414.344 356.187 415.219C356.5 416.089 356.656 417.13 356.656 418.344C356.656 419.573 356.503 420.622 356.195 421.492C355.888 422.362 355.437 423.023 354.844 423.477C354.25 423.93 353.536 424.156 352.703 424.156ZM352.703 422.906C353.245 422.906 353.711 422.729 354.102 422.375C354.492 422.021 354.786 421.503 354.984 420.82C355.182 420.138 355.281 419.312 355.281 418.344C355.281 417.375 355.18 416.547 354.977 415.859C354.773 415.172 354.479 414.648 354.094 414.289C353.708 413.93 353.245 413.75 352.703 413.75C352.161 413.75 351.698 413.93 351.312 414.289C350.927 414.648 350.63 415.172 350.422 415.859C350.214 416.547 350.109 417.375 350.109 418.344C350.109 419.312 350.214 420.138 350.422 420.82C350.63 421.503 350.924 422.021 351.305 422.375C351.69 422.729 352.156 422.906 352.703 422.906ZM362.234 424.156C361.401 424.156 360.69 423.93 360.102 423.477C359.513 423.023 359.062 422.362 358.75 421.492C358.437 420.622 358.281 419.573 358.281 418.344C358.281 417.13 358.437 416.089 358.75 415.219C359.062 414.344 359.513 413.677 360.102 413.219C360.695 412.76 361.406 412.531 362.234 412.531C363.057 412.531 363.766 412.76 364.359 413.219C364.953 413.677 365.406 414.344 365.719 415.219C366.031 416.089 366.187 417.13 366.187 418.344C366.187 419.573 366.034 420.622 365.727 421.492C365.419 422.362 364.969 423.023 364.375 423.477C363.781 423.93 363.068 424.156 362.234 424.156ZM362.234 422.906C362.776 422.906 363.242 422.729 363.633 422.375C364.023 422.021 364.318 421.503 364.516 420.82C364.714 420.138 364.812 419.312 364.812 418.344C364.812 417.375 364.711 416.547 364.508 415.859C364.305 415.172 364.01 414.648 363.625 414.289C363.24 413.93 362.776 413.75 362.234 413.75C361.693 413.75 361.229 413.93 360.844 414.289C360.458 414.648 360.161 415.172 359.953 415.859C359.745 416.547 359.641 417.375 359.641 418.344C359.641 419.312 359.745 420.138 359.953 420.82C360.161 421.503 360.456 422.021 360.836 422.375C361.221 422.729 361.687 422.906 362.234 422.906Z" fill="#56555A"/> -<path d="M375.348 423.09H374.422V420.77H375.348V423.09ZM380.012 423.453H379.086V415.543H380.012V423.453ZM380.27 425.727H372.863V424.953H380.27V425.727ZM373.789 425.176H372.863V422.68H373.789V425.176ZM371.363 420.371C372.758 420.363 373.992 420.342 375.066 420.307C376.141 420.268 377.168 420.187 378.148 420.066L378.207 420.734C377.195 420.895 376.135 421 375.025 421.051C373.916 421.102 372.738 421.125 371.492 421.121L371.363 420.371ZM379.332 422.375H376.93V421.707H379.332V422.375ZM374.785 415.965C375.289 415.965 375.736 416.039 376.127 416.187C376.521 416.336 376.826 416.549 377.041 416.826C377.256 417.104 377.363 417.422 377.363 417.781C377.363 418.148 377.256 418.467 377.041 418.736C376.826 419.006 376.523 419.215 376.133 419.363C375.742 419.512 375.293 419.586 374.785 419.586C374.273 419.586 373.822 419.512 373.432 419.363C373.045 419.215 372.744 419.006 372.529 418.736C372.314 418.467 372.207 418.148 372.207 417.781C372.207 417.422 372.314 417.104 372.529 416.826C372.744 416.549 373.047 416.336 373.437 416.187C373.828 416.039 374.277 415.965 374.785 415.965ZM374.785 416.668C374.449 416.664 374.152 416.709 373.895 416.803C373.637 416.893 373.436 417.023 373.291 417.195C373.15 417.367 373.082 417.562 373.086 417.781C373.082 418.004 373.15 418.201 373.291 418.373C373.436 418.541 373.637 418.672 373.895 418.766C374.152 418.859 374.449 418.906 374.785 418.906C375.113 418.906 375.406 418.859 375.664 418.766C375.922 418.672 376.123 418.541 376.268 418.373C376.412 418.201 376.484 418.004 376.484 417.781C376.484 417.562 376.412 417.367 376.268 417.195C376.123 417.023 375.922 416.893 375.664 416.803C375.406 416.709 375.113 416.664 374.785 416.668Z" fill="#56555A"/> -<path d="M382 446H48C43.5817 446 40 449.582 40 454V478C40 482.418 43.5817 486 48 486H382C386.418 486 390 482.418 390 478V454C390 449.582 386.418 446 382 446Z" fill="#F9F8FD"/> -<path d="M61.4297 471.781H48.4297V470.172H61.4297V471.781ZM55.8828 470.57H53.9219V467.086H55.8828V470.57ZM51.8047 462.336H58V460.117H59.9844V467.531H49.8047V460.117H51.8047V462.336ZM58 465.937V463.914H51.8047V465.937H58ZM73.8359 467.398H63.7891V465.805H73.8359V467.398ZM75.2578 471.711H62.2578V470.07H75.2578V471.711ZM73.7344 462.016H65.7578V466.469H63.7891V460.406H73.7344V462.016ZM88.3984 473.437H86.5234V459.203H88.3984V473.437ZM83.8828 466.281H80.7734V464.695H83.8828V466.281ZM85.375 472.812H83.5V459.539H85.375V472.812ZM82.2969 460.906C82.2917 462.318 82.1224 463.596 81.7891 464.742C81.4609 465.888 80.9089 466.945 80.1328 467.914C79.362 468.878 78.3281 469.732 77.0312 470.477L75.9062 469.078C76.9844 468.437 77.849 467.737 78.5 466.977C79.1562 466.211 79.6302 465.367 79.9219 464.445C80.2135 463.523 80.362 462.479 80.3672 461.312V460.906H82.2969ZM81.0078 462.508H76.6875V460.906H81.0078V462.508ZM101.805 467.266H99.8125V459.234H101.805V467.266ZM101.805 473.281H92.2812V467.906H101.805V473.281ZM94.2422 471.68H99.8516V469.484H94.2422V471.68ZM94.0156 459.875C94.7448 459.875 95.4062 460.021 96 460.312C96.5937 460.599 97.0599 461.005 97.3984 461.531C97.737 462.052 97.9062 462.643 97.9062 463.305C97.9062 463.945 97.737 464.526 97.3984 465.047C97.0599 465.562 96.5937 465.969 96 466.266C95.4062 466.557 94.7448 466.703 94.0156 466.703C93.2812 466.703 92.6172 466.557 92.0234 466.266C91.4349 465.969 90.9714 465.562 90.6328 465.047C90.2943 464.526 90.125 463.945 90.125 463.305C90.125 462.643 90.2943 462.052 90.6328 461.531C90.9714 461.005 91.4349 460.599 92.0234 460.312C92.6172 460.021 93.2812 459.875 94.0156 459.875ZM94.0156 461.555C93.6354 461.555 93.2969 461.622 93 461.758C92.7083 461.893 92.4792 462.094 92.3125 462.359C92.151 462.625 92.0703 462.94 92.0703 463.305C92.0703 463.654 92.151 463.958 92.3125 464.219C92.4792 464.474 92.7083 464.672 93 464.812C93.2969 464.953 93.6354 465.023 94.0156 465.023C94.3854 465.023 94.7135 464.953 95 464.812C95.2917 464.672 95.5182 464.474 95.6797 464.219C95.8464 463.958 95.9297 463.654 95.9297 463.305C95.9297 462.94 95.849 462.625 95.6875 462.359C95.526 462.094 95.2995 461.893 95.0078 461.758C94.7161 461.622 94.3854 461.555 94.0156 461.555Z" fill="#56555A"/> -<path d="M320.5 472.156C319.828 472.156 319.216 472.026 318.664 471.766C318.117 471.505 317.68 471.148 317.352 470.695C317.029 470.242 316.854 469.729 316.828 469.156H318.187C318.219 469.49 318.341 469.789 318.555 470.055C318.768 470.32 319.044 470.531 319.383 470.687C319.727 470.844 320.099 470.922 320.5 470.922C320.984 470.922 321.417 470.812 321.797 470.594C322.182 470.375 322.484 470.076 322.703 469.695C322.922 469.315 323.031 468.891 323.031 468.422C323.031 467.937 322.919 467.503 322.695 467.117C322.471 466.727 322.159 466.419 321.758 466.195C321.357 465.971 320.906 465.859 320.406 465.859C319.911 465.849 319.487 465.927 319.133 466.094C318.779 466.255 318.5 466.516 318.297 466.875H316.937L317.734 460.687H323.859V461.937H318.906L318.484 465.25H318.594C318.854 465.052 319.164 464.893 319.523 464.773C319.888 464.654 320.266 464.594 320.656 464.594C321.365 464.594 322.005 464.755 322.578 465.078C323.151 465.401 323.599 465.854 323.922 466.437C324.245 467.016 324.406 467.667 324.406 468.391C324.406 469.109 324.237 469.755 323.898 470.328C323.56 470.901 323.094 471.349 322.5 471.672C321.911 471.995 321.245 472.156 320.5 472.156ZM326.344 470.969L330.203 466.906C330.708 466.365 331.094 465.927 331.359 465.594C331.63 465.26 331.836 464.943 331.977 464.641C332.117 464.333 332.187 464.01 332.187 463.672C332.187 463.292 332.089 462.958 331.891 462.672C331.693 462.38 331.422 462.154 331.078 461.992C330.74 461.831 330.359 461.75 329.937 461.75C329.495 461.75 329.107 461.839 328.773 462.016C328.445 462.193 328.19 462.443 328.008 462.766C327.826 463.083 327.734 463.453 327.734 463.875H326.406C326.401 463.219 326.552 462.638 326.859 462.133C327.172 461.628 327.602 461.234 328.148 460.953C328.695 460.672 329.307 460.531 329.984 460.531C330.656 460.531 331.258 460.669 331.789 460.945C332.326 461.221 332.745 461.599 333.047 462.078C333.349 462.557 333.5 463.089 333.5 463.672C333.495 464.104 333.414 464.518 333.258 464.914C333.107 465.305 332.846 465.74 332.477 466.219C332.107 466.698 331.583 467.286 330.906 467.984L328.312 470.656V470.75H333.703V472H326.359L326.344 470.969ZM336.312 475.203H335.156L336.016 470.953H337.531L336.312 475.203ZM343.172 472.156C342.339 472.156 341.628 471.93 341.039 471.477C340.451 471.023 340 470.362 339.687 469.492C339.375 468.622 339.219 467.573 339.219 466.344C339.219 465.13 339.375 464.089 339.687 463.219C340 462.344 340.451 461.677 341.039 461.219C341.633 460.76 342.344 460.531 343.172 460.531C343.995 460.531 344.703 460.76 345.297 461.219C345.891 461.677 346.344 462.344 346.656 463.219C346.969 464.089 347.125 465.13 347.125 466.344C347.125 467.573 346.971 468.622 346.664 469.492C346.357 470.362 345.906 471.023 345.312 471.477C344.719 471.93 344.005 472.156 343.172 472.156ZM343.172 470.906C343.714 470.906 344.18 470.729 344.57 470.375C344.961 470.021 345.255 469.503 345.453 468.82C345.651 468.138 345.75 467.312 345.75 466.344C345.75 465.375 345.648 464.547 345.445 463.859C345.242 463.172 344.948 462.648 344.562 462.289C344.177 461.93 343.714 461.75 343.172 461.75C342.63 461.75 342.167 461.93 341.781 462.289C341.396 462.648 341.099 463.172 340.891 463.859C340.682 464.547 340.578 465.375 340.578 466.344C340.578 467.312 340.682 468.138 340.891 468.82C341.099 469.503 341.393 470.021 341.773 470.375C342.159 470.729 342.625 470.906 343.172 470.906ZM352.703 472.156C351.87 472.156 351.159 471.93 350.57 471.477C349.982 471.023 349.531 470.362 349.219 469.492C348.906 468.622 348.75 467.573 348.75 466.344C348.75 465.13 348.906 464.089 349.219 463.219C349.531 462.344 349.982 461.677 350.57 461.219C351.164 460.76 351.875 460.531 352.703 460.531C353.526 460.531 354.234 460.76 354.828 461.219C355.422 461.677 355.875 462.344 356.187 463.219C356.5 464.089 356.656 465.13 356.656 466.344C356.656 467.573 356.503 468.622 356.195 469.492C355.888 470.362 355.437 471.023 354.844 471.477C354.25 471.93 353.536 472.156 352.703 472.156ZM352.703 470.906C353.245 470.906 353.711 470.729 354.102 470.375C354.492 470.021 354.786 469.503 354.984 468.82C355.182 468.138 355.281 467.312 355.281 466.344C355.281 465.375 355.18 464.547 354.977 463.859C354.773 463.172 354.479 462.648 354.094 462.289C353.708 461.93 353.245 461.75 352.703 461.75C352.161 461.75 351.698 461.93 351.312 462.289C350.927 462.648 350.63 463.172 350.422 463.859C350.214 464.547 350.109 465.375 350.109 466.344C350.109 467.312 350.214 468.138 350.422 468.82C350.63 469.503 350.924 470.021 351.305 470.375C351.69 470.729 352.156 470.906 352.703 470.906ZM362.234 472.156C361.401 472.156 360.69 471.93 360.102 471.477C359.513 471.023 359.062 470.362 358.75 469.492C358.437 468.622 358.281 467.573 358.281 466.344C358.281 465.13 358.437 464.089 358.75 463.219C359.062 462.344 359.513 461.677 360.102 461.219C360.695 460.76 361.406 460.531 362.234 460.531C363.057 460.531 363.766 460.76 364.359 461.219C364.953 461.677 365.406 462.344 365.719 463.219C366.031 464.089 366.187 465.13 366.187 466.344C366.187 467.573 366.034 468.622 365.727 469.492C365.419 470.362 364.969 471.023 364.375 471.477C363.781 471.93 363.068 472.156 362.234 472.156ZM362.234 470.906C362.776 470.906 363.242 470.729 363.633 470.375C364.023 470.021 364.318 469.503 364.516 468.82C364.714 468.138 364.812 467.312 364.812 466.344C364.812 465.375 364.711 464.547 364.508 463.859C364.305 463.172 364.01 462.648 363.625 462.289C363.24 461.93 362.776 461.75 362.234 461.75C361.693 461.75 361.229 461.93 360.844 462.289C360.458 462.648 360.161 463.172 359.953 463.859C359.745 464.547 359.641 465.375 359.641 466.344C359.641 467.312 359.745 468.138 359.953 468.82C360.161 469.503 360.456 470.021 360.836 470.375C361.221 470.729 361.687 470.906 362.234 470.906Z" fill="#56555A"/> -<path d="M375.348 471.09H374.422V468.77H375.348V471.09ZM380.012 471.453H379.086V463.543H380.012V471.453ZM380.27 473.727H372.863V472.953H380.27V473.727ZM373.789 473.176H372.863V470.68H373.789V473.176ZM371.363 468.371C372.758 468.363 373.992 468.342 375.066 468.307C376.141 468.268 377.168 468.187 378.148 468.066L378.207 468.734C377.195 468.895 376.135 469 375.025 469.051C373.916 469.102 372.738 469.125 371.492 469.121L371.363 468.371ZM379.332 470.375H376.93V469.707H379.332V470.375ZM374.785 463.965C375.289 463.965 375.736 464.039 376.127 464.187C376.521 464.336 376.826 464.549 377.041 464.826C377.256 465.104 377.363 465.422 377.363 465.781C377.363 466.148 377.256 466.467 377.041 466.736C376.826 467.006 376.523 467.215 376.133 467.363C375.742 467.512 375.293 467.586 374.785 467.586C374.273 467.586 373.822 467.512 373.432 467.363C373.045 467.215 372.744 467.006 372.529 466.736C372.314 466.467 372.207 466.148 372.207 465.781C372.207 465.422 372.314 465.104 372.529 464.826C372.744 464.549 373.047 464.336 373.437 464.187C373.828 464.039 374.277 463.965 374.785 463.965ZM374.785 464.668C374.449 464.664 374.152 464.709 373.895 464.803C373.637 464.893 373.436 465.023 373.291 465.195C373.15 465.367 373.082 465.562 373.086 465.781C373.082 466.004 373.15 466.201 373.291 466.373C373.436 466.541 373.637 466.672 373.895 466.766C374.152 466.859 374.449 466.906 374.785 466.906C375.113 466.906 375.406 466.859 375.664 466.766C375.922 466.672 376.123 466.541 376.268 466.373C376.412 466.201 376.484 466.004 376.484 465.781C376.484 465.562 376.412 465.367 376.268 465.195C376.123 465.023 375.922 464.893 375.664 464.803C375.406 464.709 375.113 464.664 374.785 464.668Z" fill="#56555A"/> -<path d="M58.0488 503.953H48.3223V502.764H58.0488V503.953ZM53.9062 503.314H52.4238V501.732H53.9062V503.314ZM53.9062 499.014H52.4238V497.443H53.9062V499.014ZM53.6426 499.277C53.6426 499.82 53.4687 500.303 53.1211 500.725C52.7773 501.143 52.2715 501.482 51.6035 501.744C50.9355 502.006 50.127 502.17 49.1777 502.236L48.7207 501.111C49.5371 501.057 50.2168 500.939 50.7598 500.76C51.3027 500.576 51.6992 500.357 51.9492 500.104C52.2031 499.85 52.3301 499.574 52.3301 499.277V499.066H53.6426V499.277ZM54.0059 499.277C54.002 499.57 54.127 499.846 54.3809 500.104C54.6348 500.357 55.0312 500.576 55.5703 500.76C56.1133 500.939 56.793 501.057 57.6094 501.111L57.1582 502.236C56.209 502.17 55.4004 502.006 54.7324 501.744C54.0645 501.482 53.5566 501.143 53.209 500.725C52.8613 500.303 52.6895 499.82 52.6934 499.277V499.066H54.0059V499.277ZM57.1055 499.547H49.2539V498.363H57.1055V499.547ZM53.168 504.451C53.9453 504.451 54.6113 504.521 55.166 504.662C55.7207 504.803 56.1445 505.008 56.4375 505.277C56.7305 505.547 56.8789 505.875 56.8828 506.262C56.8789 506.652 56.7305 506.982 56.4375 507.252C56.1445 507.525 55.7207 507.73 55.166 507.867C54.6113 508.008 53.9453 508.078 53.168 508.078C52.3828 508.078 51.7109 508.008 51.1523 507.867C50.5977 507.73 50.1719 507.525 49.875 507.252C49.5781 506.982 49.4297 506.652 49.4297 506.262C49.4297 505.875 49.5781 505.547 49.875 505.277C50.1719 505.008 50.5977 504.803 51.1523 504.662C51.7109 504.521 52.3828 504.451 53.168 504.451ZM53.168 505.559C52.6641 505.555 52.248 505.58 51.9199 505.635C51.5957 505.686 51.3516 505.764 51.1875 505.869C51.0273 505.971 50.9492 506.102 50.9531 506.262C50.9492 506.426 51.0273 506.561 51.1875 506.666C51.3516 506.768 51.5957 506.844 51.9199 506.895C52.248 506.945 52.6641 506.971 53.168 506.971C53.6602 506.971 54.0684 506.945 54.3926 506.895C54.7207 506.844 54.9668 506.768 55.1309 506.666C55.2949 506.561 55.377 506.426 55.377 506.262C55.377 506.102 55.2949 505.971 55.1309 505.869C54.9668 505.764 54.7207 505.686 54.3926 505.635C54.0684 505.58 53.6602 505.555 53.168 505.559ZM61.1836 498.053C61.6523 498.053 62.0742 498.164 62.4492 498.387C62.8242 498.605 63.1172 498.914 63.3281 499.312C63.543 499.707 63.6504 500.156 63.6504 500.66C63.6504 501.168 63.543 501.617 63.3281 502.008C63.1172 502.398 62.8242 502.703 62.4492 502.922C62.0742 503.141 61.6523 503.25 61.1836 503.25C60.7148 503.25 60.2949 503.141 59.9238 502.922C59.5527 502.703 59.2617 502.398 59.0508 502.008C58.8437 501.617 58.7402 501.168 58.7402 500.66C58.7402 500.16 58.8437 499.711 59.0508 499.312C59.2617 498.914 59.5527 498.605 59.9238 498.387C60.2949 498.164 60.7148 498.053 61.1836 498.053ZM61.1836 499.33C60.9648 499.33 60.7715 499.383 60.6035 499.488C60.4355 499.59 60.3047 499.742 60.2109 499.945C60.1172 500.145 60.0723 500.383 60.0762 500.66C60.0723 500.937 60.1172 501.178 60.2109 501.381C60.3047 501.58 60.4355 501.734 60.6035 501.844C60.7715 501.953 60.9648 502.008 61.1836 502.008C61.3984 502.008 61.5898 501.953 61.7578 501.844C61.9297 501.734 62.0605 501.58 62.1504 501.381C62.2441 501.178 62.291 500.937 62.291 500.66C62.291 500.383 62.2441 500.145 62.1504 499.945C62.0605 499.742 61.9316 499.59 61.7637 499.488C61.5957 499.383 61.4023 499.33 61.1836 499.33ZM67.8516 503.795H66.4277V497.426H67.8516V503.795ZM66.832 501.205H65.1035V500.01H66.832V501.205ZM65.5605 503.736H64.166V497.607H65.5605V503.736ZM67.8516 508.078H66.3691V505.453H60.4805V504.264H67.8516V508.078Z" fill="#56555A"/> -<path d="M327.797 507H326.73V499.617H326.684L324.621 500.988V499.922L326.73 498.516H327.797V507ZM332.836 507.117C332.211 507.117 331.678 506.947 331.236 506.607C330.795 506.268 330.457 505.771 330.223 505.119C329.988 504.467 329.871 503.68 329.871 502.758C329.871 501.848 329.988 501.066 330.223 500.414C330.457 499.758 330.795 499.258 331.236 498.914C331.682 498.57 332.215 498.398 332.836 498.398C333.453 498.398 333.984 498.57 334.43 498.914C334.875 499.258 335.215 499.758 335.449 500.414C335.684 501.066 335.801 501.848 335.801 502.758C335.801 503.68 335.686 504.467 335.455 505.119C335.225 505.771 334.887 506.268 334.441 506.607C333.996 506.947 333.461 507.117 332.836 507.117ZM332.836 506.18C333.242 506.18 333.592 506.047 333.885 505.781C334.178 505.516 334.398 505.127 334.547 504.615C334.695 504.104 334.77 503.484 334.77 502.758C334.77 502.031 334.693 501.41 334.541 500.895C334.389 500.379 334.168 499.986 333.879 499.717C333.59 499.447 333.242 499.312 332.836 499.312C332.43 499.312 332.082 499.447 331.793 499.717C331.504 499.986 331.281 500.379 331.125 500.895C330.969 501.41 330.891 502.031 330.891 502.758C330.891 503.484 330.969 504.104 331.125 504.615C331.281 505.127 331.502 505.516 331.787 505.781C332.076 506.047 332.426 506.18 332.836 506.18ZM336.996 504.398L340.816 498.516H341.449V499.852H341.004L338.133 504.27V504.34H343.301V505.266H336.996V504.398ZM341.109 505.008V504.598V498.516H342.117V507H341.109V505.008ZM344.73 509.402H343.863L344.508 506.215H345.645L344.73 509.402ZM349.875 507.117C349.25 507.117 348.717 506.947 348.275 506.607C347.834 506.268 347.496 505.771 347.262 505.119C347.027 504.467 346.91 503.68 346.91 502.758C346.91 501.848 347.027 501.066 347.262 500.414C347.496 499.758 347.834 499.258 348.275 498.914C348.721 498.57 349.254 498.398 349.875 498.398C350.492 498.398 351.023 498.57 351.469 498.914C351.914 499.258 352.254 499.758 352.488 500.414C352.723 501.066 352.84 501.848 352.84 502.758C352.84 503.68 352.725 504.467 352.494 505.119C352.264 505.771 351.926 506.268 351.48 506.607C351.035 506.947 350.5 507.117 349.875 507.117ZM349.875 506.18C350.281 506.18 350.631 506.047 350.924 505.781C351.217 505.516 351.437 505.127 351.586 504.615C351.734 504.104 351.809 503.484 351.809 502.758C351.809 502.031 351.732 501.41 351.58 500.895C351.428 500.379 351.207 499.986 350.918 499.717C350.629 499.447 350.281 499.312 349.875 499.312C349.469 499.312 349.121 499.447 348.832 499.717C348.543 499.986 348.32 500.379 348.164 500.895C348.008 501.41 347.93 502.031 347.93 502.758C347.93 503.484 348.008 504.104 348.164 504.615C348.32 505.127 348.541 505.516 348.826 505.781C349.115 506.047 349.465 506.18 349.875 506.18ZM357.023 507.117C356.398 507.117 355.865 506.947 355.424 506.607C354.982 506.268 354.645 505.771 354.41 505.119C354.176 504.467 354.059 503.68 354.059 502.758C354.059 501.848 354.176 501.066 354.41 500.414C354.645 499.758 354.982 499.258 355.424 498.914C355.869 498.57 356.402 498.398 357.023 498.398C357.641 498.398 358.172 498.57 358.617 498.914C359.062 499.258 359.402 499.758 359.637 500.414C359.871 501.066 359.988 501.848 359.988 502.758C359.988 503.68 359.873 504.467 359.643 505.119C359.412 505.771 359.074 506.268 358.629 506.607C358.184 506.947 357.648 507.117 357.023 507.117ZM357.023 506.18C357.43 506.18 357.779 506.047 358.072 505.781C358.365 505.516 358.586 505.127 358.734 504.615C358.883 504.104 358.957 503.484 358.957 502.758C358.957 502.031 358.881 501.41 358.729 500.895C358.576 500.379 358.355 499.986 358.066 499.717C357.777 499.447 357.43 499.312 357.023 499.312C356.617 499.312 356.27 499.447 355.98 499.717C355.691 499.986 355.469 500.379 355.312 500.895C355.156 501.41 355.078 502.031 355.078 502.758C355.078 503.484 355.156 504.104 355.312 504.615C355.469 505.127 355.689 505.516 355.975 505.781C356.264 506.047 356.613 506.18 357.023 506.18ZM364.172 507.117C363.547 507.117 363.014 506.947 362.572 506.607C362.131 506.268 361.793 505.771 361.559 505.119C361.324 504.467 361.207 503.68 361.207 502.758C361.207 501.848 361.324 501.066 361.559 500.414C361.793 499.758 362.131 499.258 362.572 498.914C363.018 498.57 363.551 498.398 364.172 498.398C364.789 498.398 365.32 498.57 365.766 498.914C366.211 499.258 366.551 499.758 366.785 500.414C367.02 501.066 367.137 501.848 367.137 502.758C367.137 503.68 367.021 504.467 366.791 505.119C366.561 505.771 366.223 506.268 365.777 506.607C365.332 506.947 364.797 507.117 364.172 507.117ZM364.172 506.18C364.578 506.18 364.928 506.047 365.221 505.781C365.514 505.516 365.734 505.127 365.883 504.615C366.031 504.104 366.105 503.484 366.105 502.758C366.105 502.031 366.029 501.41 365.877 500.895C365.725 500.379 365.504 499.986 365.215 499.717C364.926 499.447 364.578 499.312 364.172 499.312C363.766 499.312 363.418 499.447 363.129 499.717C362.84 499.986 362.617 500.379 362.461 500.895C362.305 501.41 362.227 502.031 362.227 502.758C362.227 503.484 362.305 504.104 362.461 504.615C362.617 505.127 362.838 505.516 363.123 505.781C363.412 506.047 363.762 506.18 364.172 506.18ZM375.105 505.09H374.18V502.77H375.105V505.09ZM379.77 505.453H378.844V497.543H379.77V505.453ZM380.027 507.727H372.621V506.953H380.027V507.727ZM373.547 507.176H372.621V504.68H373.547V507.176ZM371.121 502.371C372.516 502.363 373.75 502.342 374.824 502.307C375.898 502.268 376.926 502.187 377.906 502.066L377.965 502.734C376.953 502.895 375.893 503 374.783 503.051C373.674 503.102 372.496 503.125 371.25 503.121L371.121 502.371ZM379.09 504.375H376.687V503.707H379.09V504.375ZM374.543 497.965C375.047 497.965 375.494 498.039 375.885 498.187C376.279 498.336 376.584 498.549 376.799 498.826C377.014 499.104 377.121 499.422 377.121 499.781C377.121 500.148 377.014 500.467 376.799 500.736C376.584 501.006 376.281 501.215 375.891 501.363C375.5 501.512 375.051 501.586 374.543 501.586C374.031 501.586 373.58 501.512 373.189 501.363C372.803 501.215 372.502 501.006 372.287 500.736C372.072 500.467 371.965 500.148 371.965 499.781C371.965 499.422 372.072 499.104 372.287 498.826C372.502 498.549 372.805 498.336 373.195 498.187C373.586 498.039 374.035 497.965 374.543 497.965ZM374.543 498.668C374.207 498.664 373.91 498.709 373.652 498.803C373.395 498.893 373.193 499.023 373.049 499.195C372.908 499.367 372.84 499.562 372.844 499.781C372.84 500.004 372.908 500.201 373.049 500.373C373.193 500.541 373.395 500.672 373.652 500.766C373.91 500.859 374.207 500.906 374.543 500.906C374.871 500.906 375.164 500.859 375.422 500.766C375.68 500.672 375.881 500.541 376.025 500.373C376.17 500.201 376.242 500.004 376.242 499.781C376.242 499.562 376.17 499.367 376.025 499.195C375.881 499.023 375.68 498.893 375.422 498.803C375.164 498.709 374.871 498.664 374.543 498.668Z" fill="#B2B1B6"/> -<path d="M390 528H40C35.5817 528 32 531.582 32 536V560C32 564.418 35.5817 568 40 568H390C394.418 568 398 564.418 398 560V536C398 531.582 394.418 528 390 528Z" fill="white"/> -<path d="M53.4297 553.742H40.4297V552.148H53.4297V553.742ZM47.8437 552.57H45.8594V548.922H47.8437V552.57ZM47.5312 543.047C47.5312 544.062 47.2891 545.01 46.8047 545.891C46.3255 546.766 45.6354 547.51 44.7344 548.125C43.8385 548.74 42.7891 549.159 41.5859 549.383L40.7266 547.719C41.763 547.557 42.6641 547.237 43.4297 546.758C44.1953 546.273 44.776 545.708 45.1719 545.062C45.5729 544.411 45.776 543.74 45.7812 543.047V542.039H47.5312V543.047ZM47.8984 543.047C47.8984 543.745 48.099 544.419 48.5 545.07C48.9062 545.716 49.4922 546.279 50.2578 546.758C51.0286 547.237 51.9375 547.557 52.9844 547.719L52.1328 549.383C50.9245 549.159 49.8698 548.745 48.9687 548.141C48.0677 547.531 47.375 546.789 46.8906 545.914C46.4062 545.034 46.1667 544.078 46.1719 543.047V542.039H47.8984V543.047ZM64.9609 544.82H60.7422V543.219H64.9609V544.82ZM64.9609 548.258H60.7422V546.664H64.9609V548.258ZM66.2344 551.633H64.25V541.234H66.2344V551.633ZM66.5781 555.195H56.7969V553.586H66.5781V555.195ZM58.7969 554.406H56.7969V550.578H58.7969V554.406ZM58.2187 542.055C58.9062 542.055 59.5365 542.214 60.1094 542.531C60.6875 542.849 61.1432 543.289 61.4766 543.852C61.8099 544.414 61.9792 545.047 61.9844 545.75C61.9792 546.443 61.8073 547.068 61.4687 547.625C61.1354 548.182 60.6823 548.622 60.1094 548.945C59.5365 549.263 58.9062 549.422 58.2187 549.422C57.5052 549.422 56.8594 549.263 56.2812 548.945C55.7083 548.622 55.2552 548.182 54.9219 547.625C54.5937 547.068 54.4297 546.443 54.4297 545.75C54.4297 545.047 54.5937 544.414 54.9219 543.852C55.2552 543.289 55.7083 542.849 56.2812 542.531C56.8594 542.214 57.5052 542.055 58.2187 542.055ZM58.2187 543.828C57.849 543.823 57.5208 543.898 57.2344 544.055C56.9479 544.211 56.724 544.435 56.5625 544.727C56.401 545.018 56.3203 545.359 56.3203 545.75C56.3203 546.135 56.401 546.471 56.5625 546.758C56.724 547.044 56.9479 547.266 57.2344 547.422C57.5208 547.573 57.849 547.651 58.2187 547.656C58.5729 547.651 58.8906 547.573 59.1719 547.422C59.4531 547.266 59.6745 547.044 59.8359 546.758C59.9974 546.471 60.0781 546.135 60.0781 545.75C60.0781 545.359 59.9974 545.021 59.8359 544.734C59.6745 544.443 59.4531 544.219 59.1719 544.062C58.8906 543.901 58.5729 543.823 58.2187 543.828ZM69.7266 557.297H68.0703L68.8437 552.852H71.0781L69.7266 557.297ZM83.9297 547.648H81.5078V546.016H83.9297V547.648ZM80.0156 544.891C80.0156 546.005 79.901 547.06 79.6719 548.055C79.4479 549.044 79.0964 549.937 78.6172 550.734C78.1432 551.526 77.5417 552.143 76.8125 552.586L75.5937 551.102C76.2656 550.69 76.8177 550.156 77.25 549.5C77.6823 548.839 77.9948 548.12 78.1875 547.344C78.3854 546.568 78.4844 545.75 78.4844 544.891V542.437H80.0156V544.891ZM80.4141 544.797C80.4141 545.641 80.4974 546.43 80.6641 547.164C80.8307 547.893 81.1068 548.57 81.4922 549.195C81.8776 549.815 82.3802 550.326 83 550.727L81.9219 552.258C81.1979 551.82 80.612 551.216 80.1641 550.445C79.7161 549.674 79.3958 548.818 79.2031 547.875C79.0104 546.927 78.9167 545.901 78.9219 544.797V542.437H80.4141V544.797ZM88.1875 555.437H86.2734V541.203H88.1875V555.437ZM85.2109 554.781H83.3437V541.422H85.2109V554.781ZM101.672 552.062H99.6875V541.234H101.672V552.062ZM100.43 546.375H97.7656V544.766H100.43V546.375ZM100.43 549.383H97.7656V547.797H100.43V549.383ZM97.6172 544.289H89.7187V542.719H97.6172V544.289ZM93.75 544.789C94.3906 544.789 94.9661 544.909 95.4766 545.148C95.9922 545.383 96.3932 545.714 96.6797 546.141C96.9714 546.568 97.1172 547.049 97.1172 547.586C97.1172 548.128 96.9714 548.612 96.6797 549.039C96.3932 549.461 95.9948 549.792 95.4844 550.031C94.974 550.266 94.3958 550.383 93.75 550.383C93.1146 550.383 92.5443 550.266 92.0391 550.031C91.5339 549.792 91.1354 549.461 90.8437 549.039C90.5573 548.612 90.4167 548.128 90.4219 547.586C90.4167 547.049 90.5573 546.57 90.8437 546.148C91.1354 545.721 91.5339 545.388 92.0391 545.148C92.5443 544.909 93.1146 544.789 93.75 544.789ZM93.75 546.344C93.4583 546.349 93.2005 546.401 92.9766 546.5C92.7578 546.594 92.5859 546.734 92.4609 546.922C92.3359 547.109 92.2734 547.331 92.2734 547.586C92.2734 547.857 92.3359 548.086 92.4609 548.273C92.5859 548.461 92.7578 548.604 92.9766 548.703C93.2005 548.802 93.4583 548.852 93.75 548.852C94.0417 548.852 94.2995 548.802 94.5234 548.703C94.7474 548.604 94.9219 548.461 95.0469 548.273C95.1771 548.081 95.2422 547.852 95.2422 547.586C95.2422 547.331 95.1771 547.109 95.0469 546.922C94.9219 546.729 94.7474 546.586 94.5234 546.492C94.2995 546.398 94.0417 546.349 93.75 546.344ZM94.7656 543.687H92.7734V541.195H94.7656V543.687ZM101.977 555.195H92.2031V553.586H101.977V555.195ZM94.2187 554.328H92.2031V551.133H94.2187V554.328ZM105.164 557.297H103.508L104.281 552.852H106.516L105.164 557.297ZM116.477 544.031C116.471 544.937 116.315 545.789 116.008 546.586C115.706 547.378 115.247 548.07 114.633 548.664C114.018 549.258 113.271 549.701 112.391 549.992L111.359 548.43C112.12 548.19 112.758 547.841 113.273 547.383C113.794 546.924 114.18 546.409 114.43 545.836C114.685 545.258 114.812 544.656 114.812 544.031V542.789H116.477V544.031ZM116.836 544.031C116.836 544.62 116.958 545.185 117.203 545.727C117.453 546.268 117.833 546.755 118.344 547.187C118.854 547.615 119.482 547.94 120.227 548.164L119.219 549.734C118.349 549.453 117.615 549.031 117.016 548.469C116.417 547.901 115.963 547.237 115.656 546.477C115.354 545.716 115.206 544.901 115.211 544.031V542.789H116.836V544.031ZM119.703 543.828H111.883V542.234H119.703V543.828ZM123.195 551.508H121.203V541.234H123.195V551.508ZM123.586 555.195H113.672V553.586H123.586V555.195ZM115.687 554.391H113.672V550.57H115.687V554.391ZM137.516 544.609H125.68V543.016H137.516V544.609ZM138.133 553.992H125.133V552.383H138.133V553.992ZM132.578 553.008H130.602V550.469H132.578V553.008ZM131.594 545.227C132.573 545.227 133.427 545.336 134.156 545.555C134.891 545.773 135.453 546.094 135.844 546.516C136.24 546.932 136.437 547.424 136.437 547.992C136.437 548.57 136.24 549.07 135.844 549.492C135.453 549.909 134.893 550.232 134.164 550.461C133.435 550.685 132.578 550.799 131.594 550.805C130.594 550.799 129.729 550.685 129 550.461C128.271 550.232 127.708 549.909 127.312 549.492C126.922 549.07 126.729 548.57 126.734 547.992C126.729 547.419 126.922 546.924 127.312 546.508C127.708 546.091 128.271 545.773 129 545.555C129.734 545.336 130.599 545.227 131.594 545.227ZM131.594 546.781C130.969 546.786 130.448 546.833 130.031 546.922C129.62 547.005 129.307 547.138 129.094 547.32C128.88 547.497 128.776 547.721 128.781 547.992C128.776 548.263 128.88 548.49 129.094 548.672C129.307 548.849 129.62 548.984 130.031 549.078C130.448 549.167 130.969 549.211 131.594 549.211C132.203 549.211 132.714 549.167 133.125 549.078C133.542 548.984 133.857 548.849 134.07 548.672C134.284 548.49 134.391 548.263 134.391 547.992C134.391 547.721 134.284 547.497 134.07 547.32C133.857 547.138 133.542 547.005 133.125 546.922C132.714 546.833 132.203 546.786 131.594 546.781ZM132.578 544.008H130.602V541.359H132.578V544.008ZM140.602 557.297H138.945L139.719 552.852H141.953L140.602 557.297ZM148.211 550.523C149.383 550.518 150.331 550.497 151.055 550.461C151.779 550.424 152.521 550.352 153.281 550.242L153.43 551.875C152.643 552 151.865 552.083 151.094 552.125C150.328 552.167 149.367 552.185 148.211 552.18H147.219V550.523H148.211ZM153.008 544.273H149.117V551.195H147.219V542.711H153.008V544.273ZM152.734 547.961H148.578V546.43H152.734V547.961ZM159.062 555.437H157.148V541.203H159.062V555.437ZM157.781 548.328H155.375V546.727H157.781V548.328ZM155.93 554.781H154.039V541.422H155.93V554.781ZM173.539 550.766H160.57V549.195H173.539V550.766ZM168.211 552.523H166.242V550.344H168.211V552.523ZM172.125 555.195H162.07V553.617H172.125V555.195ZM164.07 554.602H162.07V551.641H164.07V554.602ZM172.852 543.906H161.18V542.414H172.852V543.906ZM167.047 544.297C168.573 544.297 169.75 544.482 170.578 544.852C171.406 545.216 171.82 545.747 171.82 546.445C171.82 546.919 171.635 547.32 171.266 547.648C170.896 547.971 170.352 548.219 169.633 548.391C168.919 548.562 168.057 548.648 167.047 548.648C166.031 548.648 165.167 548.562 164.453 548.391C163.74 548.219 163.195 547.971 162.82 547.648C162.445 547.32 162.258 546.919 162.258 546.445C162.258 545.747 162.672 545.216 163.5 544.852C164.333 544.482 165.516 544.297 167.047 544.297ZM167.047 545.687C166.396 545.682 165.87 545.706 165.469 545.758C165.068 545.81 164.771 545.893 164.578 546.008C164.385 546.122 164.292 546.268 164.297 546.445C164.292 546.633 164.385 546.784 164.578 546.898C164.771 547.008 165.065 547.091 165.461 547.148C165.862 547.201 166.391 547.227 167.047 547.227C167.693 547.227 168.214 547.201 168.609 547.148C169.005 547.091 169.299 547.008 169.492 546.898C169.69 546.784 169.789 546.633 169.789 546.445C169.789 546.268 169.69 546.122 169.492 546.008C169.299 545.893 169.005 545.81 168.609 545.758C168.214 545.706 167.693 545.682 167.047 545.687ZM168.039 543.359H166.039V541.141H168.039V543.359ZM191.094 548.336H178.102V546.773H191.094V548.336ZM189.539 545.984H179.711V544.414H189.539V545.984ZM189.437 543.086H181.703V545.75H179.711V541.508H189.437V543.086ZM189.484 552.883H181.562V554.164H179.602V551.469H187.516V550.672H179.594V549.172H189.484V552.883ZM189.859 555.32H179.602V553.773H189.859V555.32ZM195.844 542.211C196.552 542.211 197.185 542.419 197.742 542.836C198.305 543.247 198.742 543.839 199.055 544.609C199.367 545.375 199.523 546.266 199.523 547.281C199.523 548.302 199.367 549.198 199.055 549.969C198.742 550.734 198.305 551.323 197.742 551.734C197.185 552.146 196.552 552.352 195.844 552.352C195.125 552.352 194.487 552.146 193.93 551.734C193.372 551.323 192.935 550.734 192.617 549.969C192.299 549.198 192.141 548.302 192.141 547.281C192.141 546.266 192.299 545.375 192.617 544.609C192.935 543.839 193.372 543.247 193.93 542.836C194.487 542.419 195.125 542.211 195.844 542.211ZM195.844 544.016C195.484 544.01 195.172 544.135 194.906 544.391C194.641 544.646 194.432 545.018 194.281 545.508C194.13 545.997 194.057 546.589 194.062 547.281C194.057 547.974 194.13 548.565 194.281 549.055C194.432 549.544 194.641 549.917 194.906 550.172C195.172 550.422 195.484 550.547 195.844 550.547C196.203 550.547 196.518 550.422 196.789 550.172C197.06 549.917 197.268 549.544 197.414 549.055C197.56 548.565 197.633 547.974 197.633 547.281C197.633 546.589 197.56 545.997 197.414 545.508C197.268 545.013 197.06 544.641 196.789 544.391C196.518 544.135 196.203 544.01 195.844 544.016ZM203.922 555.477H201.945V541.203H203.922V555.477ZM202.797 547.953H198.93V546.352H202.797V547.953ZM213.187 548.516H211.227V546.398H213.187V548.516ZM212.234 541.422C213.281 541.422 214.193 541.534 214.969 541.758C215.75 541.977 216.349 542.294 216.766 542.711C217.187 543.128 217.398 543.617 217.398 544.18C217.398 544.742 217.187 545.232 216.766 545.648C216.349 546.065 215.753 546.385 214.977 546.609C214.201 546.828 213.286 546.935 212.234 546.93C211.187 546.935 210.273 546.828 209.492 546.609C208.711 546.385 208.107 546.065 207.68 545.648C207.258 545.232 207.047 544.742 207.047 544.18C207.047 543.617 207.26 543.128 207.687 542.711C208.115 542.294 208.716 541.977 209.492 541.758C210.273 541.534 211.187 541.422 212.234 541.422ZM212.234 542.953C211.573 542.953 211.008 543 210.539 543.094C210.076 543.182 209.721 543.32 209.477 543.508C209.237 543.69 209.117 543.914 209.117 544.18C209.117 544.456 209.237 544.687 209.477 544.875C209.721 545.057 210.073 545.195 210.531 545.289C210.995 545.378 211.562 545.422 212.234 545.422C212.896 545.422 213.458 545.378 213.922 545.289C214.391 545.195 214.745 545.057 214.984 544.875C215.224 544.687 215.344 544.456 215.344 544.18C215.344 543.914 215.221 543.69 214.977 543.508C214.732 543.32 214.378 543.182 213.914 543.094C213.451 543 212.891 542.953 212.234 542.953ZM217.172 555.281H207.258V550.43H217.172V555.281ZM209.219 553.68H215.219V552.008H209.219V553.68ZM218.727 549.492H205.758V547.914H218.727V549.492Z" fill="#56555A"/> -<path d="M386 576H44C37.3726 576 32 581.373 32 588V720C32 726.627 37.3726 732 44 732H386C392.627 732 398 726.627 398 720V588C398 581.373 392.627 576 386 576Z" fill="white"/> -<path d="M48.6562 595.729L51.709 592.922C52.0059 592.633 52.2383 592.393 52.4062 592.201C52.5742 592.01 52.7031 591.818 52.793 591.627C52.8828 591.436 52.9277 591.23 52.9277 591.012C52.9277 590.77 52.8691 590.557 52.752 590.373C52.6348 590.189 52.4746 590.049 52.2715 589.951C52.0684 589.85 51.8379 589.799 51.5801 589.799C51.3145 589.799 51.082 589.852 50.8828 589.957C50.6875 590.062 50.5352 590.215 50.4258 590.414C50.3164 590.613 50.2617 590.848 50.2617 591.117H48.5859C48.5859 590.57 48.7109 590.092 48.9609 589.682C49.2109 589.271 49.5645 588.955 50.0215 588.732C50.4785 588.51 51.0039 588.398 51.5977 588.398C52.1953 588.398 52.7227 588.504 53.1797 588.715C53.6406 588.926 53.9961 589.221 54.2461 589.6C54.4961 589.979 54.6211 590.412 54.6211 590.9C54.6211 591.236 54.5566 591.559 54.4277 591.867C54.3027 592.172 54.0801 592.514 53.7598 592.893C53.4395 593.268 52.9883 593.719 52.4062 594.246L51.1113 595.494V595.553H54.7441V597H48.6621L48.6562 595.729ZM59.1914 590.76C59.1875 591.525 59.0742 592.262 58.8516 592.969C58.6289 593.676 58.2969 594.307 57.8555 594.861C57.418 595.412 56.8867 595.824 56.2617 596.098L55.4414 594.937C55.9961 594.695 56.4668 594.35 56.8535 593.9C57.2441 593.447 57.5352 592.949 57.7266 592.406C57.918 591.863 58.0137 591.314 58.0137 590.76V590.15H59.1914V590.76ZM59.4961 590.76C59.4922 591.283 59.582 591.803 59.7656 592.318C59.9531 592.83 60.2324 593.305 60.6035 593.742C60.9746 594.176 61.4316 594.521 61.9746 594.779L61.1484 595.916C60.543 595.643 60.0293 595.238 59.6074 594.703C59.1855 594.164 58.8672 593.555 58.6523 592.875C58.4375 592.191 58.332 591.486 58.3359 590.76V590.15H59.4961V590.76ZM61.6758 590.344H55.8047V589.154H61.6758V590.344ZM59.5078 589.775H58.0078V587.648H59.5078V589.775ZM64.0547 598.078H62.5547V587.402H64.0547V598.078ZM65.6367 592.805H63.7266V591.551H65.6367V592.805Z" fill="#56555A"/> -<path d="M367.633 597.117C367.047 597.117 366.525 597.016 366.068 596.812C365.611 596.609 365.256 596.328 365.002 595.969C364.748 595.609 364.621 595.203 364.621 594.75C364.621 594.391 364.697 594.055 364.85 593.742C365.002 593.43 365.209 593.174 365.471 592.975C365.732 592.771 366.023 592.645 366.344 592.594V592.547C366.066 592.484 365.822 592.361 365.611 592.178C365.404 591.994 365.242 591.77 365.125 591.504C365.008 591.238 364.949 590.953 364.949 590.648C364.949 590.223 365.064 589.84 365.295 589.5C365.525 589.156 365.844 588.887 366.25 588.691C366.66 588.496 367.121 588.398 367.633 588.398C368.141 588.398 368.6 588.496 369.01 588.691C369.42 588.887 369.74 589.156 369.971 589.5C370.205 589.84 370.324 590.223 370.328 590.648C370.324 590.953 370.262 591.238 370.141 591.504C370.023 591.77 369.859 591.994 369.648 592.178C369.437 592.361 369.195 592.484 368.922 592.547V592.594C369.238 592.645 369.527 592.771 369.789 592.975C370.055 593.174 370.264 593.43 370.416 593.742C370.572 594.055 370.652 594.391 370.656 594.75C370.652 595.203 370.521 595.609 370.264 595.969C370.01 596.328 369.652 596.609 369.191 596.812C368.734 597.016 368.215 597.117 367.633 597.117ZM367.633 596.191C368.031 596.191 368.379 596.127 368.676 595.998C368.973 595.869 369.201 595.693 369.361 595.471C369.521 595.248 369.602 594.988 369.602 594.691C369.602 594.383 369.518 594.105 369.35 593.859C369.182 593.609 368.947 593.414 368.646 593.273C368.346 593.133 368.008 593.062 367.633 593.062C367.258 593.062 366.922 593.133 366.625 593.273C366.328 593.414 366.094 593.609 365.922 593.859C365.754 594.105 365.672 594.383 365.676 594.691C365.672 594.988 365.748 595.248 365.904 595.471C366.064 595.693 366.291 595.869 366.584 595.998C366.881 596.127 367.23 596.191 367.633 596.191ZM367.633 592.172C367.953 592.172 368.24 592.109 368.494 591.984C368.748 591.859 368.945 591.689 369.086 591.475C369.227 591.26 369.297 591.012 369.297 590.73C369.297 590.449 369.229 590.201 369.092 589.986C368.955 589.771 368.76 589.605 368.506 589.488C368.252 589.371 367.961 589.312 367.633 589.312C367.301 589.312 367.01 589.371 366.76 589.488C366.514 589.605 366.32 589.771 366.18 589.986C366.039 590.201 365.969 590.449 365.969 590.73C365.969 591.012 366.041 591.26 366.186 591.475C366.33 591.689 366.527 591.859 366.777 591.984C367.027 592.109 367.312 592.172 367.633 592.172ZM379.773 589.992H376.703V589.23H379.773V589.992ZM379.785 592.066H376.703V591.293H379.785V592.066ZM380.336 593.707H379.41V587.531H380.336V593.707ZM376.973 592.957H372.191V588.328H376.973V592.957ZM373.105 592.207H376.07V589.078H373.105V592.207ZM376.879 594.012C377.598 594.012 378.219 594.088 378.742 594.24C379.266 594.393 379.668 594.617 379.949 594.914C380.23 595.211 380.371 595.566 380.371 595.98C380.371 596.391 380.23 596.74 379.949 597.029C379.668 597.322 379.266 597.545 378.742 597.697C378.219 597.85 377.598 597.926 376.879 597.926C376.156 597.926 375.533 597.85 375.01 597.697C374.49 597.545 374.09 597.322 373.809 597.029C373.527 596.74 373.387 596.391 373.387 595.98C373.387 595.566 373.527 595.211 373.809 594.914C374.09 594.617 374.49 594.393 375.01 594.24C375.533 594.088 376.156 594.012 376.879 594.012ZM376.879 594.727C376.348 594.73 375.889 594.783 375.502 594.885C375.115 594.982 374.818 595.125 374.611 595.312C374.404 595.5 374.301 595.723 374.301 595.98C374.301 596.23 374.404 596.447 374.611 596.631C374.818 596.814 375.115 596.955 375.502 597.053C375.889 597.15 376.348 597.199 376.879 597.199C377.406 597.199 377.863 597.15 378.25 597.053C378.641 596.955 378.939 596.814 379.146 596.631C379.354 596.447 379.457 596.23 379.457 595.98C379.457 595.723 379.354 595.5 379.146 595.312C378.939 595.125 378.643 594.982 378.256 594.885C377.869 594.783 377.41 594.73 376.879 594.727Z" fill="#B2B1B6"/> -<path d="M364 598.916H381.648V599.73H364V598.916Z" fill="#B2B1B6"/> -<path d="M382 610H48C43.5817 610 40 613.582 40 618V642C40 646.418 43.5817 650 48 650H382C386.418 650 390 646.418 390 642V618C390 613.582 386.418 610 382 610Z" fill="#F9F8FD"/> -<path d="M60.0156 630.953H49.875V629.352H60.0156V630.953ZM61.4297 635.812H48.4297V634.219H61.4297V635.812ZM55.9141 634.664H53.9219V630.281H55.9141V634.664ZM51.9141 630.031H49.875V624.305H51.9141V630.031ZM63.6406 632.625C64.6823 632.625 65.5755 632.607 66.3203 632.57C67.0703 632.534 67.8516 632.453 68.6641 632.328L68.8047 633.914C67.9349 634.06 67.1016 634.159 66.3047 634.211C65.513 634.263 64.625 634.286 63.6406 634.281H62.6484V632.625H63.6406ZM68.0469 630.078H64.5703V633.234H62.6484V628.484H66.125V626.211H62.6328V624.602H68.0469V630.078ZM74.5391 637.437H72.6641V623.203H74.5391V637.437ZM73.1172 630.203H70.7031V628.602H73.1172V630.203ZM71.2891 636.75H69.4609V623.461H71.2891V636.75ZM82.6953 631.93C83.6797 631.93 84.5312 632.036 85.25 632.25C85.974 632.464 86.5286 632.779 86.9141 633.195C87.2995 633.607 87.4922 634.099 87.4922 634.672C87.4922 635.25 87.2995 635.747 86.9141 636.164C86.5286 636.581 85.974 636.898 85.25 637.117C84.5312 637.341 83.6797 637.456 82.6953 637.461C81.6953 637.456 80.8281 637.341 80.0937 637.117C79.3646 636.898 78.8021 636.581 78.4062 636.164C78.0156 635.747 77.8203 635.25 77.8203 634.672C77.8203 634.099 78.0156 633.607 78.4062 633.195C78.8021 632.779 79.3646 632.464 80.0937 632.25C80.8281 632.036 81.6953 631.93 82.6953 631.93ZM82.6953 633.469C82.0703 633.469 81.5443 633.513 81.1172 633.602C80.6901 633.69 80.3672 633.823 80.1484 634C79.9297 634.177 79.8229 634.401 79.8281 634.672C79.8229 634.943 79.9297 635.169 80.1484 635.352C80.3724 635.529 80.6979 635.667 81.125 635.766C81.5521 635.859 82.0755 635.906 82.6953 635.906C83.3151 635.906 83.8333 635.859 84.25 635.766C84.6719 635.667 84.9896 635.529 85.2031 635.352C85.4219 635.169 85.5312 634.943 85.5312 634.672C85.5312 634.401 85.4219 634.177 85.2031 634C84.9896 633.823 84.6719 633.69 84.25 633.602C83.8333 633.513 83.3151 633.469 82.6953 633.469ZM87.3594 631.602H85.3672V623.203H87.3594V631.602ZM89.2812 628.187H86.7969V626.523H89.2812V628.187ZM78.4766 625.914H81.3906V624.117H83.3906V630.789H76.5V624.117H78.4766V625.914ZM81.3906 629.227V627.453H78.4766V629.227H81.3906Z" fill="#56555A"/> -<path d="M323.078 626.016V625.937H317.094V624.687H324.531V626L319.359 636H317.891L323.078 626.016ZM326.344 634.969L330.203 630.906C330.708 630.365 331.094 629.927 331.359 629.594C331.63 629.26 331.836 628.943 331.977 628.641C332.117 628.333 332.187 628.01 332.187 627.672C332.187 627.292 332.089 626.958 331.891 626.672C331.693 626.38 331.422 626.154 331.078 625.992C330.74 625.831 330.359 625.75 329.937 625.75C329.495 625.75 329.107 625.839 328.773 626.016C328.445 626.193 328.19 626.443 328.008 626.766C327.826 627.083 327.734 627.453 327.734 627.875H326.406C326.401 627.219 326.552 626.638 326.859 626.133C327.172 625.628 327.602 625.234 328.148 624.953C328.695 624.672 329.307 624.531 329.984 624.531C330.656 624.531 331.258 624.669 331.789 624.945C332.326 625.221 332.745 625.599 333.047 626.078C333.349 626.557 333.5 627.089 333.5 627.672C333.495 628.104 333.414 628.518 333.258 628.914C333.107 629.305 332.846 629.74 332.477 630.219C332.107 630.698 331.583 631.286 330.906 631.984L328.312 634.656V634.75H333.703V636H326.359L326.344 634.969ZM336.312 639.203H335.156L336.016 634.953H337.531L336.312 639.203ZM343.172 636.156C342.339 636.156 341.628 635.93 341.039 635.477C340.451 635.023 340 634.362 339.687 633.492C339.375 632.622 339.219 631.573 339.219 630.344C339.219 629.13 339.375 628.089 339.687 627.219C340 626.344 340.451 625.677 341.039 625.219C341.633 624.76 342.344 624.531 343.172 624.531C343.995 624.531 344.703 624.76 345.297 625.219C345.891 625.677 346.344 626.344 346.656 627.219C346.969 628.089 347.125 629.13 347.125 630.344C347.125 631.573 346.971 632.622 346.664 633.492C346.357 634.362 345.906 635.023 345.312 635.477C344.719 635.93 344.005 636.156 343.172 636.156ZM343.172 634.906C343.714 634.906 344.18 634.729 344.57 634.375C344.961 634.021 345.255 633.503 345.453 632.82C345.651 632.138 345.75 631.312 345.75 630.344C345.75 629.375 345.648 628.547 345.445 627.859C345.242 627.172 344.948 626.648 344.562 626.289C344.177 625.93 343.714 625.75 343.172 625.75C342.63 625.75 342.167 625.93 341.781 626.289C341.396 626.648 341.099 627.172 340.891 627.859C340.682 628.547 340.578 629.375 340.578 630.344C340.578 631.312 340.682 632.138 340.891 632.82C341.099 633.503 341.393 634.021 341.773 634.375C342.159 634.729 342.625 634.906 343.172 634.906ZM352.703 636.156C351.87 636.156 351.159 635.93 350.57 635.477C349.982 635.023 349.531 634.362 349.219 633.492C348.906 632.622 348.75 631.573 348.75 630.344C348.75 629.13 348.906 628.089 349.219 627.219C349.531 626.344 349.982 625.677 350.57 625.219C351.164 624.76 351.875 624.531 352.703 624.531C353.526 624.531 354.234 624.76 354.828 625.219C355.422 625.677 355.875 626.344 356.187 627.219C356.5 628.089 356.656 629.13 356.656 630.344C356.656 631.573 356.503 632.622 356.195 633.492C355.888 634.362 355.437 635.023 354.844 635.477C354.25 635.93 353.536 636.156 352.703 636.156ZM352.703 634.906C353.245 634.906 353.711 634.729 354.102 634.375C354.492 634.021 354.786 633.503 354.984 632.82C355.182 632.138 355.281 631.312 355.281 630.344C355.281 629.375 355.18 628.547 354.977 627.859C354.773 627.172 354.479 626.648 354.094 626.289C353.708 625.93 353.245 625.75 352.703 625.75C352.161 625.75 351.698 625.93 351.312 626.289C350.927 626.648 350.63 627.172 350.422 627.859C350.214 628.547 350.109 629.375 350.109 630.344C350.109 631.312 350.214 632.138 350.422 632.82C350.63 633.503 350.924 634.021 351.305 634.375C351.69 634.729 352.156 634.906 352.703 634.906ZM362.234 636.156C361.401 636.156 360.69 635.93 360.102 635.477C359.513 635.023 359.062 634.362 358.75 633.492C358.437 632.622 358.281 631.573 358.281 630.344C358.281 629.13 358.437 628.089 358.75 627.219C359.062 626.344 359.513 625.677 360.102 625.219C360.695 624.76 361.406 624.531 362.234 624.531C363.057 624.531 363.766 624.76 364.359 625.219C364.953 625.677 365.406 626.344 365.719 627.219C366.031 628.089 366.187 629.13 366.187 630.344C366.187 631.573 366.034 632.622 365.727 633.492C365.419 634.362 364.969 635.023 364.375 635.477C363.781 635.93 363.068 636.156 362.234 636.156ZM362.234 634.906C362.776 634.906 363.242 634.729 363.633 634.375C364.023 634.021 364.318 633.503 364.516 632.82C364.714 632.138 364.812 631.312 364.812 630.344C364.812 629.375 364.711 628.547 364.508 627.859C364.305 627.172 364.01 626.648 363.625 626.289C363.24 625.93 362.776 625.75 362.234 625.75C361.693 625.75 361.229 625.93 360.844 626.289C360.458 626.648 360.161 627.172 359.953 627.859C359.745 628.547 359.641 629.375 359.641 630.344C359.641 631.312 359.745 632.138 359.953 632.82C360.161 633.503 360.456 634.021 360.836 634.375C361.221 634.729 361.687 634.906 362.234 634.906Z" fill="#56555A"/> -<path d="M375.348 635.09H374.422V632.77H375.348V635.09ZM380.012 635.453H379.086V627.543H380.012V635.453ZM380.27 637.727H372.863V636.953H380.27V637.727ZM373.789 637.176H372.863V634.68H373.789V637.176ZM371.363 632.371C372.758 632.363 373.992 632.342 375.066 632.307C376.141 632.268 377.168 632.187 378.148 632.066L378.207 632.734C377.195 632.895 376.135 633 375.025 633.051C373.916 633.102 372.738 633.125 371.492 633.121L371.363 632.371ZM379.332 634.375H376.93V633.707H379.332V634.375ZM374.785 627.965C375.289 627.965 375.736 628.039 376.127 628.187C376.521 628.336 376.826 628.549 377.041 628.826C377.256 629.104 377.363 629.422 377.363 629.781C377.363 630.148 377.256 630.467 377.041 630.736C376.826 631.006 376.523 631.215 376.133 631.363C375.742 631.512 375.293 631.586 374.785 631.586C374.273 631.586 373.822 631.512 373.432 631.363C373.045 631.215 372.744 631.006 372.529 630.736C372.314 630.467 372.207 630.148 372.207 629.781C372.207 629.422 372.314 629.104 372.529 628.826C372.744 628.549 373.047 628.336 373.437 628.187C373.828 628.039 374.277 627.965 374.785 627.965ZM374.785 628.668C374.449 628.664 374.152 628.709 373.895 628.803C373.637 628.893 373.436 629.023 373.291 629.195C373.15 629.367 373.082 629.562 373.086 629.781C373.082 630.004 373.15 630.201 373.291 630.373C373.436 630.541 373.637 630.672 373.895 630.766C374.152 630.859 374.449 630.906 374.785 630.906C375.113 630.906 375.406 630.859 375.664 630.766C375.922 630.672 376.123 630.541 376.268 630.373C376.412 630.201 376.484 630.004 376.484 629.781C376.484 629.562 376.412 629.367 376.268 629.195C376.123 629.023 375.922 628.893 375.664 628.803C375.406 628.709 375.113 628.664 374.785 628.668Z" fill="#56555A"/> -<path d="M382 658H48C43.5817 658 40 661.582 40 666V690C40 694.418 43.5817 698 48 698H382C386.418 698 390 694.418 390 690V666C390 661.582 386.418 658 382 658Z" fill="#F9F8FD"/> -<path d="M56.5312 674.133H48.6016V672.531H56.5312V674.133ZM48.2422 680.539C49.9349 680.539 51.4948 680.516 52.9219 680.469C54.3542 680.422 55.7005 680.32 56.9609 680.164L57.0547 681.586C55.763 681.815 54.4167 681.969 53.0156 682.047C51.6198 682.12 50.1016 682.161 48.4609 682.172L48.2422 680.539ZM51.7812 680.984H49.8516V673.789H51.7812V680.984ZM55.2578 680.984H53.3437V673.789H55.2578V680.984ZM59.6406 685.437H57.6406V671.203H59.6406V685.437ZM61.75 678.258H59.2031V676.633H61.75V678.258ZM73.2969 676.523H69.9219V674.906H73.2969V676.523ZM74.2344 681.617H72.25V671.234H74.2344V681.617ZM74.5781 685.195H64.7969V683.586H74.5781V685.195ZM66.7969 684.523H64.7969V680.703H66.7969V684.523ZM67.2109 673.992C67.2109 674.914 67.0625 675.776 66.7656 676.578C66.474 677.375 66.026 678.076 65.4219 678.68C64.8229 679.284 64.0833 679.732 63.2031 680.023L62.1719 678.414C62.9271 678.174 63.5599 677.828 64.0703 677.375C64.5807 676.917 64.9583 676.398 65.2031 675.82C65.4531 675.237 65.5807 674.628 65.5859 673.992V673.07H67.2109V673.992ZM67.6172 674.008C67.6172 674.586 67.737 675.146 67.9766 675.687C68.2214 676.224 68.5859 676.711 69.0703 677.148C69.5599 677.586 70.1667 677.922 70.8906 678.156L69.9062 679.734C69.0469 679.453 68.3229 679.023 67.7344 678.445C67.151 677.867 66.7135 677.201 66.4219 676.445C66.1354 675.685 65.9948 674.872 66 674.008V673.07H67.6172V674.008ZM70.4531 673.789H62.7344V672.187H70.4531V673.789ZM87.0312 678.852H80.2031V672.234H87.0312V678.852ZM82.1797 677.273H85.0703V673.805H82.1797V677.273ZM91.0625 679.648H89.0703V671.203H91.0625V679.648ZM92.9844 676.242H90.5V674.625H92.9844V676.242ZM91.0625 685.453H89.0703V681.859H81.4922V680.281H91.0625V685.453ZM105.594 678.344H103.609V671.203H105.594V678.344ZM103.844 675.859H101.039V674.25H103.844V675.859ZM100.883 671.734C100.883 672.969 100.641 674.047 100.156 674.969C99.6719 675.891 98.9531 676.664 98 677.289C97.0469 677.914 95.8672 678.393 94.4609 678.727L93.7891 677.133C94.9193 676.883 95.8542 676.544 96.5937 676.117C97.3385 675.685 97.888 675.187 98.2422 674.625C98.5964 674.057 98.7734 673.435 98.7734 672.758V671.734H100.883ZM100.43 673.336H94.5781V671.734H100.43V673.336ZM105.594 682.781H98.1562V684.578H96.1641V681.305H103.586V680.453H96.1406V678.891H105.594V682.781ZM105.906 685.297H96.1641V683.719H105.906V685.297ZM119.359 685.477H117.367V671.203H119.359V685.477ZM109.477 680.5C110.815 680.51 112.016 680.482 113.078 680.414C114.146 680.341 115.237 680.214 116.352 680.031L116.531 681.641C115.432 681.833 114.336 681.966 113.242 682.039C112.154 682.107 110.898 682.141 109.477 682.141H108.203V680.5H109.477ZM114.945 677.883H110.258V681.125H108.203V676.32H112.914V674.016H108.187V672.406H114.945V677.883Z" fill="#56555A"/> -<path d="M316.156 684H314.734V674.156H314.672L311.922 675.984V674.562L314.734 672.687H316.156V684ZM323.172 684H321.75V674.156H321.687L318.937 675.984V674.562L321.75 672.687H323.172V684ZM329.969 684.156C329.187 684.156 328.492 684.021 327.883 683.75C327.273 683.479 326.799 683.104 326.461 682.625C326.122 682.146 325.953 681.604 325.953 681C325.953 680.521 326.055 680.073 326.258 679.656C326.461 679.24 326.737 678.898 327.086 678.633C327.435 678.362 327.823 678.193 328.25 678.125V678.062C327.88 677.979 327.555 677.815 327.273 677.57C326.997 677.326 326.781 677.026 326.625 676.672C326.469 676.318 326.391 675.937 326.391 675.531C326.391 674.964 326.544 674.453 326.852 674C327.159 673.542 327.583 673.182 328.125 672.922C328.672 672.661 329.286 672.531 329.969 672.531C330.646 672.531 331.258 672.661 331.805 672.922C332.352 673.182 332.779 673.542 333.086 674C333.398 674.453 333.557 674.964 333.562 675.531C333.557 675.937 333.474 676.318 333.312 676.672C333.156 677.026 332.937 677.326 332.656 677.57C332.375 677.815 332.052 677.979 331.687 678.062V678.125C332.109 678.193 332.495 678.362 332.844 678.633C333.198 678.898 333.477 679.24 333.68 679.656C333.888 680.073 333.995 680.521 334 681C333.995 681.604 333.82 682.146 333.477 682.625C333.138 683.104 332.661 683.479 332.047 683.75C331.437 684.021 330.745 684.156 329.969 684.156ZM329.969 682.922C330.5 682.922 330.964 682.836 331.359 682.664C331.755 682.492 332.06 682.258 332.273 681.961C332.487 681.664 332.594 681.318 332.594 680.922C332.594 680.51 332.482 680.141 332.258 679.812C332.034 679.479 331.721 679.219 331.32 679.031C330.919 678.844 330.469 678.75 329.969 678.75C329.469 678.75 329.021 678.844 328.625 679.031C328.229 679.219 327.917 679.479 327.687 679.812C327.464 680.141 327.354 680.51 327.359 680.922C327.354 681.318 327.456 681.664 327.664 681.961C327.878 682.258 328.18 682.492 328.57 682.664C328.966 682.836 329.432 682.922 329.969 682.922ZM329.969 677.562C330.396 677.562 330.779 677.479 331.117 677.312C331.456 677.146 331.719 676.919 331.906 676.633C332.094 676.346 332.187 676.016 332.187 675.641C332.187 675.266 332.096 674.935 331.914 674.648C331.732 674.362 331.471 674.141 331.133 673.984C330.794 673.828 330.406 673.75 329.969 673.75C329.526 673.75 329.138 673.828 328.805 673.984C328.477 674.141 328.219 674.362 328.031 674.648C327.844 674.935 327.75 675.266 327.75 675.641C327.75 676.016 327.846 676.346 328.039 676.633C328.232 676.919 328.495 677.146 328.828 677.312C329.161 677.479 329.542 677.562 329.969 677.562ZM336.094 687.203H334.937L335.797 682.953H337.312L336.094 687.203ZM343.078 684.156C342.297 684.156 341.602 684.021 340.992 683.75C340.383 683.479 339.909 683.104 339.57 682.625C339.232 682.146 339.062 681.604 339.062 681C339.062 680.521 339.164 680.073 339.367 679.656C339.57 679.24 339.846 678.898 340.195 678.633C340.544 678.362 340.932 678.193 341.359 678.125V678.062C340.99 677.979 340.664 677.815 340.383 677.57C340.107 677.326 339.891 677.026 339.734 676.672C339.578 676.318 339.5 675.937 339.5 675.531C339.5 674.964 339.654 674.453 339.961 674C340.268 673.542 340.693 673.182 341.234 672.922C341.781 672.661 342.396 672.531 343.078 672.531C343.755 672.531 344.367 672.661 344.914 672.922C345.461 673.182 345.888 673.542 346.195 674C346.508 674.453 346.667 674.964 346.672 675.531C346.667 675.937 346.583 676.318 346.422 676.672C346.266 677.026 346.047 677.326 345.766 677.57C345.484 677.815 345.161 677.979 344.797 678.062V678.125C345.219 678.193 345.604 678.362 345.953 678.633C346.307 678.898 346.586 679.24 346.789 679.656C346.997 680.073 347.104 680.521 347.109 681C347.104 681.604 346.93 682.146 346.586 682.625C346.247 683.104 345.771 683.479 345.156 683.75C344.547 684.021 343.854 684.156 343.078 684.156ZM343.078 682.922C343.609 682.922 344.073 682.836 344.469 682.664C344.865 682.492 345.169 682.258 345.383 681.961C345.596 681.664 345.703 681.318 345.703 680.922C345.703 680.51 345.591 680.141 345.367 679.812C345.143 679.479 344.831 679.219 344.43 679.031C344.029 678.844 343.578 678.75 343.078 678.75C342.578 678.75 342.13 678.844 341.734 679.031C341.339 679.219 341.026 679.479 340.797 679.812C340.573 680.141 340.464 680.51 340.469 680.922C340.464 681.318 340.565 681.664 340.773 681.961C340.987 682.258 341.289 682.492 341.68 682.664C342.076 682.836 342.542 682.922 343.078 682.922ZM343.078 677.562C343.505 677.562 343.888 677.479 344.227 677.312C344.565 677.146 344.828 676.919 345.016 676.633C345.203 676.346 345.297 676.016 345.297 675.641C345.297 675.266 345.206 674.935 345.023 674.648C344.841 674.362 344.581 674.141 344.242 673.984C343.904 673.828 343.516 673.75 343.078 673.75C342.635 673.75 342.247 673.828 341.914 673.984C341.586 674.141 341.328 674.362 341.141 674.648C340.953 674.935 340.859 675.266 340.859 675.641C340.859 676.016 340.956 676.346 341.148 676.633C341.341 676.919 341.604 677.146 341.937 677.312C342.271 677.479 342.651 677.562 343.078 677.562ZM352.703 684.156C351.87 684.156 351.159 683.93 350.57 683.477C349.982 683.023 349.531 682.362 349.219 681.492C348.906 680.622 348.75 679.573 348.75 678.344C348.75 677.13 348.906 676.089 349.219 675.219C349.531 674.344 349.982 673.677 350.57 673.219C351.164 672.76 351.875 672.531 352.703 672.531C353.526 672.531 354.234 672.76 354.828 673.219C355.422 673.677 355.875 674.344 356.187 675.219C356.5 676.089 356.656 677.13 356.656 678.344C356.656 679.573 356.503 680.622 356.195 681.492C355.888 682.362 355.437 683.023 354.844 683.477C354.25 683.93 353.536 684.156 352.703 684.156ZM352.703 682.906C353.245 682.906 353.711 682.729 354.102 682.375C354.492 682.021 354.786 681.503 354.984 680.82C355.182 680.138 355.281 679.312 355.281 678.344C355.281 677.375 355.18 676.547 354.977 675.859C354.773 675.172 354.479 674.648 354.094 674.289C353.708 673.93 353.245 673.75 352.703 673.75C352.161 673.75 351.698 673.93 351.312 674.289C350.927 674.648 350.63 675.172 350.422 675.859C350.214 676.547 350.109 677.375 350.109 678.344C350.109 679.312 350.214 680.138 350.422 680.82C350.63 681.503 350.924 682.021 351.305 682.375C351.69 682.729 352.156 682.906 352.703 682.906ZM362.234 684.156C361.401 684.156 360.69 683.93 360.102 683.477C359.513 683.023 359.062 682.362 358.75 681.492C358.437 680.622 358.281 679.573 358.281 678.344C358.281 677.13 358.437 676.089 358.75 675.219C359.062 674.344 359.513 673.677 360.102 673.219C360.695 672.76 361.406 672.531 362.234 672.531C363.057 672.531 363.766 672.76 364.359 673.219C364.953 673.677 365.406 674.344 365.719 675.219C366.031 676.089 366.187 677.13 366.187 678.344C366.187 679.573 366.034 680.622 365.727 681.492C365.419 682.362 364.969 683.023 364.375 683.477C363.781 683.93 363.068 684.156 362.234 684.156ZM362.234 682.906C362.776 682.906 363.242 682.729 363.633 682.375C364.023 682.021 364.318 681.503 364.516 680.82C364.714 680.138 364.812 679.312 364.812 678.344C364.812 677.375 364.711 676.547 364.508 675.859C364.305 675.172 364.01 674.648 363.625 674.289C363.24 673.93 362.776 673.75 362.234 673.75C361.693 673.75 361.229 673.93 360.844 674.289C360.458 674.648 360.161 675.172 359.953 675.859C359.745 676.547 359.641 677.375 359.641 678.344C359.641 679.312 359.745 680.138 359.953 680.82C360.161 681.503 360.456 682.021 360.836 682.375C361.221 682.729 361.687 682.906 362.234 682.906Z" fill="#56555A"/> -<path d="M375.348 683.09H374.422V680.77H375.348V683.09ZM380.012 683.453H379.086V675.543H380.012V683.453ZM380.27 685.727H372.863V684.953H380.27V685.727ZM373.789 685.176H372.863V682.68H373.789V685.176ZM371.363 680.371C372.758 680.363 373.992 680.342 375.066 680.307C376.141 680.268 377.168 680.187 378.148 680.066L378.207 680.734C377.195 680.895 376.135 681 375.025 681.051C373.916 681.102 372.738 681.125 371.492 681.121L371.363 680.371ZM379.332 682.375H376.93V681.707H379.332V682.375ZM374.785 675.965C375.289 675.965 375.736 676.039 376.127 676.187C376.521 676.336 376.826 676.549 377.041 676.826C377.256 677.104 377.363 677.422 377.363 677.781C377.363 678.148 377.256 678.467 377.041 678.736C376.826 679.006 376.523 679.215 376.133 679.363C375.742 679.512 375.293 679.586 374.785 679.586C374.273 679.586 373.822 679.512 373.432 679.363C373.045 679.215 372.744 679.006 372.529 678.736C372.314 678.467 372.207 678.148 372.207 677.781C372.207 677.422 372.314 677.104 372.529 676.826C372.744 676.549 373.047 676.336 373.437 676.187C373.828 676.039 374.277 675.965 374.785 675.965ZM374.785 676.668C374.449 676.664 374.152 676.709 373.895 676.803C373.637 676.893 373.436 677.023 373.291 677.195C373.15 677.367 373.082 677.562 373.086 677.781C373.082 678.004 373.15 678.201 373.291 678.373C373.436 678.541 373.637 678.672 373.895 678.766C374.152 678.859 374.449 678.906 374.785 678.906C375.113 678.906 375.406 678.859 375.664 678.766C375.922 678.672 376.123 678.541 376.268 678.373C376.412 678.201 376.484 678.004 376.484 677.781C376.484 677.562 376.412 677.367 376.268 677.195C376.123 677.023 375.922 676.893 375.664 676.803C375.406 676.709 375.113 676.664 374.785 676.668Z" fill="#56555A"/> -<path d="M58.0488 715.953H48.3223V714.764H58.0488V715.953ZM53.9062 715.314H52.4238V713.732H53.9062V715.314ZM53.9062 711.014H52.4238V709.443H53.9062V711.014ZM53.6426 711.277C53.6426 711.82 53.4687 712.303 53.1211 712.725C52.7773 713.143 52.2715 713.482 51.6035 713.744C50.9355 714.006 50.127 714.17 49.1777 714.236L48.7207 713.111C49.5371 713.057 50.2168 712.939 50.7598 712.76C51.3027 712.576 51.6992 712.357 51.9492 712.104C52.2031 711.85 52.3301 711.574 52.3301 711.277V711.066H53.6426V711.277ZM54.0059 711.277C54.002 711.57 54.127 711.846 54.3809 712.104C54.6348 712.357 55.0312 712.576 55.5703 712.76C56.1133 712.939 56.793 713.057 57.6094 713.111L57.1582 714.236C56.209 714.17 55.4004 714.006 54.7324 713.744C54.0645 713.482 53.5566 713.143 53.209 712.725C52.8613 712.303 52.6895 711.82 52.6934 711.277V711.066H54.0059V711.277ZM57.1055 711.547H49.2539V710.363H57.1055V711.547ZM53.168 716.451C53.9453 716.451 54.6113 716.521 55.166 716.662C55.7207 716.803 56.1445 717.008 56.4375 717.277C56.7305 717.547 56.8789 717.875 56.8828 718.262C56.8789 718.652 56.7305 718.982 56.4375 719.252C56.1445 719.525 55.7207 719.73 55.166 719.867C54.6113 720.008 53.9453 720.078 53.168 720.078C52.3828 720.078 51.7109 720.008 51.1523 719.867C50.5977 719.73 50.1719 719.525 49.875 719.252C49.5781 718.982 49.4297 718.652 49.4297 718.262C49.4297 717.875 49.5781 717.547 49.875 717.277C50.1719 717.008 50.5977 716.803 51.1523 716.662C51.7109 716.521 52.3828 716.451 53.168 716.451ZM53.168 717.559C52.6641 717.555 52.248 717.58 51.9199 717.635C51.5957 717.686 51.3516 717.764 51.1875 717.869C51.0273 717.971 50.9492 718.102 50.9531 718.262C50.9492 718.426 51.0273 718.561 51.1875 718.666C51.3516 718.768 51.5957 718.844 51.9199 718.895C52.248 718.945 52.6641 718.971 53.168 718.971C53.6602 718.971 54.0684 718.945 54.3926 718.895C54.7207 718.844 54.9668 718.768 55.1309 718.666C55.2949 718.561 55.377 718.426 55.377 718.262C55.377 718.102 55.2949 717.971 55.1309 717.869C54.9668 717.764 54.7207 717.686 54.3926 717.635C54.0684 717.58 53.6602 717.555 53.168 717.559ZM61.1836 710.053C61.6523 710.053 62.0742 710.164 62.4492 710.387C62.8242 710.605 63.1172 710.914 63.3281 711.312C63.543 711.707 63.6504 712.156 63.6504 712.66C63.6504 713.168 63.543 713.617 63.3281 714.008C63.1172 714.398 62.8242 714.703 62.4492 714.922C62.0742 715.141 61.6523 715.25 61.1836 715.25C60.7148 715.25 60.2949 715.141 59.9238 714.922C59.5527 714.703 59.2617 714.398 59.0508 714.008C58.8437 713.617 58.7402 713.168 58.7402 712.66C58.7402 712.16 58.8437 711.711 59.0508 711.312C59.2617 710.914 59.5527 710.605 59.9238 710.387C60.2949 710.164 60.7148 710.053 61.1836 710.053ZM61.1836 711.33C60.9648 711.33 60.7715 711.383 60.6035 711.488C60.4355 711.59 60.3047 711.742 60.2109 711.945C60.1172 712.145 60.0723 712.383 60.0762 712.66C60.0723 712.937 60.1172 713.178 60.2109 713.381C60.3047 713.58 60.4355 713.734 60.6035 713.844C60.7715 713.953 60.9648 714.008 61.1836 714.008C61.3984 714.008 61.5898 713.953 61.7578 713.844C61.9297 713.734 62.0605 713.58 62.1504 713.381C62.2441 713.178 62.291 712.937 62.291 712.66C62.291 712.383 62.2441 712.145 62.1504 711.945C62.0605 711.742 61.9316 711.59 61.7637 711.488C61.5957 711.383 61.4023 711.33 61.1836 711.33ZM67.8516 715.795H66.4277V709.426H67.8516V715.795ZM66.832 713.205H65.1035V712.01H66.832V713.205ZM65.5605 715.736H64.166V709.607H65.5605V715.736ZM67.8516 720.078H66.3691V717.453H60.4805V716.264H67.8516V720.078Z" fill="#56555A"/> -<path d="M341.797 719H340.73V711.617H340.684L338.621 712.988V711.922L340.73 710.516H341.797V719ZM346.883 710.398C347.422 710.406 347.924 710.535 348.389 710.785C348.854 711.035 349.232 711.459 349.525 712.057C349.818 712.65 349.965 713.438 349.965 714.419C349.965 715.411 349.836 716.258 349.578 716.961C349.32 717.664 348.949 718.199 348.465 718.566C347.98 718.934 347.406 719.117 346.742 719.117C346.25 719.117 345.809 719.021 345.418 718.83C345.027 718.639 344.709 718.375 344.463 718.039C344.217 717.699 344.059 717.305 343.988 716.855H345.031C345.094 717.117 345.201 717.348 345.354 717.547C345.506 717.742 345.699 717.896 345.934 718.01C346.168 718.123 346.437 718.18 346.742 718.18C347.203 718.18 347.602 718.052 347.937 717.794C348.273 717.536 348.529 717.164 348.705 716.68C348.885 716.191 348.977 715.605 348.98 714.922H348.863C348.699 715.156 348.506 715.358 348.283 715.526C348.061 715.694 347.814 715.822 347.545 715.912C347.275 716.002 346.992 716.047 346.695 716.047C346.191 716.047 345.727 715.927 345.301 715.685C344.879 715.442 344.543 715.107 344.293 714.682C344.043 714.256 343.918 713.777 343.918 713.246C343.918 712.719 344.041 712.238 344.287 711.805C344.533 711.367 344.881 711.023 345.33 710.773C345.779 710.52 346.297 710.395 346.883 710.398ZM346.883 711.324C346.52 711.324 346.189 711.41 345.893 711.582C345.6 711.754 345.367 711.986 345.195 712.279C345.027 712.572 344.945 712.891 344.949 713.234C344.949 713.582 345.031 713.901 345.195 714.19C345.359 714.476 345.584 714.701 345.869 714.869C346.158 715.037 346.484 715.121 346.848 715.121C347.207 715.121 347.537 715.031 347.838 714.852C348.139 714.672 348.377 714.436 348.553 714.143C348.729 713.85 348.816 713.539 348.816 713.211C348.816 712.887 348.732 712.58 348.564 712.291C348.396 711.998 348.164 711.764 347.867 711.588C347.574 711.412 347.246 711.324 346.883 711.324ZM354.195 719.117C353.57 719.117 353.037 718.947 352.596 718.607C352.154 718.268 351.816 717.771 351.582 717.119C351.348 716.467 351.23 715.68 351.23 714.758C351.23 713.848 351.348 713.066 351.582 712.414C351.816 711.758 352.154 711.258 352.596 710.914C353.041 710.57 353.574 710.398 354.195 710.398C354.812 710.398 355.344 710.57 355.789 710.914C356.234 711.258 356.574 711.758 356.809 712.414C357.043 713.066 357.16 713.848 357.16 714.758C357.16 715.68 357.045 716.467 356.814 717.119C356.584 717.771 356.246 718.268 355.801 718.607C355.355 718.947 354.82 719.117 354.195 719.117ZM354.195 718.18C354.602 718.18 354.951 718.047 355.244 717.781C355.537 717.516 355.758 717.127 355.906 716.615C356.055 716.104 356.129 715.484 356.129 714.758C356.129 714.031 356.053 713.41 355.9 712.895C355.748 712.379 355.527 711.986 355.238 711.717C354.949 711.447 354.602 711.312 354.195 711.312C353.789 711.312 353.441 711.447 353.152 711.717C352.863 711.986 352.641 712.379 352.484 712.895C352.328 713.41 352.25 714.031 352.25 714.758C352.25 715.484 352.328 716.104 352.484 716.615C352.641 717.127 352.861 717.516 353.146 717.781C353.436 718.047 353.785 718.18 354.195 718.18ZM358.684 721.402H357.816L358.461 718.216H359.598L358.684 721.402ZM363.922 719.117C363.336 719.117 362.814 719.016 362.357 718.812C361.9 718.609 361.545 718.328 361.291 717.969C361.037 717.609 360.91 717.203 360.91 716.75C360.91 716.391 360.986 716.055 361.139 715.742C361.291 715.43 361.498 715.174 361.76 714.975C362.021 714.771 362.312 714.645 362.633 714.594V714.547C362.355 714.484 362.111 714.361 361.9 714.178C361.693 713.994 361.531 713.771 361.414 713.505C361.297 713.239 361.238 712.953 361.238 712.648C361.238 712.223 361.354 711.84 361.584 711.5C361.814 711.156 362.133 710.887 362.539 710.691C362.949 710.496 363.41 710.398 363.922 710.398C364.43 710.398 364.889 710.496 365.299 710.691C365.709 710.887 366.029 711.156 366.26 711.5C366.494 711.84 366.613 712.223 366.617 712.648C366.613 712.953 366.551 713.239 366.43 713.505C366.312 713.771 366.148 713.994 365.937 714.178C365.727 714.361 365.484 714.484 365.211 714.547V714.594C365.527 714.645 365.816 714.771 366.078 714.975C366.344 715.174 366.553 715.43 366.705 715.742C366.861 716.055 366.941 716.391 366.945 716.75C366.941 717.203 366.811 717.609 366.553 717.969C366.299 718.328 365.941 718.609 365.48 718.812C365.023 719.016 364.504 719.117 363.922 719.117ZM363.922 718.191C364.32 718.191 364.668 718.127 364.965 717.998C365.262 717.869 365.49 717.693 365.65 717.471C365.811 717.248 365.891 716.988 365.891 716.691C365.891 716.383 365.807 716.105 365.639 715.859C365.471 715.609 365.236 715.414 364.936 715.273C364.635 715.133 364.297 715.062 363.922 715.062C363.547 715.062 363.211 715.133 362.914 715.273C362.617 715.414 362.383 715.609 362.211 715.859C362.043 716.105 361.961 716.383 361.965 716.691C361.961 716.988 362.037 717.248 362.193 717.471C362.354 717.693 362.58 717.869 362.873 717.998C363.17 718.127 363.52 718.191 363.922 718.191ZM363.922 714.172C364.242 714.172 364.529 714.109 364.783 713.984C365.037 713.859 365.234 713.689 365.375 713.475C365.516 713.26 365.586 713.012 365.586 712.73C365.586 712.449 365.518 712.202 365.381 711.987C365.244 711.772 365.049 711.605 364.795 711.488C364.541 711.371 364.25 711.312 363.922 711.312C363.59 711.312 363.299 711.371 363.049 711.488C362.803 711.605 362.609 711.772 362.469 711.987C362.328 712.202 362.258 712.449 362.258 712.73C362.258 713.012 362.33 713.26 362.475 713.475C362.619 713.689 362.816 713.859 363.066 713.984C363.316 714.109 363.602 714.172 363.922 714.172ZM371.141 719.117C370.516 719.117 369.982 718.947 369.541 718.607C369.1 718.268 368.762 717.771 368.527 717.119C368.293 716.467 368.176 715.68 368.176 714.758C368.176 713.848 368.293 713.066 368.527 712.414C368.762 711.758 369.1 711.258 369.541 710.914C369.986 710.57 370.52 710.398 371.141 710.398C371.758 710.398 372.289 710.57 372.734 710.914C373.18 711.258 373.52 711.758 373.754 712.414C373.988 713.066 374.105 713.848 374.105 714.758C374.105 715.68 373.99 716.467 373.76 717.119C373.529 717.771 373.191 718.268 372.746 718.607C372.301 718.947 371.766 719.117 371.141 719.117ZM371.141 718.18C371.547 718.18 371.896 718.047 372.189 717.781C372.482 717.516 372.703 717.127 372.852 716.615C373 716.104 373.074 715.484 373.074 714.758C373.074 714.031 372.998 713.41 372.846 712.895C372.693 712.379 372.473 711.986 372.184 711.717C371.895 711.447 371.547 711.312 371.141 711.312C370.734 711.312 370.387 711.447 370.098 711.717C369.809 711.986 369.586 712.379 369.43 712.895C369.273 713.41 369.195 714.031 369.195 714.758C369.195 715.484 369.273 716.104 369.43 716.615C369.586 717.127 369.807 717.516 370.092 717.781C370.381 718.047 370.73 718.18 371.141 718.18ZM378.289 719.117C377.664 719.117 377.131 718.947 376.689 718.607C376.248 718.268 375.91 717.771 375.676 717.119C375.441 716.467 375.324 715.68 375.324 714.758C375.324 713.848 375.441 713.066 375.676 712.414C375.91 711.758 376.248 711.258 376.689 710.914C377.135 710.57 377.668 710.398 378.289 710.398C378.906 710.398 379.437 710.57 379.883 710.914C380.328 711.258 380.668 711.758 380.902 712.414C381.137 713.066 381.254 713.848 381.254 714.758C381.254 715.68 381.139 716.467 380.908 717.119C380.678 717.771 380.34 718.268 379.895 718.607C379.449 718.947 378.914 719.117 378.289 719.117ZM378.289 718.18C378.695 718.18 379.045 718.047 379.338 717.781C379.631 717.516 379.852 717.127 380 716.615C380.148 716.104 380.223 715.484 380.223 714.758C380.223 714.031 380.146 713.41 379.994 712.895C379.842 712.379 379.621 711.986 379.332 711.717C379.043 711.447 378.695 711.312 378.289 711.312C377.883 711.312 377.535 711.447 377.246 711.717C376.957 711.986 376.734 712.379 376.578 712.895C376.422 713.41 376.344 714.031 376.344 714.758C376.344 715.484 376.422 716.104 376.578 716.615C376.734 717.127 376.955 717.516 377.24 717.781C377.529 718.047 377.879 718.18 378.289 718.18Z" fill="#B2B1B6"/> -<path d="M199 748H44C37.3726 748 32 753.373 32 760V776C32 782.627 37.3726 788 44 788H199C205.627 788 211 782.627 211 776V760C211 753.373 205.627 748 199 748Z" fill="#E7E6EB"/> -<path d="M88.6328 771.453H86.6406V761.234H88.6328V771.453ZM89.0234 775.195H79.1094V773.586H89.0234V775.195ZM81.125 774.242H79.1094V770.43H81.125V774.242ZM80.8437 762.133C81.5625 762.133 82.2187 762.286 82.8125 762.594C83.4115 762.901 83.8802 763.328 84.2187 763.875C84.5625 764.422 84.7344 765.034 84.7344 765.711C84.7344 766.404 84.5625 767.026 84.2187 767.578C83.8802 768.125 83.4141 768.555 82.8203 768.867C82.2266 769.174 81.5677 769.328 80.8437 769.328C80.1198 769.328 79.4609 769.174 78.8672 768.867C78.2786 768.555 77.8125 768.125 77.4687 767.578C77.125 767.026 76.9531 766.404 76.9531 765.711C76.9531 765.034 77.125 764.422 77.4687 763.875C77.8125 763.328 78.2786 762.901 78.8672 762.594C79.4609 762.286 80.1198 762.133 80.8437 762.133ZM80.8437 763.867C80.474 763.867 80.1406 763.943 79.8437 764.094C79.5521 764.24 79.3203 764.453 79.1484 764.734C78.9818 765.01 78.8984 765.336 78.8984 765.711C78.8984 766.102 78.9818 766.437 79.1484 766.719C79.3203 767 79.5521 767.216 79.8437 767.367C80.1406 767.518 80.474 767.591 80.8437 767.586C81.2083 767.591 81.5339 767.518 81.8203 767.367C82.112 767.216 82.3411 767 82.5078 766.719C82.6745 766.437 82.7578 766.102 82.7578 765.711C82.7578 765.336 82.6745 765.01 82.5078 764.734C82.3411 764.453 82.112 764.24 81.8203 764.094C81.5286 763.943 81.2031 763.867 80.8437 763.867ZM96.3203 771.633H94.3125V768.492H96.3203V771.633ZM102.609 771.977H100.609V761.234H102.609V771.977ZM102.922 775.195H92.3125V773.586H102.922V775.195ZM94.3203 774.016H92.3125V770.945H94.3203V774.016ZM90.5078 767.539C92.4036 767.523 94.0703 767.49 95.5078 767.437C96.9453 767.38 98.3255 767.268 99.6484 767.102L99.75 768.531C98.375 768.76 96.9349 768.917 95.4297 769C93.9297 769.078 92.3672 769.115 90.7422 769.109L90.5078 767.539ZM101.063 770.844H97.8906V769.484H101.063V770.844ZM95.1328 761.711C95.8151 761.711 96.4271 761.818 96.9687 762.031C97.5104 762.245 97.9323 762.547 98.2344 762.937C98.5365 763.323 98.6875 763.763 98.6875 764.258C98.6875 764.763 98.5365 765.203 98.2344 765.578C97.9323 765.953 97.5104 766.247 96.9687 766.461C96.4323 766.669 95.8203 766.773 95.1328 766.773C94.4349 766.773 93.8151 766.669 93.2734 766.461C92.737 766.247 92.3177 765.953 92.0156 765.578C91.7135 765.203 91.5625 764.763 91.5625 764.258C91.5625 763.763 91.7135 763.32 92.0156 762.93C92.3177 762.539 92.7396 762.24 93.2812 762.031C93.8229 761.818 94.4401 761.711 95.1328 761.711ZM95.1328 763.172C94.7943 763.172 94.5 763.214 94.25 763.297C94 763.38 93.8021 763.505 93.6562 763.672C93.5156 763.833 93.4479 764.029 93.4531 764.258C93.4479 764.487 93.5156 764.682 93.6562 764.844C93.8021 765.005 94 765.128 94.25 765.211C94.5 765.294 94.7943 765.336 95.1328 765.336C95.4609 765.336 95.7474 765.294 95.9922 765.211C96.2422 765.128 96.4375 765.005 96.5781 764.844C96.7187 764.682 96.7891 764.487 96.7891 764.258C96.7891 764.034 96.7187 763.839 96.5781 763.672C96.4375 763.505 96.2422 763.38 95.9922 763.297C95.7474 763.214 95.4609 763.172 95.1328 763.172ZM118.789 765.219H115.125V763.602H118.789V765.219ZM118.859 768.25H115.125V766.648H118.859V768.25ZM120.078 771.719H118.094V761.234H120.078V771.719ZM120.383 775.195H110.609V773.586H120.383V775.195ZM112.625 774.5H110.609V770.672H112.625V774.5ZM110.703 764.336H113.5V762.164H115.477V769.477H108.695V762.164H110.703V764.336ZM113.5 767.898V765.859H110.703V767.898H113.5ZM134.922 769.508H121.93V767.93H134.922V769.508ZM129.398 768.555H127.445V765.789H129.398V768.555ZM133.437 766.711H123.5V765.148H133.437V766.711ZM133.359 763.398H125.477V766.172H123.5V761.844H133.359V763.398ZM128.391 770.211C129.417 770.211 130.299 770.315 131.039 770.523C131.779 770.727 132.346 771.026 132.742 771.422C133.138 771.812 133.339 772.286 133.344 772.844C133.339 773.396 133.138 773.865 132.742 774.25C132.352 774.641 131.784 774.937 131.039 775.141C130.299 775.349 129.417 775.456 128.391 775.461C127.354 775.456 126.464 775.349 125.719 775.141C124.974 774.937 124.401 774.641 124 774.25C123.604 773.859 123.406 773.391 123.406 772.844C123.406 772.286 123.604 771.812 124 771.422C124.401 771.026 124.974 770.727 125.719 770.523C126.464 770.315 127.354 770.211 128.391 770.211ZM128.391 771.734C127.729 771.734 127.18 771.776 126.742 771.859C126.31 771.937 125.982 772.06 125.758 772.227C125.539 772.393 125.432 772.599 125.437 772.844C125.432 773.094 125.539 773.299 125.758 773.461C125.982 773.622 126.31 773.742 126.742 773.82C127.18 773.898 127.729 773.937 128.391 773.937C129.042 773.937 129.583 773.898 130.016 773.82C130.453 773.742 130.781 773.622 131 773.461C131.224 773.299 131.336 773.094 131.336 772.844C131.336 772.604 131.224 772.401 131 772.234C130.781 772.062 130.453 771.937 130.016 771.859C129.578 771.776 129.036 771.734 128.391 771.734ZM146.906 775.453H144.93V770.297H146.906V775.453ZM152.43 771.359H139.461V769.727H152.43V771.359ZM146.68 764.109C146.68 764.917 146.448 765.664 145.984 766.352C145.526 767.034 144.854 767.607 143.969 768.07C143.089 768.534 142.044 768.836 140.836 768.977L140.109 767.422C141.125 767.297 141.997 767.06 142.727 766.711C143.456 766.362 144.005 765.958 144.375 765.5C144.745 765.042 144.93 764.578 144.93 764.109V763.75H146.68V764.109ZM146.93 764.109C146.93 764.568 147.112 765.026 147.477 765.484C147.846 765.943 148.393 766.349 149.117 766.703C149.846 767.057 150.716 767.297 151.727 767.422L151.008 768.977C149.805 768.836 148.76 768.529 147.875 768.055C146.995 767.576 146.323 766.995 145.859 766.312C145.401 765.625 145.172 764.891 145.172 764.109V763.75H146.93V764.109ZM151.234 764.422H140.633V762.852H151.234V764.422ZM146.906 763.391H144.93V761.234H146.906V763.391ZM164.5 775.414H162.5V761.203H164.5V775.414ZM166.508 768.312H163.984V766.672H166.508V768.312ZM160.703 762.672C160.698 764.151 160.484 765.518 160.062 766.773C159.646 768.029 158.961 769.182 158.008 770.234C157.055 771.286 155.805 772.193 154.258 772.953L153.133 771.43C154.404 770.789 155.453 770.062 156.281 769.25C157.109 768.432 157.727 767.513 158.133 766.492C158.539 765.466 158.745 764.312 158.75 763.031V762.672H160.703ZM159.75 764.305H153.93V762.672H159.75V764.305Z" fill="#56555A"/> -<path d="M386 748H231C224.373 748 219 753.373 219 760V776C219 782.627 224.373 788 231 788H386C392.627 788 398 782.627 398 776V760C398 753.373 392.627 748 386 748Z" fill="#B575FF"/> -<path d="M268.828 765.086C268.823 766.206 268.664 767.273 268.352 768.289C268.039 769.305 267.578 770.206 266.969 770.992C266.359 771.773 265.625 772.365 264.766 772.766L263.625 771.195C264.391 770.852 265.042 770.357 265.578 769.711C266.12 769.06 266.526 768.336 266.797 767.539C267.073 766.737 267.211 765.919 267.211 765.086V763.43H268.828V765.086ZM269.242 765.086C269.242 765.883 269.378 766.659 269.648 767.414C269.919 768.164 270.32 768.844 270.852 769.453C271.388 770.057 272.042 770.518 272.812 770.836L271.734 772.398C270.854 772.029 270.109 771.474 269.5 770.734C268.891 769.99 268.432 769.133 268.125 768.164C267.818 767.195 267.667 766.169 267.672 765.086V763.43H269.242V765.086ZM272.227 764.219H264.195V762.594H272.227V764.219ZM275.641 775.437H273.617V761.203H275.641V775.437ZM285.023 770.5H283.062V768.43H285.023V770.5ZM290.508 768.727H277.594V767.273H290.508V768.727ZM285.016 762.922H283.039V761.203H285.016V762.922ZM284.664 763.289C284.664 763.977 284.435 764.578 283.977 765.094C283.518 765.609 282.836 766.023 281.93 766.336C281.029 766.643 279.932 766.831 278.641 766.898L278.102 765.43C279.195 765.378 280.102 765.25 280.82 765.047C281.544 764.839 282.073 764.583 282.406 764.281C282.745 763.979 282.914 763.648 282.914 763.289V763H284.664V763.289ZM285.148 763.289C285.143 763.648 285.31 763.979 285.648 764.281C285.987 764.583 286.518 764.839 287.242 765.047C287.966 765.25 288.88 765.378 289.984 765.43L289.406 766.898C288.12 766.831 287.026 766.641 286.125 766.328C285.229 766.016 284.549 765.604 284.086 765.094C283.622 764.578 283.393 763.977 283.398 763.289V763H285.148V763.289ZM289.281 763.805H278.812V762.328H289.281V763.805ZM288.953 773.086H281.031V774.469H279.07V771.75H286.984V771.055H279.062V769.625H288.953V773.086ZM289.328 775.336H279.07V773.875H289.328V775.336ZM307.359 775.437H305.437V761.203H307.359V775.437ZM305.961 768.328H303.547V766.711H305.961V768.328ZM304.109 774.75H302.242V761.461H304.109V774.75ZM297.664 771.008H295.672V762.797H297.664V771.008ZM296.625 770.242C297.448 770.242 298.247 770.214 299.023 770.156C299.805 770.099 300.607 769.99 301.43 769.828L301.641 771.547C300.74 771.703 299.878 771.815 299.055 771.883C298.237 771.945 297.427 771.974 296.625 771.969H295.672V770.242H296.625ZM319.523 764.734H315.289V763.125H319.523V764.734ZM319.523 767.82H315.289V766.227H319.523V767.82ZM320.906 775.437H318.922V771.836H311.141V770.258H320.906V775.437ZM320.906 769.625H318.922V761.203H320.906V769.625ZM312.891 761.977C313.589 761.977 314.224 762.125 314.797 762.422C315.375 762.719 315.828 763.135 316.156 763.672C316.484 764.203 316.651 764.799 316.656 765.461C316.651 766.138 316.484 766.745 316.156 767.281C315.828 767.818 315.378 768.237 314.805 768.539C314.232 768.841 313.594 768.992 312.891 768.992C312.177 768.992 311.531 768.841 310.953 768.539C310.38 768.237 309.927 767.818 309.594 767.281C309.266 766.74 309.102 766.133 309.102 765.461C309.102 764.799 309.266 764.203 309.594 763.672C309.927 763.135 310.38 762.719 310.953 762.422C311.531 762.125 312.177 761.977 312.891 761.977ZM312.891 763.664C312.521 763.664 312.193 763.734 311.906 763.875C311.62 764.016 311.396 764.224 311.234 764.5C311.073 764.776 310.992 765.096 310.992 765.461C310.992 765.836 311.073 766.161 311.234 766.437C311.396 766.714 311.62 766.927 311.906 767.078C312.193 767.229 312.521 767.305 312.891 767.305C313.245 767.305 313.562 767.229 313.844 767.078C314.125 766.927 314.346 766.714 314.508 766.437C314.669 766.161 314.75 765.836 314.75 765.461C314.75 765.096 314.669 764.776 314.508 764.5C314.346 764.224 314.122 764.016 313.836 763.875C313.555 763.734 313.24 763.664 312.891 763.664ZM333.906 775.453H331.93V770.297H333.906V775.453ZM339.43 771.359H326.461V769.727H339.43V771.359ZM333.68 764.109C333.68 764.917 333.448 765.664 332.984 766.352C332.526 767.034 331.854 767.607 330.969 768.07C330.089 768.534 329.044 768.836 327.836 768.977L327.109 767.422C328.125 767.297 328.997 767.06 329.727 766.711C330.456 766.362 331.005 765.958 331.375 765.5C331.745 765.042 331.93 764.578 331.93 764.109V763.75H333.68V764.109ZM333.93 764.109C333.93 764.568 334.112 765.026 334.477 765.484C334.846 765.943 335.393 766.349 336.117 766.703C336.846 767.057 337.716 767.297 338.727 767.422L338.008 768.977C336.805 768.836 335.76 768.529 334.875 768.055C333.995 767.576 333.323 766.995 332.859 766.312C332.401 765.625 332.172 764.891 332.172 764.109V763.75H333.93V764.109ZM338.234 764.422H327.633V762.852H338.234V764.422ZM333.906 763.391H331.93V761.234H333.906V763.391ZM351.5 775.414H349.5V761.203H351.5V775.414ZM353.508 768.312H350.984V766.672H353.508V768.312ZM347.703 762.672C347.698 764.151 347.484 765.518 347.062 766.773C346.646 768.029 345.961 769.182 345.008 770.234C344.055 771.286 342.805 772.193 341.258 772.953L340.133 771.43C341.404 770.789 342.453 770.062 343.281 769.25C344.109 768.432 344.727 767.513 345.133 766.492C345.539 765.466 345.745 764.312 345.75 763.031V762.672H347.703ZM346.75 764.305H340.93V762.672H346.75V764.305Z" fill="white"/> -<path d="M80.2334 43.1544C81.0801 43.1599 81.8548 43.3508 82.5576 43.7272C83.2604 44.1035 83.8276 44.7232 84.2593 45.5865C84.6965 46.4498 84.915 47.5759 84.915 48.9649C84.915 50.3263 84.7214 51.4994 84.334 52.4845C83.9466 53.464 83.3877 54.2138 82.6572 54.734C81.9323 55.2486 81.0801 55.506 80.1006 55.506C79.3369 55.506 78.6535 55.3593 78.0503 55.066C77.4526 54.7672 76.9684 54.3605 76.5977 53.8458C76.2324 53.3312 76.0055 52.7418 75.917 52.0777H78.042C78.1195 52.3932 78.2523 52.6671 78.4404 52.8995C78.6286 53.1319 78.861 53.3118 79.1377 53.4391C79.4199 53.5663 79.7409 53.63 80.1006 53.63C80.6761 53.63 81.1659 53.4667 81.5698 53.1402C81.9793 52.8137 82.2892 52.3434 82.4995 51.7291C82.7098 51.1148 82.8177 50.3788 82.8232 49.5211H82.6987C82.4995 49.8642 82.2422 50.1603 81.9268 50.4093C81.6169 50.6528 81.2627 50.8409 80.8643 50.9737C80.4714 51.1065 80.0563 51.173 79.6191 51.173C78.9053 51.173 78.2578 51.0069 77.6768 50.6749C77.1012 50.3373 76.6447 49.8725 76.3071 49.2804C75.9696 48.6883 75.8008 48.0214 75.8008 47.2799C75.8008 46.4941 75.9834 45.7885 76.3486 45.1632C76.7194 44.5323 77.2396 44.0398 77.9092 43.6856C78.5843 43.3259 79.359 43.1489 80.2334 43.1544ZM80.2334 44.8976C79.7962 44.8976 79.3978 45.0027 79.0381 45.213C78.6839 45.4177 78.4045 45.7 78.1997 46.0597C77.995 46.4138 77.8953 46.8012 77.9009 47.2218C77.9009 47.6479 78.0005 48.038 78.1997 48.3922C78.3989 48.7408 78.6729 49.0175 79.0215 49.2223C79.3701 49.427 79.7658 49.5294 80.2085 49.5294C80.6401 49.5294 81.0358 49.4215 81.3955 49.2057C81.7607 48.9898 82.0485 48.7049 82.2588 48.3507C82.4691 47.9965 82.5742 47.6147 82.5742 47.2052C82.5742 46.7957 82.4718 46.4138 82.2671 46.0597C82.0623 45.7055 81.7829 45.4233 81.4287 45.213C81.0745 45.0027 80.6761 44.8976 80.2334 44.8976ZM88.0444 53.8375C87.8065 53.8375 87.5879 53.7794 87.3887 53.6632C87.195 53.547 87.04 53.3893 86.9238 53.19C86.8076 52.9908 86.7523 52.775 86.7578 52.5426C86.7523 52.3157 86.8076 52.1054 86.9238 51.9117C87.04 51.7125 87.195 51.5576 87.3887 51.4469C87.5879 51.3307 87.8065 51.2726 88.0444 51.2726C88.2713 51.2726 88.4816 51.3307 88.6753 51.4469C88.8745 51.5576 89.0322 51.7125 89.1484 51.9117C89.2646 52.1054 89.3228 52.3157 89.3228 52.5426C89.3228 52.775 89.2646 52.9908 89.1484 53.19C89.0322 53.3893 88.8745 53.547 88.6753 53.6632C88.4816 53.7794 88.2713 53.8375 88.0444 53.8375ZM88.0444 47.3961C87.8065 47.3961 87.5879 47.338 87.3887 47.2218C87.195 47.1056 87.04 46.9479 86.9238 46.7486C86.8076 46.5494 86.7523 46.3336 86.7578 46.1012C86.7523 45.8743 86.8076 45.664 86.9238 45.4703C87.04 45.2711 87.195 45.1161 87.3887 45.0055C87.5879 44.8893 87.8065 44.8312 88.0444 44.8312C88.2713 44.8312 88.4816 44.8893 88.6753 45.0055C88.8745 45.1161 89.0322 45.2711 89.1484 45.4703C89.2646 45.664 89.3228 45.8743 89.3228 46.1012C89.3228 46.3336 89.2646 46.5494 89.1484 46.7486C89.0322 46.9479 88.8745 47.1056 88.6753 47.2218C88.4816 47.338 88.2713 47.3961 88.0444 47.3961ZM91.124 51.3805L96.3203 43.3204H97.748V45.7774H96.8599L93.3403 51.2311V51.3307H100.595V53.0987H91.124V51.3805ZM96.9595 52.5841L96.9844 51.8038V43.3204H99.0264V55.3399H96.9595V52.5841ZM107.053 55.3399H104.878V45.4288H104.812L101.998 47.2301V45.2462L104.978 43.3204H107.053V55.3399Z" fill="black"/> -<path opacity="0.35" d="M369.133 43.5H352.733C350.634 43.5 348.933 45.2013 348.933 47.3V51.7C348.933 53.7987 350.634 55.5 352.733 55.5H369.133C371.232 55.5 372.933 53.7987 372.933 51.7V47.3C372.933 45.2013 371.232 43.5 369.133 43.5Z" stroke="black"/> -<path opacity="0.4" d="M374.433 47.7812V51.8568C375.237 51.5117 375.761 50.7086 375.761 49.819C375.761 48.9294 375.237 48.1265 374.433 47.7812Z" fill="black"/> -<path d="M368.933 45H352.933C351.552 45 350.433 46.1193 350.433 47.5V51.5C350.433 52.8807 351.552 54 352.933 54H368.933C370.314 54 371.433 52.8807 371.433 51.5V47.5C371.433 46.1193 370.314 45 368.933 45Z" fill="black"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M332.703 46.104C335.19 46.1041 337.582 47.0262 339.385 48.6796C339.52 48.8073 339.737 48.8057 339.871 48.676L341.169 47.4126C341.236 47.3468 341.274 47.2577 341.273 47.165C341.273 47.0724 341.234 46.9837 341.166 46.9187C336.435 42.544 328.971 42.544 324.24 46.9187C324.171 46.9837 324.132 47.0723 324.132 47.165C324.131 47.2577 324.169 47.3468 324.237 47.4126L325.534 48.676C325.668 48.8059 325.885 48.8075 326.021 48.6796C327.824 47.0261 330.216 46.104 332.703 46.104ZM332.7 50.3243C334.057 50.3242 335.366 50.8359 336.372 51.76C336.508 51.8912 336.723 51.8883 336.855 51.7536L338.142 50.4343C338.21 50.3651 338.248 50.2712 338.247 50.1737C338.246 50.0761 338.206 49.9831 338.137 49.9153C335.073 47.0244 330.329 47.0244 327.265 49.9153C327.196 49.9831 327.156 50.0762 327.155 50.1738C327.154 50.2713 327.192 50.3652 327.26 50.4343L328.547 51.7536C328.68 51.8883 328.894 51.8912 329.03 51.76C330.036 50.8365 331.343 50.3248 332.7 50.3243ZM335.224 53.1178C335.226 53.2232 335.189 53.3247 335.122 53.3985L332.945 55.8533C332.881 55.9254 332.794 55.966 332.704 55.966C332.613 55.966 332.526 55.9254 332.462 55.8533L330.285 53.3985C330.218 53.3247 330.181 53.2231 330.183 53.1177C330.185 53.0124 330.225 52.9126 330.295 52.842C331.686 51.5281 333.721 51.5281 335.112 52.842C335.182 52.9127 335.222 53.0125 335.224 53.1178Z" fill="black"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M316.633 44.6819C316.633 44.0488 316.155 43.5356 315.566 43.5356H314.499C313.91 43.5356 313.433 44.0488 313.433 44.6819V54.6158C313.433 55.2489 313.91 55.7621 314.499 55.7621H315.566C316.155 55.7621 316.633 55.2489 316.633 54.6158V44.6819ZM309.199 45.9809H310.265C310.854 45.9809 311.332 46.5064 311.332 47.1547V54.5883C311.332 55.2366 310.854 55.7621 310.265 55.7621H309.199C308.609 55.7621 308.132 55.2366 308.132 54.5883V47.1547C308.132 46.5064 308.609 45.9809 309.199 45.9809ZM304.867 48.63H303.8C303.211 48.63 302.733 49.1622 302.733 49.8187V54.5734C302.733 55.2299 303.211 55.762 303.8 55.762H304.867C305.456 55.762 305.933 55.2299 305.933 54.5734V49.8187C305.933 49.1622 305.456 48.63 304.867 48.63ZM299.566 51.0753H298.499C297.91 51.0753 297.433 51.5999 297.433 52.247V54.5904C297.433 55.2375 297.91 55.7621 298.499 55.7621H299.566C300.155 55.7621 300.633 55.2375 300.633 54.5904V52.247C300.633 51.5999 300.155 51.0753 299.566 51.0753Z" fill="black"/> -</g> -</g> -</g> -<mask id="mask4_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="426" y="221" width="3" height="105"> -<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="white"/> -</mask> -<g mask="url(#mask4_1837_9941)"> -<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="url(#paint0_linear_1837_9941)"/> -</g> -<mask id="mask5_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="428" y="221" width="2" height="105"> -<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="white"/> -</mask> -<g mask="url(#mask5_1837_9941)"> -<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="url(#paint1_linear_1837_9941)"/> -</g> -<mask id="mask6_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="3" height="67"> -<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="white"/> -</mask> -<g mask="url(#mask6_1837_9941)"> -<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="url(#paint2_linear_1837_9941)"/> -</g> -<mask id="mask7_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="1" height="67"> -<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.354 0 200.307L0.706443 199.448V265.633V265.637Z" fill="white"/> -</mask> -<g mask="url(#mask7_1837_9941)"> -<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.354 0 200.307L0.706443 199.448V265.633V265.637Z" fill="url(#paint3_linear_1837_9941)"/> -</g> -<mask id="mask8_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="199" width="2" height="67"> -<path d="M2.11914 265.653H3.63295V199.447H2.11914V265.653Z" fill="white"/> -</mask> -<g mask="url(#mask8_1837_9941)"> -<path d="M2.11914 265.653H3.63295V199.447H2.11914V265.653Z" fill="url(#paint4_linear_1837_9941)"/> -</g> -<mask id="mask9_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="3" height="67"> -<path d="M2.11943 348.924H0.706543V282.72H2.11943V348.924Z" fill="white"/> -</mask> -<g mask="url(#mask9_1837_9941)"> -<path d="M2.11943 348.924H0.706543V282.72H2.11943V348.924Z" fill="url(#paint5_linear_1837_9941)"/> -</g> -<mask id="mask10_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="1" height="67"> -<path d="M0.706443 348.928L0 348.068C0.333038 341.036 0.357259 290.645 0 283.598L0.706443 282.738V348.924V348.928Z" fill="white"/> -</mask> -<g mask="url(#mask10_1837_9941)"> -<path d="M0.706443 348.928L0 348.068C0.333038 341.036 0.357259 290.645 0 283.598L0.706443 282.738V348.924V348.928Z" fill="url(#paint6_linear_1837_9941)"/> -</g> -<mask id="mask11_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="282" width="2" height="67"> -<path d="M2.11914 348.944H3.63295V282.738H2.11914V348.944Z" fill="white"/> -</mask> -<g mask="url(#mask11_1837_9941)"> -<path d="M2.11914 348.944H3.63295V282.738H2.11914V348.944Z" fill="url(#paint7_linear_1837_9941)"/> -</g> -<mask id="mask12_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="3" height="35"> -<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="white"/> -</mask> -<g mask="url(#mask12_1837_9941)"> -<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="url(#paint8_linear_1837_9941)"/> -</g> -<mask id="mask13_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="1" height="35"> -<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="white"/> -</mask> -<g mask="url(#mask13_1837_9941)"> -<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="url(#paint9_linear_1837_9941)"/> -</g> -<mask id="mask14_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="136" width="2" height="35"> -<path d="M2.11914 170.878H3.63295V136.895H2.11914V170.878Z" fill="white"/> -</mask> -<g mask="url(#mask14_1837_9941)"> -<path d="M2.11914 170.878H3.63295V136.895H2.11914V170.878Z" fill="url(#paint10_linear_1837_9941)"/> -</g> -<path d="M246.886 60.5405H179.37C171.773 60.5405 165.615 54.3824 165.615 46.7851C165.615 39.1878 171.773 33.0295 179.37 33.0295H246.886C254.483 33.0295 260.641 39.1878 260.641 46.7851C260.641 54.3824 254.483 60.5405 246.886 60.5405ZM243.083 40.7803C239.767 40.7803 237.079 43.4688 237.079 46.7851C237.079 50.1033 239.767 52.7899 243.083 52.7899C246.4 52.7899 249.088 50.1033 249.088 46.7851C249.088 43.4688 246.4 40.7803 243.083 40.7803Z" fill="#1D1D1B"/> -<mask id="mask15_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="40" width="13" height="13"> -<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="white"/> -</mask> -<g mask="url(#mask15_1837_9941)"> -<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="url(#paint11_linear_1837_9941)"/> -</g> -<mask id="mask16_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="41" width="12" height="12"> -<path d="M243.063 52.3916C242.504 52.3916 241.943 52.3089 241.4 52.1373C240.526 51.8628 239.747 51.3804 239.117 50.7526C238.473 50.1067 238.011 49.3216 237.746 48.4779C237.294 47.0347 237.419 45.422 238.182 44.0535C238.437 43.5994 238.75 43.1836 239.115 42.8203C239.745 42.1886 240.524 41.7082 241.398 41.4317C241.941 41.2621 242.502 41.1794 243.061 41.1794C243.715 41.1794 244.367 41.2924 244.982 41.5124C245.751 41.7889 246.464 42.2289 247.053 42.8203C247.419 43.1836 247.734 43.5994 247.986 44.0535C248.749 45.422 248.874 47.0347 248.42 48.4779C248.155 49.3216 247.697 50.1067 247.051 50.7526C246.462 51.342 245.749 51.782 244.98 52.0565C244.367 52.2765 243.717 52.3916 243.063 52.3916ZM243.083 43.3532C241.19 43.3532 239.654 44.8892 239.654 46.7845C239.654 48.6798 241.19 50.2158 243.083 50.2158C244.978 50.2158 246.516 48.6798 246.516 46.7845C246.516 44.8892 244.978 43.3532 243.083 43.3532Z" fill="white"/> -</mask> -<g mask="url(#mask16_1837_9941)"> -<rect x="235.513" y="39.4111" width="14.7748" height="14.7748" fill="url(#pattern0_1837_9941)"/> -</g> -<mask id="mask17_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="239" y="43" width="8" height="8"> -<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="white"/> -</mask> -<g mask="url(#mask17_1837_9941)"> -<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="url(#paint12_linear_1837_9941)"/> -</g> -<mask id="mask18_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="240" y="43" width="7" height="7"> -<path d="M243.081 49.7905C241.416 49.7905 240.08 48.4463 240.08 46.7892C240.08 45.124 241.416 43.7838 243.081 43.7838C244.74 43.7838 246.084 45.124 246.084 46.7892C246.084 47.2636 245.973 47.7156 245.778 48.1153C245.669 47.6369 245.241 47.2817 244.732 47.2817C244.139 47.2817 243.66 47.7621 243.66 48.3535C243.66 48.8823 244.042 49.3223 244.546 49.4091C244.112 49.6513 243.612 49.7905 243.081 49.7905Z" fill="white"/> -</mask> -<g mask="url(#mask18_1837_9941)"> -<rect x="238.337" y="42.2378" width="8.92141" height="8.92141" fill="url(#pattern1_1837_9941)"/> -</g> -<mask id="mask19_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="244" y="48" width="2" height="2"> -<path d="M244.732 49.4263C244.668 49.4263 244.607 49.4182 244.546 49.4081C245.077 49.1114 245.507 48.6593 245.778 48.1143C245.794 48.189 245.804 48.2698 245.804 48.3525C245.804 48.9439 245.324 49.4263 244.732 49.4263Z" fill="white"/> -</mask> -<g mask="url(#mask19_1837_9941)"> -<rect x="243.182" y="46.2739" width="4.07723" height="4.88459" fill="url(#pattern2_1837_9941)"/> -</g> -<mask id="mask20_1837_9941" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="243" y="47" width="3" height="3"> -<path d="M244.547 49.4082C244.042 49.3214 243.661 48.8814 243.661 48.3526C243.661 47.7612 244.139 47.2808 244.732 47.2808C245.241 47.2808 245.669 47.636 245.778 48.1144C245.507 48.6593 245.078 49.1115 244.547 49.4082Z" fill="white"/> -</mask> -<g mask="url(#mask20_1837_9941)"> -<rect x="242.173" y="46.2739" width="5.08643" height="4.88459" fill="url(#pattern3_1837_9941)"/> -</g> -<defs> -<pattern id="pattern0_1837_9941" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image0_1837_9941" transform="scale(0.0666667)"/> -</pattern> -<pattern id="pattern1_1837_9941" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image1_1837_9941" transform="scale(0.111111)"/> -</pattern> -<pattern id="pattern2_1837_9941" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image2_1837_9941" transform="scale(0.25 0.2)"/> -</pattern> -<pattern id="pattern3_1837_9941" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image3_1837_9941" transform="scale(0.2)"/> -</pattern> -<linearGradient id="paint0_linear_1837_9941" x1="427.525" y1="221.428" x2="427.525" y2="325.938" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2B1D2A"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2B1D2A"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint1_linear_1837_9941" x1="429.38" y1="221.455" x2="429.38" y2="325.943" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint2_linear_1837_9941" x1="1.41299" y1="199.429" x2="1.41299" y2="265.633" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint3_linear_1837_9941" x1="0.353221" y1="199.448" x2="0.353221" y2="265.637" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint4_linear_1837_9941" x1="2.87604" y1="265.653" x2="2.87604" y2="199.446" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint5_linear_1837_9941" x1="1.41299" y1="282.72" x2="1.41299" y2="348.924" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint6_linear_1837_9941" x1="0.353221" y1="282.738" x2="0.353221" y2="348.928" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint7_linear_1837_9941" x1="2.87604" y1="348.944" x2="2.87604" y2="282.737" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint8_linear_1837_9941" x1="1.41299" y1="136.878" x2="1.41299" y2="170.859" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint9_linear_1837_9941" x1="0.353222" y1="136.895" x2="0.353222" y2="170.862" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint10_linear_1837_9941" x1="2.87604" y1="170.878" x2="2.87604" y2="136.895" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint11_linear_1837_9941" x1="243.083" y1="52.4197" x2="243.083" y2="40.5892" gradientUnits="userSpaceOnUse"> -<stop stop-color="#666666"/> -<stop offset="1" stop-color="#010104"/> -</linearGradient> -<linearGradient id="paint12_linear_1837_9941" x1="243.083" y1="43.5652" x2="243.083" y2="50.325" gradientUnits="userSpaceOnUse"> -<stop stop-color="#0B131C"/> -<stop offset="1" stop-color="#354039"/> -</linearGradient> -<clipPath id="clip0_1837_9941"> -<rect width="382" height="827" fill="white" transform="translate(24 20)"/> -</clipPath> -<image id="image0_1837_9941" width="15" height="15" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAUBJREFUKJGFks1S3TAMhT/JshPndl8ehIH3X8LQ9m1uAP+IhXMbAs1U2nhkHR0dSfLz7s45sTRNRItYtEP8slz48/sXegb8n90/PGJnnxoCACKCqo4O7Jh+Cr6ZM1SJCuEL+LTtoIFoEdm81kop70dms/iNxbtz87C1b2aEYOAOIiOmYSd3902vYmbkJRMtEmMkpUQpdVBseSZbFWBLKExpIsaIiCIiXC4/iDHy+rrSWuO9lAFeluUvuJRCnjPIkJBzZkoJVSGEwDxn1vW6a/7K/Pk9pYSZMc8ZC4E3d1R3mWZhH7/70KOq4OCAqtJ756011nXluq47eJrnw/i9d2qt4yB8FCy1YMEIQdGt0+7+/UhEFdUxqNYq12uh9T628EkinFzY7ZJqa4d4v61ShJfnJwTw+4fHf9U4tZfnJwA+AH+jc5A39zmDAAAAAElFTkSuQmCC"/> -<image id="image1_1837_9941" width="9" height="9" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAABHNCSVQICAgIfAhkiAAAAMRJREFUGJWF0LFKA1EQheH/3GxW4qIkogSCjUGstLDQKnUqKx9CH0vs8kYhxNJCElJkCSy6985YhDUoQqb+ivmP2lnm/HOWF6SDI5Rqwj4g+4sUiJcPpPELGoyQ1SjF36i+fcavn2D9hp9c4Wc3yCJZA+LgHoaPaPqKVlP88BRvd8DSFlle4P07WM+hWsJXCXIgIjfCz5OzCVQLyAu808Ptk1C+A47onXtTIbWw7gXEDWHzQajKbY+O+95UyCJYQm7Abr5vonZV760IjhkAAAAASUVORK5CYII="/> -<image id="image2_1837_9941" width="4" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAFCAYAAABirU3bAAAABHNCSVQICAgIfAhkiAAAAEVJREFUCJljlFHV+M+ABFjY2FkYUAXYWBg8XFwZPnz8yHDi9CkGRj1Lk/+srKwMf//+Zfj37x9EBQPDfwYWFiYGBgYmBgAtwhBN2erPwAAAAABJRU5ErkJggg=="/> -<image id="image3_1837_9941" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABHNCSVQICAgIfAhkiAAAAGJJREFUCJk1wbEKglAAheH/yE0rp8A18A1samxpa+4BfNMew7EHEBPkgiBeT5PfJzWtNXT4XGES4fshMPewTCADK/JGRl7i04X368HzVgNGut7NGjkuPxxHUkooHArLG2B2f3kOIpEJnXBlAAAAAElFTkSuQmCC"/> -</defs> -</svg> diff --git a/client/src/assets/image/heundeut.svg b/client/src/assets/image/heundeut.svg deleted file mode 100644 index c78ca8c9b..000000000 --- a/client/src/assets/image/heundeut.svg +++ /dev/null @@ -1 +0,0 @@ -<svg width="35" height="33" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" overflow="hidden"><defs><image width="80" height="76" xlink:href="data:image/png;base64,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u1A7lAYREAEREAEREAEREIHKELBR/Zo2Wu2KK7MjO8QIRAhNtLg4Cl9L2TArwxBk082Wk00padBFRUAEREAEREAEREAERKBqBIqcHbGTG5jkaEfs7YlyhxixTuyhWYVauoFfcJGywjckvOXE3vL2L/z6uqAIiIAIiIAIiIAIiIAIVJFAwbMjdpKjPdnRE+cOMSIn9p6c9KEIiIAIiIAIiIAIiIAIVIJA0DTXYYXENb7Wsec1+fCFndzAJIed7OhDbocY4XFQL3Ji7wNMH4uACIiACIiACIiACIiAzwRs+P7ArIVN65rxZU552YKouANdsdFeLqDnZXqKETmx92SlD0VABERABERABERABESgEgQoEgIIEmTmdh4ZspF5EaHXTnIMuEBPMYIfyYl9ADR9JQIiIAIiIAIiIAIiIAI+E3DBT5z8eooRFxIHQSQndp9ruNIuAiIgAiIgAiIgAiLgLAFH/MR7ixFHEqeV2J2tvkqYCIiACIiACIiACIiA7wSsCVW5i533FiME60DitBK77zVc6RcBERABERABERABERCBAQR29/uuvTiJVmLvB0ifi4AIiIAIiIAIiIAIiIAITESgp88Iz+iCEzuS8QD2vWFo9jJN2kRABERABERABERABERABKpDoK8YccGJHZjlN1KduqaciIAIiIAIiIAIiIAIiEAXgb5ixBEndvmNdBWX/hABERABERABERABERCB6hDoK0aYRQec2JmMfdhnsHAKX7WJgAiIgAiIgAiIgAiIgAhUhEBfB3bmzwUndoiQKfiMTDdpsqVNBERABERABERABERABESgMgSGzYyUvhI7Zme0+GFlqpsyIgIiIAIiIAIiIAIi4AoBDPpPo6c9ZfvbGScK59zCuTfbkxt9zz5QjMiJvS83fSECIiACIiACIiACIiAC3hJ4+y/DBYiRGQgGukLkYYFkJzUgSvjadxsoRuTE3pebvhABERABERABERABERABbwmEu8xBCJHDcBI/iEw8mHFGvsC5b+Dcq3ZyY8DJB4oR/i4IzF28cP+Kf5e0yYm9JPC6rAiIgAiIgAiIgAiIQPUIcFYEftlzyNlDOeRuC0LkDmZFNji5Mej8Q8VIe2plAycZOMUy6CIZfKfFDzOAqFOIgAiIgAiIgAiIgAiIAE20IBbmggbMtIzZkzURCJ0Q/7agIzaHnXuoGHHFbwTK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" preserveAspectRatio="none" id="img0"></image><clipPath id="clip1"><rect x="0" y="0" width="2216978" height="2095500"/></clipPath></defs><g transform="translate(-462 -414)"><g><g transform="matrix(0.00015748 0 0 0.00015748 463 414)"><g clip-path="url(#clip1)" transform="scale(1.00249 1)"><use width="100%" height="100%" xlink:href="#img0" opacity="1" transform="scale(2760.87 2760.87)"></use></g></g></g></g></svg> \ No newline at end of file diff --git a/client/src/assets/image/memberReportMockup.svg b/client/src/assets/image/memberReportMockup.svg deleted file mode 100644 index efbaf3c1c..000000000 --- a/client/src/assets/image/memberReportMockup.svg +++ /dev/null @@ -1,311 +0,0 @@ -<svg width="100%" height="100%" viewBox="0 0 430 867" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<path d="M358.532 867H71.3893C33.968 867 3.6333 836.665 3.6333 799.244V348.944V282.739V265.653V199.447V170.878V136.894V67.6347C3.6333 30.2134 33.968 -0.12131 71.3893 -0.12131H358.532C395.954 -0.12131 426.288 30.2134 426.288 67.6347V799.244C426.288 836.665 395.954 867 358.532 867ZM71.9202 1.8971C35.3203 1.8971 5.65171 31.5657 5.65171 68.1655V798.713C5.65171 835.312 35.3203 864.982 71.9202 864.982H358.001C394.601 864.982 424.27 835.312 424.27 798.713V68.1655C424.27 31.5657 394.601 1.8971 358.001 1.8971H71.9202ZM357.471 862.963H72.451C36.6727 862.963 7.67012 833.96 7.67012 798.182V68.6964C7.67012 32.9181 36.6727 3.91551 72.451 3.91551H357.471C393.247 3.91551 422.251 32.9181 422.251 68.6964V798.182C422.251 833.96 393.247 862.963 357.471 862.963ZM73.0908 6.49706C38.683 6.49706 10.7906 34.3895 10.7906 68.7973V798.081C10.7906 832.489 38.683 860.381 73.0908 860.381H356.831C391.239 860.381 419.131 832.489 419.131 798.081V68.7973C419.131 34.3895 391.239 6.49706 356.831 6.49706H73.0908Z" fill="#5E465D"/> -<path d="M358.001 864.981H71.9193C35.3195 864.981 5.65088 835.312 5.65088 798.713V68.1653C5.65088 31.5655 35.3195 1.89689 71.9193 1.89689H358.001C394.6 1.89689 424.269 31.5655 424.269 68.1653V798.713C424.269 835.312 394.6 864.981 358.001 864.981ZM72.4502 3.9153C36.6718 3.9153 7.66929 32.9179 7.66929 68.6962V798.181C7.66929 833.96 36.6718 862.963 72.4502 862.963H357.47C393.246 862.963 422.251 833.96 422.251 798.181V68.6962C422.251 32.9179 393.246 3.9153 357.47 3.9153H72.4502Z" fill="#A597A4"/> -<path d="M356.831 860.381H73.0908C38.6829 860.381 10.7905 832.489 10.7905 798.08V68.7972C10.7905 34.3893 38.6829 6.49689 73.0908 6.49689H356.831C391.239 6.49689 419.131 34.3893 419.131 68.7972V798.08C419.131 832.489 391.239 860.381 356.831 860.381ZM72.7739 20.3169C45.9593 20.3169 24.223 42.0552 24.223 68.8698V798.008C24.223 824.823 45.9593 846.561 72.7759 846.561H357.146C383.962 846.561 405.698 824.823 405.698 798.008V68.8698C405.698 42.0552 383.962 20.3169 357.146 20.3169H324.147H105.383C94.1145 20.3169 83.421 20.3169 72.7739 20.3169Z" fill="#1D1D1B"/> -<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> -<mask id="mask0_1837_11068" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="24" y="20" width="382" height="827"> -<path d="M357.145 846.562H72.7755C45.9589 846.562 24.2227 824.823 24.2227 798.008V68.8702C24.2227 42.0556 45.9589 20.3173 72.7735 20.3173C83.4206 20.3173 94.1141 20.3173 105.383 20.3173H324.146H357.145C383.962 20.3173 405.698 42.0556 405.698 68.8702V798.008C405.698 824.823 383.962 846.562 357.145 846.562ZM179.37 33.0293C171.772 33.0293 165.614 39.1875 165.614 46.7848C165.614 54.3821 171.772 60.5403 179.37 60.5403H246.886C254.483 60.5403 260.641 54.3821 260.641 46.7848C260.641 39.1875 254.483 33.0293 246.886 33.0293H179.37Z" fill="white"/> -</mask> -<g mask="url(#mask0_1837_11068)"> -<g clip-path="url(#clip0_1837_11068)"> -<path d="M406 20H24V847H406V20Z" fill="#F1F0F5"/> -<path d="M80.2334 43.1544C81.0801 43.1599 81.8548 43.3508 82.5576 43.7272C83.2604 44.1035 83.8276 44.7232 84.2593 45.5865C84.6965 46.4498 84.915 47.5759 84.915 48.9649C84.915 50.3263 84.7214 51.4994 84.334 52.4845C83.9466 53.464 83.3877 54.2138 82.6572 54.734C81.9323 55.2486 81.0801 55.506 80.1006 55.506C79.3369 55.506 78.6535 55.3593 78.0503 55.066C77.4526 54.7672 76.9684 54.3605 76.5977 53.8458C76.2324 53.3312 76.0055 52.7418 75.917 52.0777H78.042C78.1195 52.3932 78.2523 52.6671 78.4404 52.8995C78.6286 53.1319 78.861 53.3118 79.1377 53.4391C79.4199 53.5663 79.7409 53.63 80.1006 53.63C80.6761 53.63 81.1659 53.4667 81.5698 53.1402C81.9793 52.8137 82.2892 52.3434 82.4995 51.7291C82.7098 51.1148 82.8177 50.3788 82.8232 49.5211H82.6987C82.4995 49.8642 82.2422 50.1603 81.9268 50.4093C81.6169 50.6528 81.2627 50.8409 80.8643 50.9737C80.4714 51.1065 80.0563 51.173 79.6191 51.173C78.9053 51.173 78.2578 51.0069 77.6768 50.6749C77.1012 50.3373 76.6447 49.8725 76.3071 49.2804C75.9696 48.6883 75.8008 48.0214 75.8008 47.2799C75.8008 46.4941 75.9834 45.7885 76.3486 45.1632C76.7194 44.5323 77.2396 44.0398 77.9092 43.6856C78.5843 43.3259 79.359 43.1489 80.2334 43.1544ZM80.2334 44.8976C79.7962 44.8976 79.3978 45.0027 79.0381 45.213C78.6839 45.4177 78.4045 45.7 78.1997 46.0597C77.995 46.4138 77.8953 46.8012 77.9009 47.2218C77.9009 47.6479 78.0005 48.038 78.1997 48.3922C78.3989 48.7408 78.6729 49.0175 79.0215 49.2223C79.3701 49.427 79.7658 49.5294 80.2085 49.5294C80.6401 49.5294 81.0358 49.4215 81.3955 49.2057C81.7607 48.9898 82.0485 48.7049 82.2588 48.3507C82.4691 47.9965 82.5742 47.6147 82.5742 47.2052C82.5742 46.7957 82.4718 46.4138 82.2671 46.0597C82.0623 45.7055 81.7829 45.4233 81.4287 45.213C81.0745 45.0027 80.6761 44.8976 80.2334 44.8976ZM88.0444 53.8375C87.8065 53.8375 87.5879 53.7794 87.3887 53.6632C87.195 53.547 87.04 53.3893 86.9238 53.19C86.8076 52.9908 86.7523 52.775 86.7578 52.5426C86.7523 52.3157 86.8076 52.1054 86.9238 51.9117C87.04 51.7125 87.195 51.5576 87.3887 51.4469C87.5879 51.3307 87.8065 51.2726 88.0444 51.2726C88.2713 51.2726 88.4816 51.3307 88.6753 51.4469C88.8745 51.5576 89.0322 51.7125 89.1484 51.9117C89.2646 52.1054 89.3228 52.3157 89.3228 52.5426C89.3228 52.775 89.2646 52.9908 89.1484 53.19C89.0322 53.3893 88.8745 53.547 88.6753 53.6632C88.4816 53.7794 88.2713 53.8375 88.0444 53.8375ZM88.0444 47.3961C87.8065 47.3961 87.5879 47.338 87.3887 47.2218C87.195 47.1056 87.04 46.9479 86.9238 46.7486C86.8076 46.5494 86.7523 46.3336 86.7578 46.1012C86.7523 45.8743 86.8076 45.664 86.9238 45.4703C87.04 45.2711 87.195 45.1161 87.3887 45.0055C87.5879 44.8893 87.8065 44.8312 88.0444 44.8312C88.2713 44.8312 88.4816 44.8893 88.6753 45.0055C88.8745 45.1161 89.0322 45.2711 89.1484 45.4703C89.2646 45.664 89.3228 45.8743 89.3228 46.1012C89.3228 46.3336 89.2646 46.5494 89.1484 46.7486C89.0322 46.9479 88.8745 47.1056 88.6753 47.2218C88.4816 47.338 88.2713 47.3961 88.0444 47.3961ZM91.124 51.3805L96.3203 43.3204H97.748V45.7774H96.8599L93.3403 51.2311V51.3307H100.595V53.0987H91.124V51.3805ZM96.9595 52.5841L96.9844 51.8038V43.3204H99.0264V55.3399H96.9595V52.5841ZM107.053 55.3399H104.878V45.4288H104.812L101.998 47.2301V45.2462L104.978 43.3204H107.053V55.3399Z" fill="black"/> -<path opacity="0.35" d="M369.133 43.5H352.733C350.634 43.5 348.933 45.2013 348.933 47.3V51.7C348.933 53.7987 350.634 55.5 352.733 55.5H369.133C371.232 55.5 372.933 53.7987 372.933 51.7V47.3C372.933 45.2013 371.232 43.5 369.133 43.5Z" stroke="black"/> -<path opacity="0.4" d="M374.433 47.7812V51.8568C375.237 51.5117 375.761 50.7086 375.761 49.819C375.761 48.9294 375.237 48.1265 374.433 47.7812Z" fill="black"/> -<path d="M368.933 45H352.933C351.552 45 350.433 46.1193 350.433 47.5V51.5C350.433 52.8807 351.552 54 352.933 54H368.933C370.314 54 371.433 52.8807 371.433 51.5V47.5C371.433 46.1193 370.314 45 368.933 45Z" fill="black"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M332.703 46.104C335.19 46.1041 337.582 47.0262 339.385 48.6796C339.521 48.8073 339.737 48.8057 339.871 48.676L341.169 47.4126C341.236 47.3468 341.274 47.2577 341.273 47.165C341.273 47.0724 341.234 46.9837 341.166 46.9187C336.435 42.544 328.971 42.544 324.24 46.9187C324.171 46.9837 324.132 47.0723 324.132 47.165C324.131 47.2577 324.169 47.3468 324.237 47.4126L325.534 48.676C325.668 48.8059 325.885 48.8075 326.021 48.6796C327.824 47.0261 330.216 46.104 332.703 46.104ZM332.7 50.3243C334.057 50.3242 335.366 50.8359 336.372 51.76C336.508 51.8912 336.723 51.8883 336.855 51.7536L338.142 50.4343C338.21 50.3651 338.248 50.2712 338.247 50.1737C338.246 50.0761 338.206 49.9831 338.137 49.9153C335.073 47.0244 330.329 47.0244 327.265 49.9153C327.196 49.9831 327.156 50.0762 327.155 50.1738C327.154 50.2714 327.192 50.3652 327.26 50.4343L328.547 51.7536C328.68 51.8883 328.894 51.8912 329.03 51.76C330.036 50.8365 331.343 50.3248 332.7 50.3243ZM335.224 53.1178C335.226 53.2232 335.189 53.3247 335.122 53.3985L332.945 55.8533C332.881 55.9254 332.794 55.966 332.704 55.966C332.613 55.966 332.526 55.9254 332.462 55.8533L330.285 53.3985C330.218 53.3247 330.181 53.2231 330.183 53.1177C330.185 53.0124 330.225 52.9126 330.295 52.842C331.686 51.5281 333.722 51.5281 335.112 52.842C335.182 52.9127 335.222 53.0125 335.224 53.1178Z" fill="black"/> -<path fill-rule="evenodd" clip-rule="evenodd" d="M316.633 44.6824C316.633 44.0493 316.155 43.5361 315.566 43.5361H314.499C313.91 43.5361 313.433 44.0493 313.433 44.6824V54.6163C313.433 55.2494 313.91 55.7625 314.499 55.7625H315.566C316.155 55.7625 316.633 55.2494 316.633 54.6163V44.6824ZM309.199 45.9814H310.265C310.854 45.9814 311.332 46.5069 311.332 47.1552V54.5888C311.332 55.237 310.854 55.7625 310.265 55.7625H309.199C308.609 55.7625 308.132 55.237 308.132 54.5888V47.1552C308.132 46.5069 308.609 45.9814 309.199 45.9814ZM304.867 48.6305H303.8C303.211 48.6305 302.733 49.1627 302.733 49.8191V54.5739C302.733 55.2303 303.211 55.7625 303.8 55.7625H304.867C305.456 55.7625 305.933 55.2303 305.933 54.5739V49.8191C305.933 49.1627 305.456 48.6305 304.867 48.6305ZM299.566 51.0758H298.499C297.91 51.0758 297.433 51.6003 297.433 52.2475V54.5909C297.433 55.238 297.91 55.7625 298.499 55.7625H299.566C300.155 55.7625 300.633 55.238 300.633 54.5909V52.2475C300.633 51.6003 300.155 51.0758 299.566 51.0758Z" fill="black"/> -<path d="M51.8438 93.2811H41.9297V89.1093H51.8438V93.2811ZM43.8906 91.7891H49.8906V90.5938H43.8906V91.7891ZM52.7109 81.7266H41.0391V80.2344H52.7109V81.7266ZM46.9062 82.1016C48.4583 82.1016 49.6406 82.2733 50.4531 82.6171C51.2708 82.9556 51.6797 83.4583 51.6797 84.125C51.6797 84.7917 51.2708 85.2969 50.4531 85.6406C49.6406 85.9844 48.4583 86.1561 46.9062 86.1561C45.3594 86.1561 44.1745 85.9844 43.3516 85.6406C42.5286 85.2969 42.1172 84.7917 42.1172 84.125C42.1172 83.4583 42.5286 82.9556 43.3516 82.6171C44.1745 82.2733 45.3594 82.1016 46.9062 82.1016ZM46.9062 83.4375C46.2708 83.4375 45.7656 83.4609 45.3906 83.5078C45.0156 83.5547 44.7318 83.6276 44.5391 83.7266C44.3464 83.8255 44.25 83.9583 44.25 84.125C44.25 84.2865 44.3464 84.4167 44.5391 84.5156C44.7318 84.6146 45.0208 84.6901 45.4062 84.7422C45.7917 84.7943 46.2917 84.8202 46.9062 84.8202C47.5312 84.8202 48.0339 84.7943 48.4141 84.7422C48.7995 84.6901 49.0859 84.6146 49.2734 84.5156C49.4609 84.4167 49.5547 84.2865 49.5547 84.125C49.5547 83.9583 49.4609 83.8255 49.2734 83.7266C49.0859 83.6276 48.8047 83.5547 48.4297 83.5078C48.0547 83.4609 47.5469 83.4375 46.9062 83.4375ZM47.8984 81.3046H45.8984V79.0938H47.8984V81.3046ZM53.3984 88.3906H40.4297V86.8358H53.3984V88.3906ZM47.8984 87.6797H45.8984V85.6483H47.8984V87.6797Z" fill="#56555A"/> -<path d="M73.2188 81.875H67.0781V80.25H73.2188V81.875ZM70.8594 87.1094H68.875V83.5312H70.8594V87.1094ZM74.3984 81.2344C74.3932 81.9688 74.3724 82.6458 74.3359 83.2656C74.2995 83.8854 74.2135 84.5651 74.0781 85.3047L72.1094 85.1328C72.25 84.388 72.3385 83.737 72.375 83.1797C72.4167 82.6224 72.4427 81.9818 72.4531 81.2578V81.1328V80.25H74.3984V81.1328V81.2344ZM77.875 89.8516H75.8281V79.2031H77.875V89.8516ZM79.6016 85.2188H77.0703V83.5547H79.6016V85.2188ZM78.3203 93.1953H68.3281V91.5859H78.3203V93.1953ZM70.3281 92.0938H68.3281V88.9062H70.3281V92.0938ZM66.2344 86.3438C67.9375 86.3438 69.513 86.3151 70.9609 86.2578C72.4141 86.2005 73.7839 86.0781 75.0703 85.8906L75.1641 87.3281C73.8464 87.5729 72.4635 87.7344 71.0156 87.8125C69.5677 87.8906 68.0312 87.9297 66.4062 87.9297L66.2344 86.3438ZM92.1719 93.4766H90.1797V79.2031H92.1719V93.4766ZM82.2891 88.5C83.6276 88.5104 84.8281 88.4818 85.8906 88.4141C86.9583 88.3411 88.0495 88.2135 89.1641 88.0312L89.3438 89.6406C88.2448 89.8333 87.1484 89.9661 86.0547 90.0391C84.9661 90.1068 83.7109 90.1406 82.2891 90.1406H81.0156V88.5H82.2891ZM87.7578 85.8828H83.0703V89.125H81.0156V84.3203H85.7266V82.0156H81V80.4062H87.7578V85.8828Z" fill="#B2B1B6"/> -<path d="M406 114H24V214H406V114Z" fill="white"/> -<path d="M60.9609 151.188H58.1133V137.805H60.9609V151.188ZM58.875 145.551H55.3828V143.113H58.875V145.551ZM56.4141 150.496H53.625V138.215H56.4141V150.496ZM52.9922 142.34H42.5273V140.008H52.9922V142.34ZM47.7891 143.066C48.6875 143.066 49.4883 143.219 50.1914 143.523C50.9023 143.828 51.457 144.266 51.8555 144.836C52.2539 145.398 52.4531 146.051 52.4531 146.793C52.4531 147.512 52.2539 148.152 51.8555 148.715C51.457 149.27 50.9023 149.703 50.1914 150.016C49.4883 150.32 48.6875 150.473 47.7891 150.473C46.9062 150.473 46.1133 150.32 45.4102 150.016C44.7148 149.703 44.168 149.27 43.7695 148.715C43.3711 148.152 43.1719 147.512 43.1719 146.793C43.1719 146.051 43.3711 145.398 43.7695 144.836C44.168 144.266 44.7148 143.828 45.4102 143.523C46.1133 143.219 46.9062 143.066 47.7891 143.066ZM47.7891 145.211C47.4062 145.203 47.0664 145.262 46.7695 145.387C46.4805 145.512 46.2539 145.695 46.0898 145.938C45.9258 146.18 45.8438 146.465 45.8438 146.793C45.8438 147.113 45.9219 147.391 46.0781 147.625C46.2422 147.859 46.4688 148.043 46.7578 148.176C47.0547 148.301 47.3984 148.363 47.7891 148.363C48.1797 148.363 48.5234 148.301 48.8203 148.176C49.1172 148.043 49.3477 147.859 49.5117 147.625C49.6758 147.391 49.7578 147.113 49.7578 146.793C49.7578 146.465 49.6758 146.18 49.5117 145.938C49.3477 145.695 49.1172 145.512 48.8203 145.387C48.5234 145.262 48.1797 145.203 47.7891 145.211ZM49.2656 141.625H46.2773V138.016H49.2656V141.625ZM53.6719 151.41C55.2031 151.41 56.5234 151.562 57.6328 151.867C58.7422 152.164 59.5898 152.605 60.1758 153.191C60.7695 153.777 61.0664 154.477 61.0664 155.289C61.0664 156.109 60.7695 156.805 60.1758 157.375C59.5898 157.953 58.7422 158.395 57.6328 158.699C56.5234 159.004 55.2031 159.156 53.6719 159.156C52.1484 159.156 50.832 159.004 49.7227 158.699C48.6211 158.395 47.7734 157.953 47.1797 157.375C46.5859 156.805 46.2891 156.109 46.2891 155.289C46.2891 154.477 46.5859 153.777 47.1797 153.191C47.7734 152.605 48.6211 152.164 49.7227 151.867C50.832 151.562 52.1484 151.41 53.6719 151.41ZM53.6719 153.648C52.6953 153.641 51.8828 153.695 51.2344 153.812C50.5938 153.93 50.1055 154.113 49.7695 154.363C49.4414 154.613 49.2812 154.922 49.2891 155.289C49.2812 155.641 49.4414 155.938 49.7695 156.18C50.1055 156.414 50.5977 156.594 51.2461 156.719C51.8945 156.844 52.7031 156.906 53.6719 156.906C54.6406 156.906 55.4492 156.844 56.0977 156.719C56.7539 156.594 57.2422 156.414 57.5625 156.18C57.8906 155.945 58.0586 155.648 58.0664 155.289C58.0586 154.914 57.8906 154.605 57.5625 154.363C57.2422 154.113 56.7578 153.93 56.1094 153.812C55.4609 153.695 54.6484 153.641 53.6719 153.648ZM82.875 150.262H63.3867V147.895H82.875V150.262ZM74.5898 148.832H71.6602V144.684H74.5898V148.832ZM80.6484 146.066H65.7422V143.723H80.6484V146.066ZM80.5312 141.098H68.707V145.258H65.7422V138.766H80.5312V141.098ZM73.0781 151.316C74.6172 151.316 75.9414 151.473 77.0508 151.785C78.1602 152.09 79.0117 152.539 79.6055 153.133C80.1992 153.719 80.5 154.43 80.5078 155.266C80.5 156.094 80.1992 156.797 79.6055 157.375C79.0195 157.961 78.168 158.406 77.0508 158.711C75.9414 159.023 74.6172 159.184 73.0781 159.191C71.5234 159.184 70.1875 159.023 69.0703 158.711C67.9531 158.406 67.0938 157.961 66.4922 157.375C65.8984 156.789 65.6016 156.086 65.6016 155.266C65.6016 154.43 65.8984 153.719 66.4922 153.133C67.0938 152.539 67.9531 152.09 69.0703 151.785C70.1875 151.473 71.5234 151.316 73.0781 151.316ZM73.0781 153.602C72.0859 153.602 71.2617 153.664 70.6055 153.789C69.957 153.906 69.4648 154.09 69.1289 154.34C68.8008 154.59 68.6406 154.898 68.6484 155.266C68.6406 155.641 68.8008 155.949 69.1289 156.191C69.4648 156.434 69.957 156.613 70.6055 156.73C71.2617 156.848 72.0859 156.906 73.0781 156.906C74.0547 156.906 74.8672 156.848 75.5156 156.73C76.1719 156.613 76.6641 156.434 76.9922 156.191C77.3281 155.949 77.4961 155.641 77.4961 155.266C77.4961 154.906 77.3281 154.602 76.9922 154.352C76.6641 154.094 76.1719 153.906 75.5156 153.789C74.8594 153.664 74.0469 153.602 73.0781 153.602ZM102.551 159.156H99.7383V137.805H102.551V159.156ZM100.418 148.457H96.7969V146.066H100.418V148.457ZM97.6758 158.125H94.9336V138.191H97.6758V158.125ZM86.2148 151.832C87.7773 151.832 89.1172 151.797 90.2344 151.727C91.3516 151.656 92.5 151.516 93.6797 151.305L93.8906 153.73C92.7031 153.965 91.5352 154.121 90.3867 154.199C89.2461 154.27 87.8555 154.312 86.2148 154.328H84.7148V151.832H86.2148ZM92.6836 142.703H87.7148V153.039H84.7148V140.301H92.6836V142.703ZM112.16 141.59C112.152 142.98 111.926 144.277 111.481 145.48C111.035 146.676 110.352 147.719 109.43 148.609C108.516 149.5 107.391 150.16 106.055 150.59L104.555 148.234C105.695 147.867 106.652 147.34 107.426 146.652C108.199 145.957 108.77 145.176 109.137 144.309C109.512 143.441 109.703 142.535 109.711 141.59V140.195H112.16V141.59ZM112.734 141.578C112.734 142.445 112.91 143.27 113.262 144.051C113.613 144.824 114.156 145.52 114.891 146.137C115.625 146.746 116.543 147.215 117.645 147.543L116.238 149.875C114.926 149.484 113.828 148.879 112.945 148.059C112.063 147.23 111.398 146.266 110.953 145.164C110.516 144.055 110.297 142.859 110.297 141.578V140.195H112.734V141.578ZM116.988 141.637H105.363V139.246H116.988V141.637ZM121.781 150.473H118.793V137.805H121.781V150.473ZM124.664 145.211H120.938V142.773H124.664V145.211ZM114.785 150.895C116.262 150.895 117.539 151.059 118.617 151.387C119.703 151.707 120.535 152.176 121.113 152.793C121.691 153.41 121.981 154.148 121.981 155.008C121.981 155.867 121.691 156.605 121.113 157.223C120.535 157.848 119.703 158.324 118.617 158.652C117.539 158.988 116.262 159.156 114.785 159.156C113.293 159.156 111.996 158.988 110.895 158.652C109.793 158.324 108.945 157.848 108.352 157.223C107.766 156.605 107.473 155.867 107.473 155.008C107.473 154.148 107.766 153.41 108.352 152.793C108.945 152.176 109.789 151.707 110.883 151.387C111.984 151.059 113.285 150.895 114.785 150.895ZM114.785 153.215C113.856 153.215 113.066 153.281 112.418 153.414C111.777 153.547 111.293 153.75 110.965 154.023C110.637 154.289 110.477 154.617 110.484 155.008C110.477 155.414 110.637 155.754 110.965 156.027C111.293 156.293 111.777 156.496 112.418 156.637C113.059 156.77 113.848 156.836 114.785 156.836C115.715 156.836 116.492 156.77 117.117 156.637C117.75 156.496 118.227 156.293 118.547 156.027C118.875 155.754 119.039 155.414 119.039 155.008C119.039 154.609 118.875 154.277 118.547 154.012C118.227 153.746 117.75 153.547 117.117 153.414C116.492 153.281 115.715 153.215 114.785 153.215ZM136.91 139.316C137.988 139.316 138.949 139.629 139.793 140.254C140.645 140.871 141.312 141.758 141.797 142.914C142.281 144.062 142.527 145.398 142.535 146.922C142.527 148.453 142.281 149.797 141.797 150.953C141.312 152.102 140.645 152.984 139.793 153.602C138.949 154.219 137.988 154.527 136.91 154.527C135.816 154.527 134.844 154.219 133.992 153.602C133.141 152.984 132.473 152.102 131.988 150.953C131.512 149.797 131.273 148.453 131.273 146.922C131.273 145.398 131.512 144.062 131.988 142.914C132.473 141.758 133.141 140.871 133.992 140.254C134.844 139.629 135.816 139.316 136.91 139.316ZM136.91 142.023C136.363 142.016 135.883 142.203 135.469 142.586C135.055 142.969 134.73 143.527 134.496 144.262C134.27 144.996 134.156 145.883 134.156 146.922C134.156 147.961 134.27 148.848 134.496 149.582C134.73 150.316 135.055 150.875 135.469 151.258C135.883 151.633 136.363 151.82 136.91 151.82C137.465 151.82 137.949 151.633 138.363 151.258C138.777 150.875 139.094 150.316 139.312 149.582C139.539 148.848 139.652 147.961 139.652 146.922C139.652 145.883 139.539 144.996 139.312 144.262C139.094 143.52 138.777 142.961 138.363 142.586C137.949 142.203 137.465 142.016 136.91 142.023ZM150.996 145.281H147.176V142.785H150.996V145.281ZM150.996 151.504H147.176V149.078H150.996V151.504ZM147.984 159.156H144.984V137.805H147.984V159.156ZM159.41 159.156H156.34V151.27H159.41V159.156ZM166.816 159.156H163.781V151.27H166.816V159.156ZM171.387 152.102H151.887V149.688H171.387V152.102ZM161.578 138.531C163.094 138.531 164.441 138.73 165.621 139.129C166.801 139.527 167.715 140.09 168.363 140.816C169.02 141.543 169.348 142.387 169.348 143.348C169.348 144.293 169.02 145.121 168.363 145.832C167.715 146.535 166.801 147.082 165.621 147.473C164.441 147.863 163.094 148.059 161.578 148.059C160.062 148.059 158.719 147.863 157.547 147.473C156.375 147.082 155.461 146.535 154.805 145.832C154.156 145.121 153.832 144.293 153.832 143.348C153.832 142.387 154.156 141.543 154.805 140.816C155.461 140.09 156.375 139.527 157.547 139.129C158.719 138.73 160.062 138.531 161.578 138.531ZM161.578 140.922C160.617 140.93 159.785 141.027 159.082 141.215C158.387 141.395 157.852 141.668 157.477 142.035C157.102 142.395 156.918 142.832 156.926 143.348C156.918 143.84 157.102 144.262 157.477 144.613C157.852 144.965 158.387 145.234 159.082 145.422C159.785 145.602 160.617 145.691 161.578 145.691C162.539 145.691 163.371 145.602 164.074 145.422C164.777 145.234 165.316 144.969 165.691 144.625C166.074 144.273 166.266 143.848 166.266 143.348C166.266 142.832 166.074 142.395 165.691 142.035C165.316 141.668 164.777 141.395 164.074 141.215C163.379 141.027 162.547 140.93 161.578 140.922ZM181.137 154.258H178.16V150.777H181.137V154.258ZM190.559 159.156H187.594V137.805H190.559V159.156ZM173.578 153.133C176.234 153.117 178.57 153.074 180.586 153.004C182.609 152.926 184.555 152.762 186.422 152.512L186.609 154.727C184.547 155.086 182.426 155.32 180.246 155.43C178.066 155.531 175.695 155.582 173.133 155.582L172.734 153.133H173.578ZM186.117 142.551H173.156V140.207H186.117V142.551ZM179.625 143.395C180.672 143.395 181.602 143.562 182.414 143.898C183.234 144.227 183.867 144.695 184.312 145.305C184.766 145.914 184.992 146.613 184.992 147.402C184.992 148.184 184.766 148.879 184.312 149.488C183.867 150.09 183.234 150.559 182.414 150.895C181.602 151.23 180.672 151.398 179.625 151.398C178.594 151.398 177.676 151.23 176.871 150.895C176.066 150.559 175.438 150.09 174.984 149.488C174.539 148.879 174.316 148.184 174.316 147.402C174.316 146.613 174.539 145.914 174.984 145.305C175.438 144.695 176.066 144.227 176.871 143.898C177.676 143.562 178.594 143.395 179.625 143.395ZM179.625 145.656C179.141 145.656 178.711 145.727 178.336 145.867C177.969 146 177.68 146.199 177.469 146.465C177.258 146.73 177.152 147.043 177.152 147.402C177.152 147.77 177.254 148.082 177.457 148.34C177.668 148.59 177.961 148.785 178.336 148.926C178.711 149.059 179.141 149.125 179.625 149.125C180.125 149.125 180.566 149.059 180.949 148.926C181.332 148.785 181.625 148.59 181.828 148.34C182.031 148.082 182.133 147.77 182.133 147.402C182.133 147.043 182.031 146.73 181.828 146.465C181.625 146.199 181.332 146 180.949 145.867C180.566 145.727 180.125 145.656 179.625 145.656ZM181.16 141.543H178.16V137.91H181.16V141.543Z" fill="#56555A"/> -<path d="M380 174H50C45.5817 174 42 177.582 42 182V190C42 194.418 45.5817 198 50 198H380C384.418 198 388 194.418 388 190V182C388 177.582 384.418 174 380 174Z" fill="white"/> -<path d="M50.6602 187.188H47.9883V186.426H50.6602V187.188ZM51.0585 191.184H50.1327V183.543H51.0585V191.184ZM51.3516 193.727H44.3672V192.953H51.3516V193.727ZM45.2929 193.328H44.3672V190.492H45.2929V193.328ZM45.8789 185.688C45.8789 186.309 45.7559 186.896 45.5098 187.451C45.2637 188.002 44.918 188.486 44.4727 188.904C44.0312 189.318 43.5234 189.633 42.9492 189.848L42.4688 189.098C42.9765 188.918 43.4316 188.654 43.834 188.307C44.2363 187.959 44.5508 187.559 44.7773 187.105C45.0039 186.648 45.1172 186.176 45.1172 185.688V184.832H45.8789V185.688ZM46.0429 185.688C46.0429 186.133 46.1522 186.566 46.371 186.988C46.5897 187.41 46.8926 187.785 47.2793 188.113C47.666 188.441 48.1094 188.691 48.6094 188.863L48.1289 189.602C47.5703 189.398 47.0762 189.1 46.6465 188.705C46.2207 188.311 45.8887 187.854 45.6504 187.334C45.4121 186.814 45.2929 186.266 45.2929 185.688V184.832H46.0429V185.688ZM48.375 185.148H42.7617V184.387H48.375V185.148ZM59.0858 188.43H57.082V187.645H59.0858V188.43ZM55.6875 186.742C55.6836 187.438 55.584 188.117 55.3887 188.781C55.1973 189.445 54.918 190.043 54.5508 190.574C54.1875 191.102 53.7578 191.516 53.2617 191.816L52.7108 191.113C53.1718 190.848 53.5723 190.482 53.9121 190.018C54.252 189.553 54.5117 189.035 54.6914 188.465C54.875 187.895 54.9688 187.32 54.9727 186.742V186.191H55.6875V186.742ZM55.8398 186.742C55.8438 187.305 55.9355 187.855 56.1152 188.395C56.2988 188.934 56.5625 189.424 56.9062 189.865C57.25 190.303 57.6523 190.645 58.1133 190.891L57.5858 191.582C57.0819 191.309 56.6444 190.92 56.2733 190.416C55.9061 189.912 55.6229 189.342 55.4237 188.705C55.2284 188.068 55.1328 187.414 55.1367 186.742V186.191H55.8398V186.742ZM57.7969 186.227H52.9922V185.465H57.7969V186.227ZM55.8516 186.039H54.9727V183.918H55.8516V186.039ZM61.6992 193.949H60.8203V183.531H61.6992V193.949ZM59.5898 193.41H58.7226V183.789H59.5898V193.41ZM69.7383 186.73C69.7383 187.449 69.6015 188.158 69.328 188.857C69.0546 189.557 68.6875 190.178 68.2266 190.721C67.7695 191.264 67.2695 191.672 66.7266 191.945L66.1758 191.219C66.6719 190.98 67.1328 190.621 67.5586 190.141C67.9883 189.656 68.332 189.113 68.5898 188.512C68.8477 187.91 68.9766 187.316 68.9766 186.73V185.008H69.7383V186.73ZM69.9023 186.73C69.9023 187.305 70.0312 187.877 70.2891 188.447C70.5469 189.014 70.8906 189.52 71.3203 189.965C71.75 190.41 72.2188 190.742 72.7266 190.961L72.2108 191.688C71.6444 191.43 71.1289 191.047 70.6641 190.539C70.2031 190.031 69.8359 189.447 69.5625 188.787C69.293 188.123 69.1602 187.438 69.1641 186.73V185.008H69.9023V186.73ZM72.3867 185.371H66.5155V184.609H72.3867V185.371ZM74.7655 193.949H73.8398V183.531H74.7655V193.949ZM81.7383 190.293H80.8358V188.711H81.7383V190.293ZM86.0391 188.887H76.5586V188.172H86.0391V188.887ZM81.7383 184.738H80.8358V183.473H81.7383V184.738ZM81.5976 184.984C81.5976 185.512 81.4061 185.969 81.0233 186.355C80.6405 186.738 80.1269 187.041 79.4823 187.264C78.8417 187.482 78.125 187.625 77.332 187.691L77.0625 186.988C77.75 186.945 78.377 186.838 78.9434 186.666C79.5098 186.49 79.959 186.26 80.291 185.975C80.623 185.686 80.7891 185.355 80.7891 184.984V184.832H81.5976V184.984ZM81.7969 184.984C81.793 185.355 81.957 185.686 82.2891 185.975C82.625 186.26 83.0742 186.49 83.6367 186.666C84.2031 186.838 84.8319 186.945 85.5233 186.988L85.2421 187.691C84.453 187.625 83.7382 187.482 83.0976 187.264C82.4569 187.041 81.9453 186.738 81.5625 186.355C81.1797 185.969 80.9883 185.512 80.9883 184.984V184.832H81.7969V184.984ZM85.078 185.172H77.5312V184.445H85.078V185.172ZM84.8203 192.109H78.6328V193.387H77.7188V191.453H83.9179V190.551H77.6953V189.859H84.8203V192.109ZM85.1367 193.832H77.7188V193.129H85.1367V193.832ZM97.9102 184.855H91.1367V184.094H97.9102V184.855ZM99.4688 188.688H89.9297V187.926H99.4688V188.688ZM98.2147 184.867C98.2147 185.473 98.1952 186.023 98.1561 186.52C98.1171 187.012 98.0234 187.578 97.875 188.219L96.9608 188.16C97.0663 187.73 97.1425 187.326 97.1894 186.947C97.2401 186.568 97.2715 186.236 97.2832 185.951C97.2949 185.662 97.3007 185.324 97.3007 184.938V184.867V184.094H98.2147V184.867ZM98.2617 193.809H91.1016V190.129H98.2617V193.809ZM92.0156 193.059H97.3477V190.855H92.0156V193.059ZM102.797 184.188C103.25 184.188 103.658 184.291 104.021 184.498C104.385 184.705 104.67 184.996 104.877 185.371C105.084 185.746 105.187 186.172 105.187 186.648C105.187 187.125 105.084 187.547 104.877 187.914C104.67 188.281 104.385 188.568 104.021 188.775C103.662 188.982 103.254 189.086 102.797 189.086C102.336 189.086 101.926 188.982 101.566 188.775C101.207 188.568 100.926 188.281 100.723 187.914C100.519 187.547 100.418 187.125 100.418 186.648C100.418 186.172 100.519 185.746 100.723 185.371C100.926 184.996 101.207 184.705 101.566 184.498C101.926 184.291 102.336 184.188 102.797 184.188ZM102.797 184.984C102.5 184.984 102.234 185.055 102 185.195C101.766 185.336 101.58 185.535 101.443 185.793C101.31 186.047 101.246 186.332 101.25 186.648C101.246 186.965 101.31 187.25 101.443 187.504C101.58 187.754 101.766 187.951 102 188.096C102.234 188.24 102.5 188.312 102.797 188.312C103.09 188.312 103.353 188.24 103.588 188.096C103.826 187.951 104.012 187.754 104.144 187.504C104.277 187.25 104.344 186.965 104.344 186.648C104.344 186.332 104.277 186.047 104.144 185.793C104.012 185.535 103.826 185.336 103.588 185.195C103.353 185.055 103.09 184.984 102.797 184.984ZM109.148 189.742H108.269V183.543H109.148V189.742ZM108.551 186.988H106.547V186.227H108.551V186.988ZM106.887 189.672H106.019V183.742H106.887V189.672ZM109.148 193.949H108.246V191.066H102.129V190.328H109.148V193.949Z" fill="#B2B1B6"/> -<path d="M309.047 190.969L312.906 186.906C313.411 186.365 313.797 185.927 314.062 185.594C314.333 185.26 314.539 184.943 314.68 184.641C314.82 184.333 314.891 184.01 314.891 183.672C314.891 183.292 314.792 182.958 314.594 182.672C314.396 182.38 314.125 182.154 313.781 181.992C313.443 181.831 313.062 181.75 312.641 181.75C312.198 181.75 311.81 181.839 311.477 182.016C311.148 182.193 310.893 182.443 310.711 182.766C310.529 183.083 310.438 183.453 310.438 183.875H309.109C309.104 183.219 309.255 182.638 309.562 182.133C309.875 181.628 310.305 181.234 310.852 180.953C311.398 180.672 312.01 180.531 312.688 180.531C313.359 180.531 313.961 180.669 314.492 180.945C315.029 181.221 315.448 181.599 315.75 182.078C316.052 182.557 316.203 183.089 316.203 183.672C316.198 184.104 316.117 184.518 315.961 184.914C315.81 185.305 315.549 185.74 315.18 186.219C314.81 186.698 314.286 187.286 313.609 187.984L311.016 190.656V190.75H316.406V192H309.062L309.047 190.969ZM322.219 180.531C322.938 180.542 323.607 180.714 324.227 181.047C324.846 181.38 325.352 181.945 325.742 182.742C326.133 183.534 326.328 184.583 326.328 185.891C326.328 187.214 326.156 188.344 325.812 189.281C325.469 190.219 324.974 190.932 324.328 191.422C323.682 191.911 322.917 192.156 322.031 192.156C321.375 192.156 320.786 192.029 320.266 191.773C319.745 191.518 319.32 191.167 318.992 190.719C318.664 190.266 318.453 189.74 318.359 189.141H319.75C319.833 189.49 319.977 189.797 320.18 190.062C320.383 190.323 320.641 190.529 320.953 190.68C321.266 190.831 321.625 190.906 322.031 190.906C322.646 190.906 323.177 190.734 323.625 190.391C324.073 190.047 324.414 189.552 324.648 188.906C324.888 188.255 325.01 187.474 325.016 186.562H324.859C324.641 186.875 324.383 187.143 324.086 187.367C323.789 187.591 323.461 187.763 323.102 187.883C322.742 188.003 322.365 188.062 321.969 188.062C321.297 188.062 320.677 187.901 320.109 187.578C319.547 187.255 319.099 186.81 318.766 186.242C318.432 185.674 318.266 185.036 318.266 184.328C318.266 183.625 318.43 182.984 318.758 182.406C319.086 181.823 319.549 181.365 320.148 181.031C320.747 180.693 321.438 180.526 322.219 180.531ZM322.219 181.766C321.734 181.766 321.294 181.88 320.898 182.109C320.508 182.339 320.198 182.648 319.969 183.039C319.745 183.43 319.635 183.854 319.641 184.312C319.641 184.776 319.75 185.201 319.969 185.586C320.188 185.966 320.487 186.268 320.867 186.492C321.253 186.716 321.688 186.828 322.172 186.828C322.651 186.828 323.091 186.708 323.492 186.469C323.893 186.229 324.211 185.914 324.445 185.523C324.68 185.133 324.797 184.719 324.797 184.281C324.797 183.849 324.685 183.44 324.461 183.055C324.237 182.664 323.927 182.352 323.531 182.117C323.141 181.883 322.703 181.766 322.219 181.766ZM327.984 188.531L333.078 180.688H333.922V182.469H333.328L329.5 188.359V188.453H336.391V189.688H327.984V188.531ZM333.469 189.344V188.797V180.688H334.812V192H333.469V189.344ZM338.297 195.203H337.141L338 190.953H339.516L338.297 195.203ZM345.281 192.156C344.5 192.156 343.805 192.021 343.195 191.75C342.586 191.479 342.112 191.104 341.773 190.625C341.435 190.146 341.266 189.604 341.266 189C341.266 188.521 341.367 188.073 341.57 187.656C341.773 187.24 342.049 186.898 342.398 186.633C342.747 186.362 343.135 186.193 343.562 186.125V186.062C343.193 185.979 342.867 185.815 342.586 185.57C342.31 185.326 342.094 185.026 341.938 184.672C341.781 184.318 341.703 183.938 341.703 183.531C341.703 182.964 341.857 182.453 342.164 182C342.471 181.542 342.896 181.182 343.438 180.922C343.984 180.661 344.599 180.531 345.281 180.531C345.958 180.531 346.57 180.661 347.117 180.922C347.664 181.182 348.091 181.542 348.398 182C348.711 182.453 348.87 182.964 348.875 183.531C348.87 183.938 348.786 184.318 348.625 184.672C348.469 185.026 348.25 185.326 347.969 185.57C347.688 185.815 347.365 185.979 347 186.062V186.125C347.422 186.193 347.807 186.362 348.156 186.633C348.51 186.898 348.789 187.24 348.992 187.656C349.201 188.073 349.307 188.521 349.312 189C349.307 189.604 349.133 190.146 348.789 190.625C348.451 191.104 347.974 191.479 347.359 191.75C346.75 192.021 346.057 192.156 345.281 192.156ZM345.281 190.922C345.812 190.922 346.276 190.836 346.672 190.664C347.068 190.492 347.372 190.258 347.586 189.961C347.799 189.664 347.906 189.318 347.906 188.922C347.906 188.51 347.794 188.141 347.57 187.812C347.346 187.479 347.034 187.219 346.633 187.031C346.232 186.844 345.781 186.75 345.281 186.75C344.781 186.75 344.333 186.844 343.938 187.031C343.542 187.219 343.229 187.479 343 187.812C342.776 188.141 342.667 188.51 342.672 188.922C342.667 189.318 342.768 189.664 342.977 189.961C343.19 190.258 343.492 190.492 343.883 190.664C344.279 190.836 344.745 190.922 345.281 190.922ZM345.281 185.562C345.708 185.562 346.091 185.479 346.43 185.312C346.768 185.146 347.031 184.919 347.219 184.633C347.406 184.346 347.5 184.016 347.5 183.641C347.5 183.266 347.409 182.935 347.227 182.648C347.044 182.362 346.784 182.141 346.445 181.984C346.107 181.828 345.719 181.75 345.281 181.75C344.839 181.75 344.451 181.828 344.117 181.984C343.789 182.141 343.531 182.362 343.344 182.648C343.156 182.935 343.062 183.266 343.062 183.641C343.062 184.016 343.159 184.346 343.352 184.633C343.544 184.919 343.807 185.146 344.141 185.312C344.474 185.479 344.854 185.562 345.281 185.562ZM354.906 192.156C354.073 192.156 353.362 191.93 352.773 191.477C352.185 191.023 351.734 190.362 351.422 189.492C351.109 188.622 350.953 187.573 350.953 186.344C350.953 185.13 351.109 184.089 351.422 183.219C351.734 182.344 352.185 181.677 352.773 181.219C353.367 180.76 354.078 180.531 354.906 180.531C355.729 180.531 356.438 180.76 357.031 181.219C357.625 181.677 358.078 182.344 358.391 183.219C358.703 184.089 358.859 185.13 358.859 186.344C358.859 187.573 358.706 188.622 358.398 189.492C358.091 190.362 357.641 191.023 357.047 191.477C356.453 191.93 355.74 192.156 354.906 192.156ZM354.906 190.906C355.448 190.906 355.914 190.729 356.305 190.375C356.695 190.021 356.99 189.503 357.188 188.82C357.385 188.138 357.484 187.312 357.484 186.344C357.484 185.375 357.383 184.547 357.18 183.859C356.977 183.172 356.682 182.648 356.297 182.289C355.911 181.93 355.448 181.75 354.906 181.75C354.365 181.75 353.901 181.93 353.516 182.289C353.13 182.648 352.833 183.172 352.625 183.859C352.417 184.547 352.312 185.375 352.312 186.344C352.312 187.312 352.417 188.138 352.625 188.82C352.833 189.503 353.128 190.021 353.508 190.375C353.893 190.729 354.359 190.906 354.906 190.906ZM364.438 192.156C363.604 192.156 362.893 191.93 362.305 191.477C361.716 191.023 361.266 190.362 360.953 189.492C360.641 188.622 360.484 187.573 360.484 186.344C360.484 185.13 360.641 184.089 360.953 183.219C361.266 182.344 361.716 181.677 362.305 181.219C362.898 180.76 363.609 180.531 364.438 180.531C365.26 180.531 365.969 180.76 366.562 181.219C367.156 181.677 367.609 182.344 367.922 183.219C368.234 184.089 368.391 185.13 368.391 186.344C368.391 187.573 368.237 188.622 367.93 189.492C367.622 190.362 367.172 191.023 366.578 191.477C365.984 191.93 365.271 192.156 364.438 192.156ZM364.438 190.906C364.979 190.906 365.445 190.729 365.836 190.375C366.227 190.021 366.521 189.503 366.719 188.82C366.917 188.138 367.016 187.312 367.016 186.344C367.016 185.375 366.914 184.547 366.711 183.859C366.508 183.172 366.214 182.648 365.828 182.289C365.443 181.93 364.979 181.75 364.438 181.75C363.896 181.75 363.432 181.93 363.047 182.289C362.661 182.648 362.365 183.172 362.156 183.859C361.948 184.547 361.844 185.375 361.844 186.344C361.844 187.312 361.948 188.138 362.156 188.82C362.365 189.503 362.659 190.021 363.039 190.375C363.424 190.729 363.891 190.906 364.438 190.906ZM379.016 189.453H377.781V186.359H379.016V189.453ZM385.234 189.938H384V179.391H385.234V189.938ZM385.578 192.969H375.703V191.938H385.578V192.969ZM376.938 192.234H375.703V188.906H376.938V192.234ZM373.703 185.828C375.562 185.818 377.208 185.789 378.641 185.742C380.073 185.69 381.443 185.583 382.75 185.422L382.828 186.312C381.479 186.526 380.065 186.667 378.586 186.734C377.107 186.802 375.536 186.833 373.875 186.828L373.703 185.828ZM384.328 188.5H381.125V187.609H384.328V188.5ZM378.266 179.953C378.938 179.953 379.534 180.052 380.055 180.25C380.581 180.448 380.987 180.732 381.273 181.102C381.56 181.471 381.703 181.896 381.703 182.375C381.703 182.865 381.56 183.289 381.273 183.648C380.987 184.008 380.583 184.286 380.062 184.484C379.542 184.682 378.943 184.781 378.266 184.781C377.583 184.781 376.982 184.682 376.461 184.484C375.945 184.286 375.544 184.008 375.258 183.648C374.971 183.289 374.828 182.865 374.828 182.375C374.828 181.896 374.971 181.471 375.258 181.102C375.544 180.732 375.948 180.448 376.469 180.25C376.99 180.052 377.589 179.953 378.266 179.953ZM378.266 180.891C377.818 180.885 377.422 180.945 377.078 181.07C376.734 181.19 376.466 181.365 376.273 181.594C376.086 181.823 375.995 182.083 376 182.375C375.995 182.672 376.086 182.935 376.273 183.164C376.466 183.388 376.734 183.562 377.078 183.688C377.422 183.812 377.818 183.875 378.266 183.875C378.703 183.875 379.094 183.812 379.438 183.688C379.781 183.562 380.049 183.388 380.242 183.164C380.435 182.935 380.531 182.672 380.531 182.375C380.531 182.083 380.435 181.823 380.242 181.594C380.049 181.365 379.781 181.19 379.438 181.07C379.094 180.945 378.703 180.885 378.266 180.891Z" fill="#56555A"/> -<path d="M406 214H24V254H406V214Z" fill="white"/> -<mask id="mask1_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="24" y="214" width="191" height="40"> -<path d="M24 214H215V254H24V214Z" fill="white"/> -</mask> -<g mask="url(#mask1_1837_11068)"> -<path d="M215 253H24V255H215V253Z" fill="#B2B1B6"/> -</g> -<path d="M85.5469 232.25H81.9844V231.234H85.5469V232.25ZM86.0781 237.578H84.8438V227.391H86.0781V237.578ZM86.4688 240.969H77.1562V239.938H86.4688V240.969ZM78.3906 240.438H77.1562V236.656H78.3906V240.438ZM79.1719 230.25C79.1719 231.078 79.0078 231.862 78.6797 232.602C78.3516 233.336 77.8906 233.982 77.2969 234.539C76.7083 235.091 76.0312 235.51 75.2656 235.797L74.625 234.797C75.3021 234.557 75.9089 234.206 76.4453 233.742C76.9818 233.279 77.401 232.745 77.7031 232.141C78.0052 231.531 78.1562 230.901 78.1562 230.25V229.109H79.1719V230.25ZM79.3906 230.25C79.3906 230.844 79.5365 231.422 79.8281 231.984C80.1198 232.547 80.5234 233.047 81.0391 233.484C81.5547 233.922 82.1458 234.255 82.8125 234.484L82.1719 235.469C81.4271 235.198 80.7682 234.799 80.1953 234.273C79.6276 233.747 79.1849 233.138 78.8672 232.445C78.5495 231.753 78.3906 231.021 78.3906 230.25V229.109H79.3906V230.25ZM82.5 229.531H75.0156V228.516H82.5V229.531ZM96.7812 233.906H94.1094V232.859H96.7812V233.906ZM92.25 231.656C92.2448 232.583 92.112 233.49 91.8516 234.375C91.5964 235.26 91.224 236.057 90.7344 236.766C90.25 237.469 89.6771 238.021 89.0156 238.422L88.2812 237.484C88.8958 237.13 89.4297 236.643 89.8828 236.023C90.3359 235.404 90.6823 234.714 90.9219 233.953C91.1667 233.193 91.2917 232.427 91.2969 231.656V230.922H92.25V231.656ZM92.4531 231.656C92.4583 232.406 92.5807 233.141 92.8203 233.859C93.0651 234.578 93.4167 235.232 93.875 235.82C94.3333 236.404 94.8698 236.859 95.4844 237.188L94.7812 238.109C94.1094 237.745 93.526 237.227 93.0312 236.555C92.5417 235.883 92.1641 235.122 91.8984 234.273C91.638 233.424 91.5104 232.552 91.5156 231.656V230.922H92.4531V231.656ZM95.0625 230.969H88.6562V229.953H95.0625V230.969ZM92.4688 230.719H91.2969V227.891H92.4688V230.719ZM100.266 241.266H99.0938V227.375H100.266V241.266ZM97.4531 240.547H96.2969V227.719H97.4531V240.547ZM110.984 231.641C110.984 232.599 110.802 233.544 110.438 234.477C110.073 235.409 109.583 236.237 108.969 236.961C108.359 237.685 107.693 238.229 106.969 238.594L106.234 237.625C106.896 237.307 107.51 236.828 108.078 236.188C108.651 235.542 109.109 234.818 109.453 234.016C109.797 233.214 109.969 232.422 109.969 231.641V229.344H110.984V231.641ZM111.203 231.641C111.203 232.406 111.375 233.169 111.719 233.93C112.063 234.685 112.521 235.359 113.094 235.953C113.667 236.547 114.292 236.99 114.969 237.281L114.281 238.25C113.526 237.906 112.839 237.396 112.219 236.719C111.604 236.042 111.115 235.263 110.75 234.383C110.391 233.497 110.214 232.583 110.219 231.641V229.344H111.203V231.641ZM114.516 229.828H106.688V228.812H114.516V229.828ZM117.688 241.266H116.453V227.375H117.688V241.266ZM126.984 236.391H125.781V234.281H126.984V236.391ZM132.719 234.516H120.078V233.562H132.719V234.516ZM126.984 228.984H125.781V227.297H126.984V228.984ZM126.797 229.312C126.797 230.016 126.542 230.625 126.031 231.141C125.521 231.651 124.836 232.055 123.977 232.352C123.122 232.643 122.167 232.833 121.109 232.922L120.75 231.984C121.667 231.927 122.503 231.784 123.258 231.555C124.013 231.32 124.612 231.013 125.055 230.633C125.497 230.247 125.719 229.807 125.719 229.312V229.109H126.797V229.312ZM127.062 229.312C127.057 229.807 127.276 230.247 127.719 230.633C128.167 231.013 128.766 231.32 129.516 231.555C130.271 231.784 131.109 231.927 132.031 231.984L131.656 232.922C130.604 232.833 129.651 232.643 128.797 232.352C127.943 232.055 127.26 231.651 126.75 231.141C126.24 230.625 125.984 230.016 125.984 229.312V229.109H127.062V229.312ZM131.438 229.562H121.375V228.594H131.438V229.562ZM131.094 238.812H122.844V240.516H121.625V237.938H129.891V236.734H121.594V235.812H131.094V238.812ZM131.516 241.109H121.625V240.172H131.516V241.109ZM149.766 241.266H148.562V227.375H149.766V241.266ZM148.922 234.078H146.203V233.031H148.922V234.078ZM146.562 240.547H145.406V227.688H146.562V240.547ZM139.828 237.078H138.609V229.078H139.828V237.078ZM139.469 236.578C140.297 236.583 141.107 236.555 141.898 236.492C142.695 236.424 143.521 236.302 144.375 236.125L144.531 237.219C143.615 237.385 142.747 237.503 141.93 237.57C141.117 237.638 140.297 237.672 139.469 237.672H138.609V236.578H139.469ZM162.391 230.438H158.141V229.422H162.391V230.438ZM162.391 233.562H158.141V232.547H162.391V233.562ZM163.25 241.266H162.016V237.312H153.906V236.328H163.25V241.266ZM163.25 235.562H162.016V227.375H163.25V235.562ZM155.562 228.172C156.24 228.172 156.852 228.312 157.398 228.594C157.945 228.875 158.372 229.268 158.68 229.773C158.992 230.279 159.151 230.849 159.156 231.484C159.151 232.135 158.992 232.714 158.68 233.219C158.372 233.719 157.945 234.112 157.398 234.398C156.852 234.68 156.24 234.818 155.562 234.812C154.875 234.818 154.258 234.68 153.711 234.398C153.164 234.112 152.734 233.716 152.422 233.211C152.109 232.706 151.953 232.13 151.953 231.484C151.953 230.849 152.109 230.279 152.422 229.773C152.734 229.268 153.164 228.875 153.711 228.594C154.258 228.312 154.875 228.172 155.562 228.172ZM155.562 229.219C155.094 229.219 154.674 229.315 154.305 229.508C153.935 229.701 153.646 229.971 153.438 230.32C153.229 230.664 153.125 231.052 153.125 231.484C153.125 231.927 153.229 232.323 153.438 232.672C153.646 233.016 153.935 233.286 154.305 233.484C154.674 233.682 155.094 233.781 155.562 233.781C156.016 233.781 156.424 233.682 156.789 233.484C157.159 233.286 157.448 233.016 157.656 232.672C157.865 232.323 157.969 231.927 157.969 231.484C157.969 231.057 157.865 230.669 157.656 230.32C157.448 229.971 157.159 229.701 156.789 229.508C156.419 229.315 156.01 229.219 155.562 229.219Z" fill="#B2B1B6"/> -<mask id="mask2_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="215" y="214" width="191" height="40"> -<path d="M215 214H406V254H215V214Z" fill="white"/> -</mask> -<g mask="url(#mask2_1837_11068)"> -<path d="M406 252H215V256H406V252Z" fill="#8425EC"/> -</g> -<path d="M270.586 230.125C270.586 230.964 270.438 231.74 270.141 232.453C269.844 233.167 269.393 233.786 268.789 234.312C268.185 234.833 267.443 235.216 266.562 235.461L265.617 233.914C266.362 233.716 266.987 233.422 267.492 233.031C268.003 232.635 268.38 232.19 268.625 231.695C268.87 231.201 268.992 230.677 268.992 230.125V229.609H270.586V230.125ZM270.969 230.125C270.969 230.63 271.089 231.115 271.328 231.578C271.573 232.036 271.943 232.451 272.438 232.82C272.938 233.19 273.56 233.474 274.305 233.672L273.391 235.211C272.505 234.977 271.76 234.609 271.156 234.109C270.552 233.604 270.099 233.013 269.797 232.336C269.5 231.654 269.352 230.917 269.352 230.125V229.609H270.969V230.125ZM273.836 230.211H266.125V228.641H273.836V230.211ZM270.992 229.328H268.992V227.156H270.992V229.328ZM277.016 235.547H275.023V227.203H277.016V235.547ZM278.938 232.188H276.453V230.555H278.938V232.188ZM277.016 241.281H267.719V236.141H277.016V241.281ZM269.695 239.68H275.047V237.711H269.695V239.68ZM289.922 231.742H285.961V230.141H289.922V231.742ZM289.922 236.148H285.961V234.547H289.922V236.148ZM283.484 228.211C284.193 228.211 284.826 228.419 285.383 228.836C285.945 229.247 286.383 229.839 286.695 230.609C287.008 231.375 287.164 232.266 287.164 233.281C287.164 234.302 287.008 235.198 286.695 235.969C286.383 236.734 285.945 237.323 285.383 237.734C284.826 238.146 284.193 238.352 283.484 238.352C282.766 238.352 282.128 238.146 281.57 237.734C281.013 237.323 280.576 236.734 280.258 235.969C279.94 235.198 279.781 234.302 279.781 233.281C279.781 232.266 279.94 231.375 280.258 230.609C280.576 229.839 281.013 229.247 281.57 228.836C282.128 228.419 282.766 228.211 283.484 228.211ZM283.484 230.016C283.125 230.01 282.812 230.135 282.547 230.391C282.281 230.646 282.073 231.018 281.922 231.508C281.771 231.997 281.698 232.589 281.703 233.281C281.698 233.974 281.771 234.565 281.922 235.055C282.073 235.544 282.281 235.917 282.547 236.172C282.812 236.422 283.125 236.547 283.484 236.547C283.844 236.547 284.159 236.422 284.43 236.172C284.701 235.917 284.909 235.544 285.055 235.055C285.201 234.565 285.273 233.974 285.273 233.281C285.273 232.589 285.201 231.997 285.055 231.508C284.909 231.013 284.701 230.641 284.43 230.391C284.159 230.135 283.844 230.01 283.484 230.016ZM291.562 241.477H289.586V227.203H291.562V241.477ZM298.219 231.086C298.219 232.18 298.062 233.237 297.75 234.258C297.443 235.273 296.987 236.18 296.383 236.977C295.784 237.773 295.065 238.37 294.227 238.766L293.055 237.195C293.82 236.836 294.471 236.328 295.008 235.672C295.549 235.016 295.956 234.292 296.227 233.5C296.497 232.708 296.635 231.904 296.641 231.086V229.43H298.219V231.086ZM298.641 231.086C298.635 231.841 298.766 232.591 299.031 233.336C299.297 234.081 299.69 234.766 300.211 235.391C300.737 236.01 301.375 236.492 302.125 236.836L301.016 238.398C300.177 238.018 299.461 237.448 298.867 236.688C298.279 235.927 297.831 235.062 297.523 234.094C297.216 233.12 297.062 232.117 297.062 231.086V229.43H298.641V231.086ZM301.508 230.219H293.625V228.594H301.508V230.219ZM304.609 241.438H302.609V227.203H304.609V241.438ZM306.719 234.312H304.172V232.648H306.719V234.312ZM321.383 230.516H317.828V229.031H321.383V230.516ZM321.383 233.109H317.828V231.602H321.383V233.109ZM322.898 234.531H320.922V227.203H322.898V234.531ZM322.898 238.859H315.461V240.703H313.453V237.398H320.922V236.594H313.438V235.062H322.898V238.859ZM323.32 241.281H313.453V239.711H323.32V241.281ZM313.531 229.492H316.328V227.82H318.305V234.133H311.523V227.82H313.531V229.492ZM316.328 232.562V230.992H313.531V232.562H316.328ZM338.969 232.297H336.234V230.68H338.969V232.297ZM340.438 235.664H338.453V227.203H340.438V235.664ZM335.578 235.977C336.589 235.977 337.461 236.086 338.195 236.305C338.93 236.523 339.492 236.839 339.883 237.25C340.279 237.656 340.479 238.146 340.484 238.719C340.479 239.286 340.279 239.773 339.883 240.18C339.492 240.591 338.93 240.906 338.195 241.125C337.461 241.344 336.589 241.456 335.578 241.461C334.573 241.456 333.703 241.344 332.969 241.125C332.24 240.906 331.677 240.591 331.281 240.18C330.891 239.773 330.695 239.286 330.695 238.719C330.695 238.146 330.891 237.656 331.281 237.25C331.677 236.839 332.24 236.523 332.969 236.305C333.703 236.086 334.573 235.977 335.578 235.977ZM335.578 237.492C334.943 237.492 334.411 237.539 333.984 237.633C333.557 237.721 333.232 237.857 333.008 238.039C332.784 238.221 332.672 238.448 332.672 238.719C332.672 238.984 332.784 239.208 333.008 239.391C333.232 239.573 333.557 239.711 333.984 239.805C334.417 239.893 334.948 239.938 335.578 239.938C336.214 239.938 336.747 239.893 337.18 239.805C337.617 239.711 337.945 239.573 338.164 239.391C338.383 239.208 338.492 238.984 338.492 238.719C338.492 238.448 338.383 238.221 338.164 238.039C337.945 237.857 337.617 237.721 337.18 237.633C336.747 237.539 336.214 237.492 335.578 237.492ZM333.414 229.578C333.414 230.5 333.266 231.365 332.969 232.172C332.677 232.979 332.229 233.69 331.625 234.305C331.026 234.914 330.286 235.37 329.406 235.672L328.367 234.086C329.122 233.831 329.755 233.466 330.266 232.992C330.781 232.518 331.161 231.99 331.406 231.406C331.656 230.818 331.784 230.208 331.789 229.578V228.641H333.414V229.578ZM333.82 229.562C333.82 230.146 333.938 230.708 334.172 231.25C334.411 231.786 334.776 232.273 335.266 232.711C335.755 233.148 336.365 233.49 337.094 233.734L336.109 235.297C335.25 235.016 334.526 234.589 333.938 234.016C333.354 233.438 332.917 232.768 332.625 232.008C332.339 231.242 332.198 230.427 332.203 229.562V228.641H333.82V229.562ZM336.656 229.68H328.938V228.07H336.656V229.68ZM347.18 229.641C347.18 230.604 347.029 231.495 346.727 232.312C346.43 233.13 345.979 233.844 345.375 234.453C344.776 235.062 344.036 235.516 343.156 235.812L342.047 234.242C342.828 233.997 343.477 233.638 343.992 233.164C344.513 232.69 344.896 232.154 345.141 231.555C345.391 230.951 345.516 230.312 345.516 229.641V228.094H347.18V229.641ZM347.523 229.656C347.523 230.286 347.643 230.883 347.883 231.445C348.128 232.008 348.497 232.513 348.992 232.961C349.492 233.404 350.115 233.745 350.859 233.984L349.812 235.547C348.953 235.26 348.234 234.826 347.656 234.242C347.078 233.659 346.643 232.979 346.352 232.203C346.065 231.422 345.922 230.573 345.922 229.656V228.094H347.523V229.656ZM353.562 237.641H351.57V227.227H353.562V237.641ZM355.484 233.016H352.984V231.344H355.484V233.016ZM354.094 241.195H344.336V239.586H354.094V241.195ZM346.367 240.438H344.336V236.609H346.367V240.438Z" fill="#56555A"/> -<path d="M382 270H48C39.1634 270 32 277.163 32 286V302C32 310.837 39.1634 318 48 318H382C390.837 318 398 310.837 398 302V286C398 277.163 390.837 270 382 270Z" fill="white"/> -<path d="M60.0156 301.297H58.7812V287.375H60.0156V301.297ZM52.625 288.453C53.3125 288.453 53.9245 288.651 54.4609 289.047C54.9974 289.443 55.4167 290.008 55.7188 290.742C56.0208 291.477 56.1719 292.328 56.1719 293.297C56.1719 294.266 56.0208 295.115 55.7188 295.844C55.4167 296.573 54.9974 297.135 54.4609 297.531C53.9245 297.927 53.3125 298.125 52.625 298.125C51.9375 298.125 51.3255 297.927 50.7891 297.531C50.2526 297.135 49.8333 296.573 49.5312 295.844C49.2292 295.115 49.0781 294.266 49.0781 293.297C49.0781 292.328 49.2292 291.477 49.5312 290.742C49.8333 290.008 50.2526 289.443 50.7891 289.047C51.3255 288.651 51.9375 288.453 52.625 288.453ZM52.625 289.547C52.1667 289.547 51.7578 289.703 51.3984 290.016C51.0391 290.328 50.7604 290.768 50.5625 291.336C50.3646 291.904 50.2656 292.557 50.2656 293.297C50.2656 294.042 50.3646 294.698 50.5625 295.266C50.7604 295.828 51.0391 296.263 51.3984 296.57C51.7578 296.878 52.1667 297.031 52.625 297.031C53.0885 297.031 53.4974 296.878 53.8516 296.57C54.2109 296.263 54.4896 295.828 54.6875 295.266C54.8854 294.698 54.9844 294.042 54.9844 293.297C54.9844 292.552 54.8854 291.898 54.6875 291.336C54.4896 290.768 54.2109 290.328 53.8516 290.016C53.4974 289.703 53.0885 289.547 52.625 289.547ZM75.0938 295.562H62.375V294.547H75.0938V295.562ZM73.4531 291H65.25V292.844H64.0312V290.078H72.2188V288.703H63.9844V287.719H73.4531V291ZM73.75 293.344H64.0312V292.391H73.75V293.344ZM73.4531 301.078H64.1094V296.828H73.4531V301.078ZM65.3125 300.078H72.25V297.828H65.3125V300.078ZM87.4062 288.281C87.4062 289.427 87.1458 290.466 86.625 291.398C86.1042 292.331 85.3568 293.135 84.3828 293.812C83.4089 294.49 82.25 295.021 80.9062 295.406L80.3906 294.438C81.5729 294.104 82.5938 293.661 83.4531 293.109C84.3177 292.557 84.9792 291.917 85.4375 291.188C85.8958 290.458 86.125 289.667 86.125 288.812V288.281H87.4062ZM86.9375 289.297H81.1094V288.281H86.9375V289.297ZM91.75 295.312H90.5156V287.391H91.75V295.312ZM90.75 292H87.4375V290.969H90.75V292ZM91.75 301.078H82.7344V295.906H91.75V301.078ZM83.9219 300.078H90.5312V296.891H83.9219V300.078ZM98.0156 290.094C98.0104 290.792 97.875 291.482 97.6094 292.164C97.349 292.846 96.9714 293.461 96.4766 294.008C95.987 294.555 95.4115 294.974 94.75 295.266L94.0781 294.312C94.6719 294.052 95.1927 293.69 95.6406 293.227C96.0885 292.763 96.4297 292.258 96.6641 291.711C96.9036 291.164 97.026 290.625 97.0312 290.094V288.234H98.0156V290.094ZM98.2031 290.094C98.2083 290.625 98.3229 291.143 98.5469 291.648C98.776 292.154 99.1042 292.612 99.5312 293.023C99.9635 293.43 100.469 293.745 101.047 293.969L100.391 294.922C99.7344 294.656 99.1693 294.276 98.6953 293.781C98.2214 293.281 97.8568 292.716 97.6016 292.086C97.3516 291.451 97.2292 290.786 97.2344 290.094V288.234H98.2031V290.094ZM105.859 295.781H104.688V287.391H105.859V295.781ZM105.063 292.047H102.391V291.016H105.063V292.047ZM102.844 295.703H101.688V287.641H102.844V295.703ZM105.859 301.266H104.656V297.562H96.5V296.547H105.859V301.266Z" fill="#B2B1B6"/> -<path d="M373.977 296.472H373.187L372.907 296.202C373.532 295.476 373.989 294.621 374.245 293.698C374.5 292.775 374.549 291.806 374.387 290.862C373.917 288.082 371.597 285.862 368.797 285.522C367.813 285.398 366.813 285.5 365.874 285.821C364.935 286.143 364.082 286.674 363.381 287.376C362.679 288.078 362.147 288.93 361.826 289.869C361.505 290.808 361.402 291.808 361.527 292.792C361.867 295.592 364.087 297.912 366.867 298.382C367.811 298.544 368.779 298.496 369.703 298.24C370.626 297.984 371.481 297.527 372.207 296.902L372.477 297.182V297.972L376.727 302.222C377.137 302.632 377.807 302.632 378.217 302.222C378.627 301.812 378.627 301.142 378.217 300.732L373.977 296.472ZM367.977 296.472C365.487 296.472 363.477 294.462 363.477 291.972C363.477 289.482 365.487 287.472 367.977 287.472C370.467 287.472 372.477 289.482 372.477 291.972C372.477 294.462 370.467 296.472 367.977 296.472Z" fill="#B2B1B6"/> -<path d="M382 326H48C39.1634 326 32 333.163 32 342V702C32 710.837 39.1634 718 48 718H382C390.837 718 398 710.837 398 702V342C398 333.163 390.837 326 382 326Z" fill="white"/> -<path d="M390 334H40C35.5817 334 32 337.582 32 342V366C32 370.418 35.5817 374 40 374H390C394.418 374 398 370.418 398 366V342C398 337.582 394.418 334 390 334Z" fill="white"/> -<path d="M60.4062 357.633H58.4219V347.234H60.4062V357.633ZM58.7031 352.977H55.875V351.352H58.7031V352.977ZM56.0078 348.273C56.0026 349.539 55.7422 350.693 55.2266 351.734C54.7109 352.771 53.9609 353.669 52.9766 354.43C51.9922 355.185 50.8073 355.779 49.4219 356.211L48.6016 354.617C49.6953 354.273 50.638 353.831 51.4297 353.289C52.2266 352.742 52.8333 352.12 53.25 351.422C53.6719 350.724 53.8854 349.974 53.8906 349.172V348.273H56.0078ZM55.1641 349.906H49.3438V348.273H55.1641V349.906ZM60.7734 361.195H51.0234V359.586H60.7734V361.195ZM53.0469 360.508H51.0234V356.57H53.0469V360.508ZM67.0547 349.258C67.0547 350.227 66.9089 351.125 66.6172 351.953C66.3307 352.781 65.8932 353.503 65.3047 354.117C64.7161 354.727 63.987 355.18 63.1172 355.477L62.0469 353.914C62.8073 353.654 63.4401 353.286 63.9453 352.812C64.4505 352.333 64.8229 351.792 65.0625 351.188C65.3021 350.583 65.4245 349.94 65.4297 349.258V347.969H67.0547V349.258ZM67.4297 349.453C67.4297 350.052 67.5469 350.617 67.7812 351.148C68.0208 351.68 68.3828 352.154 68.8672 352.57C69.3568 352.982 69.9635 353.302 70.6875 353.531L69.625 355.078C68.7917 354.802 68.0911 354.388 67.5234 353.836C66.9557 353.279 66.5286 352.628 66.2422 351.883C65.9557 351.138 65.8151 350.328 65.8203 349.453V347.969H67.4297V349.453ZM73.5312 355.648H71.5391V347.203H73.5312V355.648ZM75.4531 352.203H72.9688V350.539H75.4531V352.203ZM68.8672 355.938C69.8464 355.938 70.6953 356.047 71.4141 356.266C72.138 356.479 72.6927 356.794 73.0781 357.211C73.4688 357.622 73.6641 358.112 73.6641 358.68C73.6641 359.258 73.4688 359.753 73.0781 360.164C72.6927 360.576 72.138 360.891 71.4141 361.109C70.6953 361.328 69.8464 361.438 68.8672 361.438C67.8724 361.438 67.0078 361.328 66.2734 361.109C65.5443 360.891 64.9818 360.576 64.5859 360.164C64.1901 359.753 63.9922 359.258 63.9922 358.68C63.9922 358.112 64.1901 357.622 64.5859 357.211C64.9818 356.794 65.5443 356.479 66.2734 356.266C67.0078 356.047 67.8724 355.938 68.8672 355.938ZM68.8672 357.5C68.2474 357.495 67.724 357.539 67.2969 357.633C66.8698 357.721 66.5443 357.854 66.3203 358.031C66.1016 358.208 65.9948 358.424 66 358.68C65.9948 358.945 66.1016 359.167 66.3203 359.344C66.5391 359.521 66.8594 359.654 67.2812 359.742C67.7083 359.831 68.237 359.875 68.8672 359.875C69.487 359.875 70.0078 359.831 70.4297 359.742C70.8516 359.654 71.1693 359.521 71.3828 359.344C71.5964 359.167 71.7031 358.945 71.7031 358.68C71.7031 358.424 71.5938 358.208 71.375 358.031C71.1615 357.849 70.8438 357.714 70.4219 357.625C70 357.536 69.4818 357.495 68.8672 357.5Z" fill="#56555A"/> -<path d="M288.781 356.531L293.875 348.688H294.719V350.469H294.125L290.297 356.359V356.453H297.188V357.688H288.781V356.531ZM294.266 357.344V356.797V348.688H295.609V360H294.266V357.344ZM302.812 348.531C303.531 348.542 304.201 348.714 304.82 349.047C305.44 349.38 305.945 349.945 306.336 350.742C306.727 351.534 306.922 352.583 306.922 353.891C306.922 355.214 306.75 356.344 306.406 357.281C306.062 358.219 305.568 358.932 304.922 359.422C304.276 359.911 303.51 360.156 302.625 360.156C301.969 360.156 301.38 360.029 300.859 359.773C300.339 359.518 299.914 359.167 299.586 358.719C299.258 358.266 299.047 357.74 298.953 357.141H300.344C300.427 357.49 300.57 357.797 300.773 358.062C300.977 358.323 301.234 358.529 301.547 358.68C301.859 358.831 302.219 358.906 302.625 358.906C303.24 358.906 303.771 358.734 304.219 358.391C304.667 358.047 305.008 357.552 305.242 356.906C305.482 356.255 305.604 355.474 305.609 354.562H305.453C305.234 354.875 304.977 355.143 304.68 355.367C304.383 355.591 304.055 355.763 303.695 355.883C303.336 356.003 302.958 356.062 302.562 356.062C301.891 356.062 301.271 355.901 300.703 355.578C300.141 355.255 299.693 354.81 299.359 354.242C299.026 353.674 298.859 353.036 298.859 352.328C298.859 351.625 299.023 350.984 299.352 350.406C299.68 349.823 300.143 349.365 300.742 349.031C301.341 348.693 302.031 348.526 302.812 348.531ZM302.812 349.766C302.328 349.766 301.888 349.88 301.492 350.109C301.102 350.339 300.792 350.648 300.562 351.039C300.339 351.43 300.229 351.854 300.234 352.312C300.234 352.776 300.344 353.201 300.562 353.586C300.781 353.966 301.081 354.268 301.461 354.492C301.846 354.716 302.281 354.828 302.766 354.828C303.245 354.828 303.685 354.708 304.086 354.469C304.487 354.229 304.805 353.914 305.039 353.523C305.273 353.133 305.391 352.719 305.391 352.281C305.391 351.849 305.279 351.44 305.055 351.055C304.831 350.664 304.521 350.352 304.125 350.117C303.734 349.883 303.297 349.766 302.812 349.766ZM309.016 363.203H307.859L308.719 358.953H310.234L309.016 363.203ZM316 360.156C315.219 360.156 314.523 360.021 313.914 359.75C313.305 359.479 312.831 359.104 312.492 358.625C312.154 358.146 311.984 357.604 311.984 357C311.984 356.521 312.086 356.073 312.289 355.656C312.492 355.24 312.768 354.898 313.117 354.633C313.466 354.362 313.854 354.193 314.281 354.125V354.062C313.911 353.979 313.586 353.815 313.305 353.57C313.029 353.326 312.812 353.026 312.656 352.672C312.5 352.318 312.422 351.938 312.422 351.531C312.422 350.964 312.576 350.453 312.883 350C313.19 349.542 313.615 349.182 314.156 348.922C314.703 348.661 315.318 348.531 316 348.531C316.677 348.531 317.289 348.661 317.836 348.922C318.383 349.182 318.81 349.542 319.117 350C319.43 350.453 319.589 350.964 319.594 351.531C319.589 351.938 319.505 352.318 319.344 352.672C319.188 353.026 318.969 353.326 318.688 353.57C318.406 353.815 318.083 353.979 317.719 354.062V354.125C318.141 354.193 318.526 354.362 318.875 354.633C319.229 354.898 319.508 355.24 319.711 355.656C319.919 356.073 320.026 356.521 320.031 357C320.026 357.604 319.852 358.146 319.508 358.625C319.169 359.104 318.693 359.479 318.078 359.75C317.469 360.021 316.776 360.156 316 360.156ZM316 358.922C316.531 358.922 316.995 358.836 317.391 358.664C317.786 358.492 318.091 358.258 318.305 357.961C318.518 357.664 318.625 357.318 318.625 356.922C318.625 356.51 318.513 356.141 318.289 355.812C318.065 355.479 317.753 355.219 317.352 355.031C316.951 354.844 316.5 354.75 316 354.75C315.5 354.75 315.052 354.844 314.656 355.031C314.26 355.219 313.948 355.479 313.719 355.812C313.495 356.141 313.385 356.51 313.391 356.922C313.385 357.318 313.487 357.664 313.695 357.961C313.909 358.258 314.211 358.492 314.602 358.664C314.997 358.836 315.464 358.922 316 358.922ZM316 353.562C316.427 353.562 316.81 353.479 317.148 353.312C317.487 353.146 317.75 352.919 317.938 352.633C318.125 352.346 318.219 352.016 318.219 351.641C318.219 351.266 318.128 350.935 317.945 350.648C317.763 350.362 317.503 350.141 317.164 349.984C316.826 349.828 316.438 349.75 316 349.75C315.557 349.75 315.169 349.828 314.836 349.984C314.508 350.141 314.25 350.362 314.062 350.648C313.875 350.935 313.781 351.266 313.781 351.641C313.781 352.016 313.878 352.346 314.07 352.633C314.263 352.919 314.526 353.146 314.859 353.312C315.193 353.479 315.573 353.562 316 353.562ZM325.609 360.156C324.938 360.156 324.326 360.026 323.773 359.766C323.227 359.505 322.789 359.148 322.461 358.695C322.138 358.242 321.964 357.729 321.938 357.156H323.297C323.328 357.49 323.451 357.789 323.664 358.055C323.878 358.32 324.154 358.531 324.492 358.688C324.836 358.844 325.208 358.922 325.609 358.922C326.094 358.922 326.526 358.812 326.906 358.594C327.292 358.375 327.594 358.076 327.812 357.695C328.031 357.315 328.141 356.891 328.141 356.422C328.141 355.938 328.029 355.503 327.805 355.117C327.581 354.727 327.268 354.419 326.867 354.195C326.466 353.971 326.016 353.859 325.516 353.859C325.021 353.849 324.596 353.927 324.242 354.094C323.888 354.255 323.609 354.516 323.406 354.875H322.047L322.844 348.688H328.969V349.938H324.016L323.594 353.25H323.703C323.964 353.052 324.273 352.893 324.633 352.773C324.997 352.654 325.375 352.594 325.766 352.594C326.474 352.594 327.115 352.755 327.688 353.078C328.26 353.401 328.708 353.854 329.031 354.438C329.354 355.016 329.516 355.667 329.516 356.391C329.516 357.109 329.346 357.755 329.008 358.328C328.669 358.901 328.203 359.349 327.609 359.672C327.021 359.995 326.354 360.156 325.609 360.156ZM335.172 360.156C334.339 360.156 333.628 359.93 333.039 359.477C332.451 359.023 332 358.362 331.688 357.492C331.375 356.622 331.219 355.573 331.219 354.344C331.219 353.13 331.375 352.089 331.688 351.219C332 350.344 332.451 349.677 333.039 349.219C333.633 348.76 334.344 348.531 335.172 348.531C335.995 348.531 336.703 348.76 337.297 349.219C337.891 349.677 338.344 350.344 338.656 351.219C338.969 352.089 339.125 353.13 339.125 354.344C339.125 355.573 338.971 356.622 338.664 357.492C338.357 358.362 337.906 359.023 337.312 359.477C336.719 359.93 336.005 360.156 335.172 360.156ZM335.172 358.906C335.714 358.906 336.18 358.729 336.57 358.375C336.961 358.021 337.255 357.503 337.453 356.82C337.651 356.138 337.75 355.312 337.75 354.344C337.75 353.375 337.648 352.547 337.445 351.859C337.242 351.172 336.948 350.648 336.562 350.289C336.177 349.93 335.714 349.75 335.172 349.75C334.63 349.75 334.167 349.93 333.781 350.289C333.396 350.648 333.099 351.172 332.891 351.859C332.682 352.547 332.578 353.375 332.578 354.344C332.578 355.312 332.682 356.138 332.891 356.82C333.099 357.503 333.393 358.021 333.773 358.375C334.159 358.729 334.625 358.906 335.172 358.906ZM349.75 357.453H348.516V354.359H349.75V357.453ZM355.969 357.938H354.734V347.391H355.969V357.938ZM356.312 360.969H346.438V359.938H356.312V360.969ZM347.672 360.234H346.438V356.906H347.672V360.234ZM344.438 353.828C346.297 353.818 347.943 353.789 349.375 353.742C350.807 353.69 352.177 353.583 353.484 353.422L353.562 354.312C352.214 354.526 350.799 354.667 349.32 354.734C347.841 354.802 346.271 354.833 344.609 354.828L344.438 353.828ZM355.062 356.5H351.859V355.609H355.062V356.5ZM349 347.953C349.672 347.953 350.268 348.052 350.789 348.25C351.315 348.448 351.721 348.732 352.008 349.102C352.294 349.471 352.438 349.896 352.438 350.375C352.438 350.865 352.294 351.289 352.008 351.648C351.721 352.008 351.318 352.286 350.797 352.484C350.276 352.682 349.677 352.781 349 352.781C348.318 352.781 347.716 352.682 347.195 352.484C346.68 352.286 346.279 352.008 345.992 351.648C345.706 351.289 345.562 350.865 345.562 350.375C345.562 349.896 345.706 349.471 345.992 349.102C346.279 348.732 346.682 348.448 347.203 348.25C347.724 348.052 348.323 347.953 349 347.953ZM349 348.891C348.552 348.885 348.156 348.945 347.812 349.07C347.469 349.19 347.201 349.365 347.008 349.594C346.82 349.823 346.729 350.083 346.734 350.375C346.729 350.672 346.82 350.935 347.008 351.164C347.201 351.388 347.469 351.562 347.812 351.688C348.156 351.812 348.552 351.875 349 351.875C349.438 351.875 349.828 351.812 350.172 351.688C350.516 351.562 350.784 351.388 350.977 351.164C351.169 350.935 351.266 350.672 351.266 350.375C351.266 350.083 351.169 349.823 350.977 349.594C350.784 349.365 350.516 349.19 350.172 349.07C349.828 348.945 349.438 348.885 349 348.891Z" fill="#56555A"/> -<path d="M376 350L380 354L376 358" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -<path d="M390 382H40C35.5817 382 32 385.582 32 390V414C32 418.418 35.5817 422 40 422H390C394.418 422 398 418.418 398 414V390C398 385.582 394.418 382 390 382Z" fill="white"/> -<path d="M55.4922 397.227C55.4922 398.07 55.2656 398.841 54.8125 399.539C54.3646 400.232 53.7109 400.815 52.8516 401.289C51.9922 401.758 50.974 402.073 49.7969 402.234L49.0547 400.68C50.0495 400.56 50.901 400.323 51.6094 399.969C52.3229 399.609 52.8594 399.193 53.2188 398.719C53.5781 398.24 53.7578 397.742 53.7578 397.227V396.797H55.4922V397.227ZM56.0625 397.227C56.0625 397.742 56.2396 398.24 56.5938 398.719C56.9531 399.193 57.487 399.609 58.1953 399.969C58.9089 400.323 59.7708 400.56 60.7812 400.68L60.0625 402.234C58.875 402.073 57.849 401.758 56.9844 401.289C56.1198 400.815 55.4609 400.232 55.0078 399.539C54.5547 398.841 54.3281 398.07 54.3281 397.227V396.797H56.0625V397.227ZM55.8594 409.445H53.8828V404.203H55.8594V409.445ZM61.3984 404.656H48.4297V403.07H61.3984V404.656ZM60.2266 397.523H49.5938V395.969H60.2266V397.523ZM73.625 406.32H71.6172V395.203H73.625V406.32ZM75.4453 401.531H72.9141V399.891H75.4453V401.531ZM74.1094 409.195H64.0859V407.586H74.1094V409.195ZM66.1016 408.062H64.0859V405.586H66.1016V408.062ZM67.5312 404.125H65.5469V402.039H67.5312V404.125ZM62.1016 403.391C63.7474 403.391 65.3099 403.359 66.7891 403.297C68.2682 403.229 69.6589 403.102 70.9609 402.914L71.1094 404.281C69.8594 404.521 68.5703 404.682 67.2422 404.766C65.9141 404.849 64.401 404.904 62.7031 404.93C62.625 404.93 62.5573 404.93 62.5 404.93C62.4427 404.93 62.375 404.93 62.2969 404.93L62.1016 403.391ZM70.6016 397.805H62.4609V396.367H70.6016V397.805ZM66.5312 398.195C67.224 398.195 67.8333 398.284 68.3594 398.461C68.8854 398.633 69.2917 398.888 69.5781 399.227C69.8646 399.56 70.0104 399.958 70.0156 400.422C70.0104 400.859 69.8646 401.242 69.5781 401.57C69.2917 401.893 68.8854 402.146 68.3594 402.328C67.8333 402.505 67.224 402.594 66.5312 402.594C65.8333 402.594 65.2214 402.505 64.6953 402.328C64.1693 402.151 63.7604 401.901 63.4688 401.578C63.1823 401.25 63.0391 400.865 63.0391 400.422C63.0391 399.958 63.1823 399.56 63.4688 399.227C63.7604 398.888 64.1667 398.633 64.6875 398.461C65.2135 398.284 65.8281 398.195 66.5312 398.195ZM66.5312 399.531C66.1875 399.531 65.8984 399.562 65.6641 399.625C65.4297 399.688 65.25 399.786 65.125 399.922C65.0052 400.057 64.9453 400.224 64.9453 400.422C64.9453 400.594 65.0052 400.745 65.125 400.875C65.25 401 65.4297 401.096 65.6641 401.164C65.9036 401.227 66.1927 401.258 66.5312 401.258C66.8594 401.258 67.1406 401.227 67.375 401.164C67.6146 401.096 67.7943 401 67.9141 400.875C68.0391 400.745 68.1016 400.594 68.1016 400.422C68.1016 400.224 68.0417 400.057 67.9219 399.922C67.8021 399.786 67.6224 399.688 67.3828 399.625C67.1484 399.562 66.8646 399.531 66.5312 399.531ZM67.5312 397.008H65.5469V395.164H67.5312V397.008Z" fill="#56555A"/> -<path d="M288.781 404.531L293.875 396.688H294.719V398.469H294.125L290.297 404.359V404.453H297.188V405.688H288.781V404.531ZM294.266 405.344V404.797V396.688H295.609V408H294.266V405.344ZM302.812 396.531C303.531 396.542 304.201 396.714 304.82 397.047C305.44 397.38 305.945 397.945 306.336 398.742C306.727 399.534 306.922 400.583 306.922 401.891C306.922 403.214 306.75 404.344 306.406 405.281C306.062 406.219 305.568 406.932 304.922 407.422C304.276 407.911 303.51 408.156 302.625 408.156C301.969 408.156 301.38 408.029 300.859 407.773C300.339 407.518 299.914 407.167 299.586 406.719C299.258 406.266 299.047 405.74 298.953 405.141H300.344C300.427 405.49 300.57 405.797 300.773 406.062C300.977 406.323 301.234 406.529 301.547 406.68C301.859 406.831 302.219 406.906 302.625 406.906C303.24 406.906 303.771 406.734 304.219 406.391C304.667 406.047 305.008 405.552 305.242 404.906C305.482 404.255 305.604 403.474 305.609 402.562H305.453C305.234 402.875 304.977 403.143 304.68 403.367C304.383 403.591 304.055 403.763 303.695 403.883C303.336 404.003 302.958 404.062 302.562 404.062C301.891 404.062 301.271 403.901 300.703 403.578C300.141 403.255 299.693 402.81 299.359 402.242C299.026 401.674 298.859 401.036 298.859 400.328C298.859 399.625 299.023 398.984 299.352 398.406C299.68 397.823 300.143 397.365 300.742 397.031C301.341 396.693 302.031 396.526 302.812 396.531ZM302.812 397.766C302.328 397.766 301.888 397.88 301.492 398.109C301.102 398.339 300.792 398.648 300.562 399.039C300.339 399.43 300.229 399.854 300.234 400.312C300.234 400.776 300.344 401.201 300.562 401.586C300.781 401.966 301.081 402.268 301.461 402.492C301.846 402.716 302.281 402.828 302.766 402.828C303.245 402.828 303.685 402.708 304.086 402.469C304.487 402.229 304.805 401.914 305.039 401.523C305.273 401.133 305.391 400.719 305.391 400.281C305.391 399.849 305.279 399.44 305.055 399.055C304.831 398.664 304.521 398.352 304.125 398.117C303.734 397.883 303.297 397.766 302.812 397.766ZM309.016 411.203H307.859L308.719 406.953H310.234L309.016 411.203ZM316 408.156C315.219 408.156 314.523 408.021 313.914 407.75C313.305 407.479 312.831 407.104 312.492 406.625C312.154 406.146 311.984 405.604 311.984 405C311.984 404.521 312.086 404.073 312.289 403.656C312.492 403.24 312.768 402.898 313.117 402.633C313.466 402.362 313.854 402.193 314.281 402.125V402.062C313.911 401.979 313.586 401.815 313.305 401.57C313.029 401.326 312.812 401.026 312.656 400.672C312.5 400.318 312.422 399.938 312.422 399.531C312.422 398.964 312.576 398.453 312.883 398C313.19 397.542 313.615 397.182 314.156 396.922C314.703 396.661 315.318 396.531 316 396.531C316.677 396.531 317.289 396.661 317.836 396.922C318.383 397.182 318.81 397.542 319.117 398C319.43 398.453 319.589 398.964 319.594 399.531C319.589 399.938 319.505 400.318 319.344 400.672C319.188 401.026 318.969 401.326 318.688 401.57C318.406 401.815 318.083 401.979 317.719 402.062V402.125C318.141 402.193 318.526 402.362 318.875 402.633C319.229 402.898 319.508 403.24 319.711 403.656C319.919 404.073 320.026 404.521 320.031 405C320.026 405.604 319.852 406.146 319.508 406.625C319.169 407.104 318.693 407.479 318.078 407.75C317.469 408.021 316.776 408.156 316 408.156ZM316 406.922C316.531 406.922 316.995 406.836 317.391 406.664C317.786 406.492 318.091 406.258 318.305 405.961C318.518 405.664 318.625 405.318 318.625 404.922C318.625 404.51 318.513 404.141 318.289 403.812C318.065 403.479 317.753 403.219 317.352 403.031C316.951 402.844 316.5 402.75 316 402.75C315.5 402.75 315.052 402.844 314.656 403.031C314.26 403.219 313.948 403.479 313.719 403.812C313.495 404.141 313.385 404.51 313.391 404.922C313.385 405.318 313.487 405.664 313.695 405.961C313.909 406.258 314.211 406.492 314.602 406.664C314.997 406.836 315.464 406.922 316 406.922ZM316 401.562C316.427 401.562 316.81 401.479 317.148 401.312C317.487 401.146 317.75 400.919 317.938 400.633C318.125 400.346 318.219 400.016 318.219 399.641C318.219 399.266 318.128 398.935 317.945 398.648C317.763 398.362 317.503 398.141 317.164 397.984C316.826 397.828 316.438 397.75 316 397.75C315.557 397.75 315.169 397.828 314.836 397.984C314.508 398.141 314.25 398.362 314.062 398.648C313.875 398.935 313.781 399.266 313.781 399.641C313.781 400.016 313.878 400.346 314.07 400.633C314.263 400.919 314.526 401.146 314.859 401.312C315.193 401.479 315.573 401.562 316 401.562ZM325.609 408.156C324.938 408.156 324.326 408.026 323.773 407.766C323.227 407.505 322.789 407.148 322.461 406.695C322.138 406.242 321.964 405.729 321.938 405.156H323.297C323.328 405.49 323.451 405.789 323.664 406.055C323.878 406.32 324.154 406.531 324.492 406.688C324.836 406.844 325.208 406.922 325.609 406.922C326.094 406.922 326.526 406.812 326.906 406.594C327.292 406.375 327.594 406.076 327.812 405.695C328.031 405.315 328.141 404.891 328.141 404.422C328.141 403.938 328.029 403.503 327.805 403.117C327.581 402.727 327.268 402.419 326.867 402.195C326.466 401.971 326.016 401.859 325.516 401.859C325.021 401.849 324.596 401.927 324.242 402.094C323.888 402.255 323.609 402.516 323.406 402.875H322.047L322.844 396.688H328.969V397.938H324.016L323.594 401.25H323.703C323.964 401.052 324.273 400.893 324.633 400.773C324.997 400.654 325.375 400.594 325.766 400.594C326.474 400.594 327.115 400.755 327.688 401.078C328.26 401.401 328.708 401.854 329.031 402.438C329.354 403.016 329.516 403.667 329.516 404.391C329.516 405.109 329.346 405.755 329.008 406.328C328.669 406.901 328.203 407.349 327.609 407.672C327.021 407.995 326.354 408.156 325.609 408.156ZM335.172 408.156C334.339 408.156 333.628 407.93 333.039 407.477C332.451 407.023 332 406.362 331.688 405.492C331.375 404.622 331.219 403.573 331.219 402.344C331.219 401.13 331.375 400.089 331.688 399.219C332 398.344 332.451 397.677 333.039 397.219C333.633 396.76 334.344 396.531 335.172 396.531C335.995 396.531 336.703 396.76 337.297 397.219C337.891 397.677 338.344 398.344 338.656 399.219C338.969 400.089 339.125 401.13 339.125 402.344C339.125 403.573 338.971 404.622 338.664 405.492C338.357 406.362 337.906 407.023 337.312 407.477C336.719 407.93 336.005 408.156 335.172 408.156ZM335.172 406.906C335.714 406.906 336.18 406.729 336.57 406.375C336.961 406.021 337.255 405.503 337.453 404.82C337.651 404.138 337.75 403.312 337.75 402.344C337.75 401.375 337.648 400.547 337.445 399.859C337.242 399.172 336.948 398.648 336.562 398.289C336.177 397.93 335.714 397.75 335.172 397.75C334.63 397.75 334.167 397.93 333.781 398.289C333.396 398.648 333.099 399.172 332.891 399.859C332.682 400.547 332.578 401.375 332.578 402.344C332.578 403.312 332.682 404.138 332.891 404.82C333.099 405.503 333.393 406.021 333.773 406.375C334.159 406.729 334.625 406.906 335.172 406.906ZM349.75 405.453H348.516V402.359H349.75V405.453ZM355.969 405.938H354.734V395.391H355.969V405.938ZM356.312 408.969H346.438V407.938H356.312V408.969ZM347.672 408.234H346.438V404.906H347.672V408.234ZM344.438 401.828C346.297 401.818 347.943 401.789 349.375 401.742C350.807 401.69 352.177 401.583 353.484 401.422L353.562 402.312C352.214 402.526 350.799 402.667 349.32 402.734C347.841 402.802 346.271 402.833 344.609 402.828L344.438 401.828ZM355.062 404.5H351.859V403.609H355.062V404.5ZM349 395.953C349.672 395.953 350.268 396.052 350.789 396.25C351.315 396.448 351.721 396.732 352.008 397.102C352.294 397.471 352.438 397.896 352.438 398.375C352.438 398.865 352.294 399.289 352.008 399.648C351.721 400.008 351.318 400.286 350.797 400.484C350.276 400.682 349.677 400.781 349 400.781C348.318 400.781 347.716 400.682 347.195 400.484C346.68 400.286 346.279 400.008 345.992 399.648C345.706 399.289 345.562 398.865 345.562 398.375C345.562 397.896 345.706 397.471 345.992 397.102C346.279 396.732 346.682 396.448 347.203 396.25C347.724 396.052 348.323 395.953 349 395.953ZM349 396.891C348.552 396.885 348.156 396.945 347.812 397.07C347.469 397.19 347.201 397.365 347.008 397.594C346.82 397.823 346.729 398.083 346.734 398.375C346.729 398.672 346.82 398.935 347.008 399.164C347.201 399.388 347.469 399.562 347.812 399.688C348.156 399.812 348.552 399.875 349 399.875C349.438 399.875 349.828 399.812 350.172 399.688C350.516 399.562 350.784 399.388 350.977 399.164C351.169 398.935 351.266 398.672 351.266 398.375C351.266 398.083 351.169 397.823 350.977 397.594C350.784 397.365 350.516 397.19 350.172 397.07C349.828 396.945 349.438 396.885 349 396.891Z" fill="#56555A"/> -<path d="M376 398L380 402L376 406" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -<path d="M390 430H40C35.5817 430 32 433.582 32 438V462C32 466.418 35.5817 470 40 470H390C394.418 470 398 466.418 398 462V438C398 433.582 394.418 430 390 430Z" fill="white"/> -<path d="M60.8125 446.609H48.9766V445.016H60.8125V446.609ZM61.4297 455.992H48.4297V454.383H61.4297V455.992ZM55.875 455.008H53.8984V452.469H55.875V455.008ZM54.8906 447.227C55.8698 447.227 56.724 447.336 57.4531 447.555C58.1875 447.773 58.75 448.094 59.1406 448.516C59.5365 448.932 59.7344 449.424 59.7344 449.992C59.7344 450.57 59.5365 451.07 59.1406 451.492C58.75 451.909 58.1901 452.232 57.4609 452.461C56.7318 452.685 55.875 452.799 54.8906 452.805C53.8906 452.799 53.026 452.685 52.2969 452.461C51.5677 452.232 51.0052 451.909 50.6094 451.492C50.2188 451.07 50.026 450.57 50.0312 449.992C50.026 449.419 50.2188 448.924 50.6094 448.508C51.0052 448.091 51.5677 447.773 52.2969 447.555C53.0312 447.336 53.8958 447.227 54.8906 447.227ZM54.8906 448.781C54.2656 448.786 53.7448 448.833 53.3281 448.922C52.9167 449.005 52.6042 449.138 52.3906 449.32C52.1771 449.497 52.0729 449.721 52.0781 449.992C52.0729 450.263 52.1771 450.49 52.3906 450.672C52.6042 450.849 52.9167 450.984 53.3281 451.078C53.7448 451.167 54.2656 451.211 54.8906 451.211C55.5 451.211 56.0104 451.167 56.4219 451.078C56.8385 450.984 57.1536 450.849 57.3672 450.672C57.5807 450.49 57.6875 450.263 57.6875 449.992C57.6875 449.721 57.5807 449.497 57.3672 449.32C57.1536 449.138 56.8385 449.005 56.4219 448.922C56.0104 448.833 55.5 448.786 54.8906 448.781ZM55.875 446.008H53.8984V443.359H55.875V446.008ZM74.2344 453.633H72.25V443.234H74.2344V453.633ZM72.5312 448.977H69.7031V447.352H72.5312V448.977ZM69.8359 444.273C69.8307 445.539 69.5703 446.693 69.0547 447.734C68.5391 448.771 67.7891 449.669 66.8047 450.43C65.8203 451.185 64.6354 451.779 63.25 452.211L62.4297 450.617C63.5234 450.273 64.4661 449.831 65.2578 449.289C66.0547 448.742 66.6615 448.12 67.0781 447.422C67.5 446.724 67.7135 445.974 67.7188 445.172V444.273H69.8359ZM68.9922 445.906H63.1719V444.273H68.9922V445.906ZM74.6016 457.195H64.8516V455.586H74.6016V457.195ZM66.875 456.508H64.8516V452.57H66.875V456.508Z" fill="#56555A"/> -<path d="M288.781 452.531L293.875 444.688H294.719V446.469H294.125L290.297 452.359V452.453H297.188V453.688H288.781V452.531ZM294.266 453.344V452.797V444.688H295.609V456H294.266V453.344ZM302.812 444.531C303.531 444.542 304.201 444.714 304.82 445.047C305.44 445.38 305.945 445.945 306.336 446.742C306.727 447.534 306.922 448.583 306.922 449.891C306.922 451.214 306.75 452.344 306.406 453.281C306.062 454.219 305.568 454.932 304.922 455.422C304.276 455.911 303.51 456.156 302.625 456.156C301.969 456.156 301.38 456.029 300.859 455.773C300.339 455.518 299.914 455.167 299.586 454.719C299.258 454.266 299.047 453.74 298.953 453.141H300.344C300.427 453.49 300.57 453.797 300.773 454.062C300.977 454.323 301.234 454.529 301.547 454.68C301.859 454.831 302.219 454.906 302.625 454.906C303.24 454.906 303.771 454.734 304.219 454.391C304.667 454.047 305.008 453.552 305.242 452.906C305.482 452.255 305.604 451.474 305.609 450.562H305.453C305.234 450.875 304.977 451.143 304.68 451.367C304.383 451.591 304.055 451.763 303.695 451.883C303.336 452.003 302.958 452.062 302.562 452.062C301.891 452.062 301.271 451.901 300.703 451.578C300.141 451.255 299.693 450.81 299.359 450.242C299.026 449.674 298.859 449.036 298.859 448.328C298.859 447.625 299.023 446.984 299.352 446.406C299.68 445.823 300.143 445.365 300.742 445.031C301.341 444.693 302.031 444.526 302.812 444.531ZM302.812 445.766C302.328 445.766 301.888 445.88 301.492 446.109C301.102 446.339 300.792 446.648 300.562 447.039C300.339 447.43 300.229 447.854 300.234 448.312C300.234 448.776 300.344 449.201 300.562 449.586C300.781 449.966 301.081 450.268 301.461 450.492C301.846 450.716 302.281 450.828 302.766 450.828C303.245 450.828 303.685 450.708 304.086 450.469C304.487 450.229 304.805 449.914 305.039 449.523C305.273 449.133 305.391 448.719 305.391 448.281C305.391 447.849 305.279 447.44 305.055 447.055C304.831 446.664 304.521 446.352 304.125 446.117C303.734 445.883 303.297 445.766 302.812 445.766ZM309.016 459.203H307.859L308.719 454.953H310.234L309.016 459.203ZM316 456.156C315.219 456.156 314.523 456.021 313.914 455.75C313.305 455.479 312.831 455.104 312.492 454.625C312.154 454.146 311.984 453.604 311.984 453C311.984 452.521 312.086 452.073 312.289 451.656C312.492 451.24 312.768 450.898 313.117 450.633C313.466 450.362 313.854 450.193 314.281 450.125V450.062C313.911 449.979 313.586 449.815 313.305 449.57C313.029 449.326 312.812 449.026 312.656 448.672C312.5 448.318 312.422 447.938 312.422 447.531C312.422 446.964 312.576 446.453 312.883 446C313.19 445.542 313.615 445.182 314.156 444.922C314.703 444.661 315.318 444.531 316 444.531C316.677 444.531 317.289 444.661 317.836 444.922C318.383 445.182 318.81 445.542 319.117 446C319.43 446.453 319.589 446.964 319.594 447.531C319.589 447.938 319.505 448.318 319.344 448.672C319.188 449.026 318.969 449.326 318.688 449.57C318.406 449.815 318.083 449.979 317.719 450.062V450.125C318.141 450.193 318.526 450.362 318.875 450.633C319.229 450.898 319.508 451.24 319.711 451.656C319.919 452.073 320.026 452.521 320.031 453C320.026 453.604 319.852 454.146 319.508 454.625C319.169 455.104 318.693 455.479 318.078 455.75C317.469 456.021 316.776 456.156 316 456.156ZM316 454.922C316.531 454.922 316.995 454.836 317.391 454.664C317.786 454.492 318.091 454.258 318.305 453.961C318.518 453.664 318.625 453.318 318.625 452.922C318.625 452.51 318.513 452.141 318.289 451.812C318.065 451.479 317.753 451.219 317.352 451.031C316.951 450.844 316.5 450.75 316 450.75C315.5 450.75 315.052 450.844 314.656 451.031C314.26 451.219 313.948 451.479 313.719 451.812C313.495 452.141 313.385 452.51 313.391 452.922C313.385 453.318 313.487 453.664 313.695 453.961C313.909 454.258 314.211 454.492 314.602 454.664C314.997 454.836 315.464 454.922 316 454.922ZM316 449.562C316.427 449.562 316.81 449.479 317.148 449.312C317.487 449.146 317.75 448.919 317.938 448.633C318.125 448.346 318.219 448.016 318.219 447.641C318.219 447.266 318.128 446.935 317.945 446.648C317.763 446.362 317.503 446.141 317.164 445.984C316.826 445.828 316.438 445.75 316 445.75C315.557 445.75 315.169 445.828 314.836 445.984C314.508 446.141 314.25 446.362 314.062 446.648C313.875 446.935 313.781 447.266 313.781 447.641C313.781 448.016 313.878 448.346 314.07 448.633C314.263 448.919 314.526 449.146 314.859 449.312C315.193 449.479 315.573 449.562 316 449.562ZM325.609 456.156C324.938 456.156 324.326 456.026 323.773 455.766C323.227 455.505 322.789 455.148 322.461 454.695C322.138 454.242 321.964 453.729 321.938 453.156H323.297C323.328 453.49 323.451 453.789 323.664 454.055C323.878 454.32 324.154 454.531 324.492 454.688C324.836 454.844 325.208 454.922 325.609 454.922C326.094 454.922 326.526 454.812 326.906 454.594C327.292 454.375 327.594 454.076 327.812 453.695C328.031 453.315 328.141 452.891 328.141 452.422C328.141 451.938 328.029 451.503 327.805 451.117C327.581 450.727 327.268 450.419 326.867 450.195C326.466 449.971 326.016 449.859 325.516 449.859C325.021 449.849 324.596 449.927 324.242 450.094C323.888 450.255 323.609 450.516 323.406 450.875H322.047L322.844 444.688H328.969V445.938H324.016L323.594 449.25H323.703C323.964 449.052 324.273 448.893 324.633 448.773C324.997 448.654 325.375 448.594 325.766 448.594C326.474 448.594 327.115 448.755 327.688 449.078C328.26 449.401 328.708 449.854 329.031 450.438C329.354 451.016 329.516 451.667 329.516 452.391C329.516 453.109 329.346 453.755 329.008 454.328C328.669 454.901 328.203 455.349 327.609 455.672C327.021 455.995 326.354 456.156 325.609 456.156ZM335.172 456.156C334.339 456.156 333.628 455.93 333.039 455.477C332.451 455.023 332 454.362 331.688 453.492C331.375 452.622 331.219 451.573 331.219 450.344C331.219 449.13 331.375 448.089 331.688 447.219C332 446.344 332.451 445.677 333.039 445.219C333.633 444.76 334.344 444.531 335.172 444.531C335.995 444.531 336.703 444.76 337.297 445.219C337.891 445.677 338.344 446.344 338.656 447.219C338.969 448.089 339.125 449.13 339.125 450.344C339.125 451.573 338.971 452.622 338.664 453.492C338.357 454.362 337.906 455.023 337.312 455.477C336.719 455.93 336.005 456.156 335.172 456.156ZM335.172 454.906C335.714 454.906 336.18 454.729 336.57 454.375C336.961 454.021 337.255 453.503 337.453 452.82C337.651 452.138 337.75 451.312 337.75 450.344C337.75 449.375 337.648 448.547 337.445 447.859C337.242 447.172 336.948 446.648 336.562 446.289C336.177 445.93 335.714 445.75 335.172 445.75C334.63 445.75 334.167 445.93 333.781 446.289C333.396 446.648 333.099 447.172 332.891 447.859C332.682 448.547 332.578 449.375 332.578 450.344C332.578 451.312 332.682 452.138 332.891 452.82C333.099 453.503 333.393 454.021 333.773 454.375C334.159 454.729 334.625 454.906 335.172 454.906ZM349.75 453.453H348.516V450.359H349.75V453.453ZM355.969 453.938H354.734V443.391H355.969V453.938ZM356.312 456.969H346.438V455.938H356.312V456.969ZM347.672 456.234H346.438V452.906H347.672V456.234ZM344.438 449.828C346.297 449.818 347.943 449.789 349.375 449.742C350.807 449.69 352.177 449.583 353.484 449.422L353.562 450.312C352.214 450.526 350.799 450.667 349.32 450.734C347.841 450.802 346.271 450.833 344.609 450.828L344.438 449.828ZM355.062 452.5H351.859V451.609H355.062V452.5ZM349 443.953C349.672 443.953 350.268 444.052 350.789 444.25C351.315 444.448 351.721 444.732 352.008 445.102C352.294 445.471 352.438 445.896 352.438 446.375C352.438 446.865 352.294 447.289 352.008 447.648C351.721 448.008 351.318 448.286 350.797 448.484C350.276 448.682 349.677 448.781 349 448.781C348.318 448.781 347.716 448.682 347.195 448.484C346.68 448.286 346.279 448.008 345.992 447.648C345.706 447.289 345.562 446.865 345.562 446.375C345.562 445.896 345.706 445.471 345.992 445.102C346.279 444.732 346.682 444.448 347.203 444.25C347.724 444.052 348.323 443.953 349 443.953ZM349 444.891C348.552 444.885 348.156 444.945 347.812 445.07C347.469 445.19 347.201 445.365 347.008 445.594C346.82 445.823 346.729 446.083 346.734 446.375C346.729 446.672 346.82 446.935 347.008 447.164C347.201 447.388 347.469 447.562 347.812 447.688C348.156 447.812 348.552 447.875 349 447.875C349.438 447.875 349.828 447.812 350.172 447.688C350.516 447.562 350.784 447.388 350.977 447.164C351.169 446.935 351.266 446.672 351.266 446.375C351.266 446.083 351.169 445.823 350.977 445.594C350.784 445.365 350.516 445.19 350.172 445.07C349.828 444.945 349.438 444.885 349 444.891Z" fill="#56555A"/> -<path d="M376 446L380 450L376 454" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -<path d="M390 478H40C35.5817 478 32 481.582 32 486V510C32 514.418 35.5817 518 40 518H390C394.418 518 398 514.418 398 510V486C398 481.582 394.418 478 390 478Z" fill="white"/> -<path d="M55.4922 493.227C55.4922 494.07 55.2656 494.841 54.8125 495.539C54.3646 496.232 53.7109 496.815 52.8516 497.289C51.9922 497.758 50.974 498.073 49.7969 498.234L49.0547 496.68C50.0495 496.56 50.901 496.323 51.6094 495.969C52.3229 495.609 52.8594 495.193 53.2188 494.719C53.5781 494.24 53.7578 493.742 53.7578 493.227V492.797H55.4922V493.227ZM56.0625 493.227C56.0625 493.742 56.2396 494.24 56.5938 494.719C56.9531 495.193 57.487 495.609 58.1953 495.969C58.9089 496.323 59.7708 496.56 60.7812 496.68L60.0625 498.234C58.875 498.073 57.849 497.758 56.9844 497.289C56.1198 496.815 55.4609 496.232 55.0078 495.539C54.5547 494.841 54.3281 494.07 54.3281 493.227V492.797H56.0625V493.227ZM55.8594 505.445H53.8828V500.203H55.8594V505.445ZM61.3984 500.656H48.4297V499.07H61.3984V500.656ZM60.2266 493.523H49.5938V491.969H60.2266V493.523ZM73.4688 505.438H71.5V491.203H73.4688V505.438ZM75.5781 498.422H73.0312V496.789H75.5781V498.422ZM70.5312 494.938H62.1797V493.336H70.5312V494.938ZM66.3906 495.727C67.0729 495.727 67.6901 495.872 68.2422 496.164C68.7995 496.451 69.2344 496.852 69.5469 497.367C69.8646 497.883 70.026 498.466 70.0312 499.117C70.026 499.773 69.8646 500.359 69.5469 500.875C69.2344 501.385 68.7995 501.786 68.2422 502.078C67.6901 502.365 67.0729 502.508 66.3906 502.508C65.6979 502.508 65.0755 502.365 64.5234 502.078C63.9714 501.786 63.5391 501.385 63.2266 500.875C62.9141 500.359 62.7578 499.773 62.7578 499.117C62.7578 498.466 62.9141 497.883 63.2266 497.367C63.5391 496.852 63.9714 496.451 64.5234 496.164C65.0755 495.872 65.6979 495.727 66.3906 495.727ZM66.3906 497.352C66.0573 497.357 65.7604 497.43 65.5 497.57C65.2396 497.711 65.0339 497.917 64.8828 498.188C64.737 498.453 64.6641 498.763 64.6641 499.117C64.6641 499.482 64.737 499.797 64.8828 500.062C65.0339 500.323 65.2396 500.523 65.5 500.664C65.7604 500.805 66.0573 500.878 66.3906 500.883C66.724 500.878 67.0208 500.805 67.2812 500.664C67.5469 500.523 67.75 500.323 67.8906 500.062C68.0365 499.797 68.1094 499.482 68.1094 499.117C68.1094 498.763 68.0365 498.453 67.8906 498.188C67.75 497.917 67.5469 497.711 67.2812 497.57C67.0208 497.43 66.724 497.357 66.3906 497.352ZM67.3828 493.945H65.3984V491.43H67.3828V493.945Z" fill="#56555A"/> -<path d="M288.781 500.531L293.875 492.688H294.719V494.469H294.125L290.297 500.359V500.453H297.188V501.688H288.781V500.531ZM294.266 501.344V500.797V492.688H295.609V504H294.266V501.344ZM302.812 492.531C303.531 492.542 304.201 492.714 304.82 493.047C305.44 493.38 305.945 493.945 306.336 494.742C306.727 495.534 306.922 496.583 306.922 497.891C306.922 499.214 306.75 500.344 306.406 501.281C306.062 502.219 305.568 502.932 304.922 503.422C304.276 503.911 303.51 504.156 302.625 504.156C301.969 504.156 301.38 504.029 300.859 503.773C300.339 503.518 299.914 503.167 299.586 502.719C299.258 502.266 299.047 501.74 298.953 501.141H300.344C300.427 501.49 300.57 501.797 300.773 502.062C300.977 502.323 301.234 502.529 301.547 502.68C301.859 502.831 302.219 502.906 302.625 502.906C303.24 502.906 303.771 502.734 304.219 502.391C304.667 502.047 305.008 501.552 305.242 500.906C305.482 500.255 305.604 499.474 305.609 498.562H305.453C305.234 498.875 304.977 499.143 304.68 499.367C304.383 499.591 304.055 499.763 303.695 499.883C303.336 500.003 302.958 500.062 302.562 500.062C301.891 500.062 301.271 499.901 300.703 499.578C300.141 499.255 299.693 498.81 299.359 498.242C299.026 497.674 298.859 497.036 298.859 496.328C298.859 495.625 299.023 494.984 299.352 494.406C299.68 493.823 300.143 493.365 300.742 493.031C301.341 492.693 302.031 492.526 302.812 492.531ZM302.812 493.766C302.328 493.766 301.888 493.88 301.492 494.109C301.102 494.339 300.792 494.648 300.562 495.039C300.339 495.43 300.229 495.854 300.234 496.312C300.234 496.776 300.344 497.201 300.562 497.586C300.781 497.966 301.081 498.268 301.461 498.492C301.846 498.716 302.281 498.828 302.766 498.828C303.245 498.828 303.685 498.708 304.086 498.469C304.487 498.229 304.805 497.914 305.039 497.523C305.273 497.133 305.391 496.719 305.391 496.281C305.391 495.849 305.279 495.44 305.055 495.055C304.831 494.664 304.521 494.352 304.125 494.117C303.734 493.883 303.297 493.766 302.812 493.766ZM309.016 507.203H307.859L308.719 502.953H310.234L309.016 507.203ZM316 504.156C315.219 504.156 314.523 504.021 313.914 503.75C313.305 503.479 312.831 503.104 312.492 502.625C312.154 502.146 311.984 501.604 311.984 501C311.984 500.521 312.086 500.073 312.289 499.656C312.492 499.24 312.768 498.898 313.117 498.633C313.466 498.362 313.854 498.193 314.281 498.125V498.062C313.911 497.979 313.586 497.815 313.305 497.57C313.029 497.326 312.812 497.026 312.656 496.672C312.5 496.318 312.422 495.938 312.422 495.531C312.422 494.964 312.576 494.453 312.883 494C313.19 493.542 313.615 493.182 314.156 492.922C314.703 492.661 315.318 492.531 316 492.531C316.677 492.531 317.289 492.661 317.836 492.922C318.383 493.182 318.81 493.542 319.117 494C319.43 494.453 319.589 494.964 319.594 495.531C319.589 495.938 319.505 496.318 319.344 496.672C319.188 497.026 318.969 497.326 318.688 497.57C318.406 497.815 318.083 497.979 317.719 498.062V498.125C318.141 498.193 318.526 498.362 318.875 498.633C319.229 498.898 319.508 499.24 319.711 499.656C319.919 500.073 320.026 500.521 320.031 501C320.026 501.604 319.852 502.146 319.508 502.625C319.169 503.104 318.693 503.479 318.078 503.75C317.469 504.021 316.776 504.156 316 504.156ZM316 502.922C316.531 502.922 316.995 502.836 317.391 502.664C317.786 502.492 318.091 502.258 318.305 501.961C318.518 501.664 318.625 501.318 318.625 500.922C318.625 500.51 318.513 500.141 318.289 499.812C318.065 499.479 317.753 499.219 317.352 499.031C316.951 498.844 316.5 498.75 316 498.75C315.5 498.75 315.052 498.844 314.656 499.031C314.26 499.219 313.948 499.479 313.719 499.812C313.495 500.141 313.385 500.51 313.391 500.922C313.385 501.318 313.487 501.664 313.695 501.961C313.909 502.258 314.211 502.492 314.602 502.664C314.997 502.836 315.464 502.922 316 502.922ZM316 497.562C316.427 497.562 316.81 497.479 317.148 497.312C317.487 497.146 317.75 496.919 317.938 496.633C318.125 496.346 318.219 496.016 318.219 495.641C318.219 495.266 318.128 494.935 317.945 494.648C317.763 494.362 317.503 494.141 317.164 493.984C316.826 493.828 316.438 493.75 316 493.75C315.557 493.75 315.169 493.828 314.836 493.984C314.508 494.141 314.25 494.362 314.062 494.648C313.875 494.935 313.781 495.266 313.781 495.641C313.781 496.016 313.878 496.346 314.07 496.633C314.263 496.919 314.526 497.146 314.859 497.312C315.193 497.479 315.573 497.562 316 497.562ZM325.609 504.156C324.938 504.156 324.326 504.026 323.773 503.766C323.227 503.505 322.789 503.148 322.461 502.695C322.138 502.242 321.964 501.729 321.938 501.156H323.297C323.328 501.49 323.451 501.789 323.664 502.055C323.878 502.32 324.154 502.531 324.492 502.688C324.836 502.844 325.208 502.922 325.609 502.922C326.094 502.922 326.526 502.812 326.906 502.594C327.292 502.375 327.594 502.076 327.812 501.695C328.031 501.315 328.141 500.891 328.141 500.422C328.141 499.938 328.029 499.503 327.805 499.117C327.581 498.727 327.268 498.419 326.867 498.195C326.466 497.971 326.016 497.859 325.516 497.859C325.021 497.849 324.596 497.927 324.242 498.094C323.888 498.255 323.609 498.516 323.406 498.875H322.047L322.844 492.688H328.969V493.938H324.016L323.594 497.25H323.703C323.964 497.052 324.273 496.893 324.633 496.773C324.997 496.654 325.375 496.594 325.766 496.594C326.474 496.594 327.115 496.755 327.688 497.078C328.26 497.401 328.708 497.854 329.031 498.438C329.354 499.016 329.516 499.667 329.516 500.391C329.516 501.109 329.346 501.755 329.008 502.328C328.669 502.901 328.203 503.349 327.609 503.672C327.021 503.995 326.354 504.156 325.609 504.156ZM335.172 504.156C334.339 504.156 333.628 503.93 333.039 503.477C332.451 503.023 332 502.362 331.688 501.492C331.375 500.622 331.219 499.573 331.219 498.344C331.219 497.13 331.375 496.089 331.688 495.219C332 494.344 332.451 493.677 333.039 493.219C333.633 492.76 334.344 492.531 335.172 492.531C335.995 492.531 336.703 492.76 337.297 493.219C337.891 493.677 338.344 494.344 338.656 495.219C338.969 496.089 339.125 497.13 339.125 498.344C339.125 499.573 338.971 500.622 338.664 501.492C338.357 502.362 337.906 503.023 337.312 503.477C336.719 503.93 336.005 504.156 335.172 504.156ZM335.172 502.906C335.714 502.906 336.18 502.729 336.57 502.375C336.961 502.021 337.255 501.503 337.453 500.82C337.651 500.138 337.75 499.312 337.75 498.344C337.75 497.375 337.648 496.547 337.445 495.859C337.242 495.172 336.948 494.648 336.562 494.289C336.177 493.93 335.714 493.75 335.172 493.75C334.63 493.75 334.167 493.93 333.781 494.289C333.396 494.648 333.099 495.172 332.891 495.859C332.682 496.547 332.578 497.375 332.578 498.344C332.578 499.312 332.682 500.138 332.891 500.82C333.099 501.503 333.393 502.021 333.773 502.375C334.159 502.729 334.625 502.906 335.172 502.906ZM349.75 501.453H348.516V498.359H349.75V501.453ZM355.969 501.938H354.734V491.391H355.969V501.938ZM356.312 504.969H346.438V503.938H356.312V504.969ZM347.672 504.234H346.438V500.906H347.672V504.234ZM344.438 497.828C346.297 497.818 347.943 497.789 349.375 497.742C350.807 497.69 352.177 497.583 353.484 497.422L353.562 498.312C352.214 498.526 350.799 498.667 349.32 498.734C347.841 498.802 346.271 498.833 344.609 498.828L344.438 497.828ZM355.062 500.5H351.859V499.609H355.062V500.5ZM349 491.953C349.672 491.953 350.268 492.052 350.789 492.25C351.315 492.448 351.721 492.732 352.008 493.102C352.294 493.471 352.438 493.896 352.438 494.375C352.438 494.865 352.294 495.289 352.008 495.648C351.721 496.008 351.318 496.286 350.797 496.484C350.276 496.682 349.677 496.781 349 496.781C348.318 496.781 347.716 496.682 347.195 496.484C346.68 496.286 346.279 496.008 345.992 495.648C345.706 495.289 345.562 494.865 345.562 494.375C345.562 493.896 345.706 493.471 345.992 493.102C346.279 492.732 346.682 492.448 347.203 492.25C347.724 492.052 348.323 491.953 349 491.953ZM349 492.891C348.552 492.885 348.156 492.945 347.812 493.07C347.469 493.19 347.201 493.365 347.008 493.594C346.82 493.823 346.729 494.083 346.734 494.375C346.729 494.672 346.82 494.935 347.008 495.164C347.201 495.388 347.469 495.562 347.812 495.688C348.156 495.812 348.552 495.875 349 495.875C349.438 495.875 349.828 495.812 350.172 495.688C350.516 495.562 350.784 495.388 350.977 495.164C351.169 494.935 351.266 494.672 351.266 494.375C351.266 494.083 351.169 493.823 350.977 493.594C350.784 493.365 350.516 493.19 350.172 493.07C349.828 492.945 349.438 492.885 349 492.891Z" fill="#56555A"/> -<path d="M376 494L380 498L376 502" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -<path d="M390 526H40C35.5817 526 32 529.582 32 534V558C32 562.418 35.5817 566 40 566H390C394.418 566 398 562.418 398 558V534C398 529.582 394.418 526 390 526Z" fill="white"/> -<path d="M61.4297 551.742H48.4297V550.148H61.4297V551.742ZM55.8438 550.57H53.8594V546.922H55.8438V550.57ZM55.5312 541.047C55.5312 542.062 55.2891 543.01 54.8047 543.891C54.3255 544.766 53.6354 545.51 52.7344 546.125C51.8385 546.74 50.7891 547.159 49.5859 547.383L48.7266 545.719C49.763 545.557 50.6641 545.237 51.4297 544.758C52.1953 544.273 52.776 543.708 53.1719 543.062C53.5729 542.411 53.776 541.74 53.7812 541.047V540.039H55.5312V541.047ZM55.8984 541.047C55.8984 541.745 56.099 542.419 56.5 543.07C56.9062 543.716 57.4922 544.279 58.2578 544.758C59.0286 545.237 59.9375 545.557 60.9844 545.719L60.1328 547.383C58.9245 547.159 57.8698 546.745 56.9688 546.141C56.0677 545.531 55.375 544.789 54.8906 543.914C54.4062 543.034 54.1667 542.078 54.1719 541.047V540.039H55.8984V541.047ZM72.9609 542.82H68.7422V541.219H72.9609V542.82ZM72.9609 546.258H68.7422V544.664H72.9609V546.258ZM74.2344 549.633H72.25V539.234H74.2344V549.633ZM74.5781 553.195H64.7969V551.586H74.5781V553.195ZM66.7969 552.406H64.7969V548.578H66.7969V552.406ZM66.2188 540.055C66.9062 540.055 67.5365 540.214 68.1094 540.531C68.6875 540.849 69.1432 541.289 69.4766 541.852C69.8099 542.414 69.9792 543.047 69.9844 543.75C69.9792 544.443 69.8073 545.068 69.4688 545.625C69.1354 546.182 68.6823 546.622 68.1094 546.945C67.5365 547.263 66.9062 547.422 66.2188 547.422C65.5052 547.422 64.8594 547.263 64.2812 546.945C63.7083 546.622 63.2552 546.182 62.9219 545.625C62.5938 545.068 62.4297 544.443 62.4297 543.75C62.4297 543.047 62.5938 542.414 62.9219 541.852C63.2552 541.289 63.7083 540.849 64.2812 540.531C64.8594 540.214 65.5052 540.055 66.2188 540.055ZM66.2188 541.828C65.849 541.823 65.5208 541.898 65.2344 542.055C64.9479 542.211 64.724 542.435 64.5625 542.727C64.401 543.018 64.3203 543.359 64.3203 543.75C64.3203 544.135 64.401 544.471 64.5625 544.758C64.724 545.044 64.9479 545.266 65.2344 545.422C65.5208 545.573 65.849 545.651 66.2188 545.656C66.5729 545.651 66.8906 545.573 67.1719 545.422C67.4531 545.266 67.6745 545.044 67.8359 544.758C67.9974 544.471 68.0781 544.135 68.0781 543.75C68.0781 543.359 67.9974 543.021 67.8359 542.734C67.6745 542.443 67.4531 542.219 67.1719 542.062C66.8906 541.901 66.5729 541.823 66.2188 541.828Z" fill="#56555A"/> -<path d="M289.047 550.969L292.906 546.906C293.411 546.365 293.797 545.927 294.062 545.594C294.333 545.26 294.539 544.943 294.68 544.641C294.82 544.333 294.891 544.01 294.891 543.672C294.891 543.292 294.792 542.958 294.594 542.672C294.396 542.38 294.125 542.154 293.781 541.992C293.443 541.831 293.062 541.75 292.641 541.75C292.198 541.75 291.81 541.839 291.477 542.016C291.148 542.193 290.893 542.443 290.711 542.766C290.529 543.083 290.438 543.453 290.438 543.875H289.109C289.104 543.219 289.255 542.638 289.562 542.133C289.875 541.628 290.305 541.234 290.852 540.953C291.398 540.672 292.01 540.531 292.688 540.531C293.359 540.531 293.961 540.669 294.492 540.945C295.029 541.221 295.448 541.599 295.75 542.078C296.052 542.557 296.203 543.089 296.203 543.672C296.198 544.104 296.117 544.518 295.961 544.914C295.81 545.305 295.549 545.74 295.18 546.219C294.81 546.698 294.286 547.286 293.609 547.984L291.016 550.656V550.75H296.406V552H289.062L289.047 550.969ZM302.359 552.156C301.615 552.156 300.948 552.031 300.359 551.781C299.776 551.531 299.312 551.18 298.969 550.727C298.625 550.268 298.443 549.745 298.422 549.156H299.844C299.87 549.51 299.995 549.818 300.219 550.078C300.448 550.339 300.745 550.542 301.109 550.688C301.479 550.833 301.891 550.906 302.344 550.906C302.839 550.906 303.281 550.823 303.672 550.656C304.068 550.49 304.375 550.255 304.594 549.953C304.812 549.651 304.922 549.307 304.922 548.922C304.917 548.51 304.807 548.146 304.594 547.828C304.385 547.505 304.073 547.255 303.656 547.078C303.24 546.901 302.745 546.812 302.172 546.812H301.25V545.578H302.172C302.625 545.578 303.029 545.497 303.383 545.336C303.742 545.174 304.018 544.948 304.211 544.656C304.404 544.359 304.5 544.021 304.5 543.641C304.5 543.266 304.414 542.935 304.242 542.648C304.07 542.362 303.826 542.141 303.508 541.984C303.19 541.828 302.818 541.75 302.391 541.75C301.984 541.755 301.604 541.831 301.25 541.977C300.896 542.117 300.607 542.323 300.383 542.594C300.159 542.859 300.036 543.172 300.016 543.531H298.656C298.677 542.948 298.859 542.427 299.203 541.969C299.547 541.51 300 541.156 300.562 540.906C301.125 540.656 301.74 540.531 302.406 540.531C303.104 540.531 303.716 540.669 304.242 540.945C304.768 541.221 305.169 541.591 305.445 542.055C305.727 542.518 305.865 543.021 305.859 543.562C305.865 543.984 305.789 544.37 305.633 544.719C305.482 545.062 305.26 545.354 304.969 545.594C304.677 545.833 304.333 546.01 303.938 546.125V546.203C304.422 546.276 304.841 546.435 305.195 546.68C305.555 546.924 305.828 547.24 306.016 547.625C306.203 548.01 306.297 548.443 306.297 548.922C306.297 549.531 306.128 550.083 305.789 550.578C305.451 551.068 304.979 551.453 304.375 551.734C303.776 552.016 303.104 552.156 302.359 552.156ZM308.531 555.203H307.375L308.234 550.953H309.75L308.531 555.203ZM315.516 552.156C314.734 552.156 314.039 552.021 313.43 551.75C312.82 551.479 312.346 551.104 312.008 550.625C311.669 550.146 311.5 549.604 311.5 549C311.5 548.521 311.602 548.073 311.805 547.656C312.008 547.24 312.284 546.898 312.633 546.633C312.982 546.362 313.37 546.193 313.797 546.125V546.062C313.427 545.979 313.102 545.815 312.82 545.57C312.544 545.326 312.328 545.026 312.172 544.672C312.016 544.318 311.938 543.938 311.938 543.531C311.938 542.964 312.091 542.453 312.398 542C312.706 541.542 313.13 541.182 313.672 540.922C314.219 540.661 314.833 540.531 315.516 540.531C316.193 540.531 316.805 540.661 317.352 540.922C317.898 541.182 318.326 541.542 318.633 542C318.945 542.453 319.104 542.964 319.109 543.531C319.104 543.938 319.021 544.318 318.859 544.672C318.703 545.026 318.484 545.326 318.203 545.57C317.922 545.815 317.599 545.979 317.234 546.062V546.125C317.656 546.193 318.042 546.362 318.391 546.633C318.745 546.898 319.023 547.24 319.227 547.656C319.435 548.073 319.542 548.521 319.547 549C319.542 549.604 319.367 550.146 319.023 550.625C318.685 551.104 318.208 551.479 317.594 551.75C316.984 552.021 316.292 552.156 315.516 552.156ZM315.516 550.922C316.047 550.922 316.51 550.836 316.906 550.664C317.302 550.492 317.607 550.258 317.82 549.961C318.034 549.664 318.141 549.318 318.141 548.922C318.141 548.51 318.029 548.141 317.805 547.812C317.581 547.479 317.268 547.219 316.867 547.031C316.466 546.844 316.016 546.75 315.516 546.75C315.016 546.75 314.568 546.844 314.172 547.031C313.776 547.219 313.464 547.479 313.234 547.812C313.01 548.141 312.901 548.51 312.906 548.922C312.901 549.318 313.003 549.664 313.211 549.961C313.424 550.258 313.727 550.492 314.117 550.664C314.513 550.836 314.979 550.922 315.516 550.922ZM315.516 545.562C315.943 545.562 316.326 545.479 316.664 545.312C317.003 545.146 317.266 544.919 317.453 544.633C317.641 544.346 317.734 544.016 317.734 543.641C317.734 543.266 317.643 542.935 317.461 542.648C317.279 542.362 317.018 542.141 316.68 541.984C316.341 541.828 315.953 541.75 315.516 541.75C315.073 541.75 314.685 541.828 314.352 541.984C314.023 542.141 313.766 542.362 313.578 542.648C313.391 542.935 313.297 543.266 313.297 543.641C313.297 544.016 313.393 544.346 313.586 544.633C313.779 544.919 314.042 545.146 314.375 545.312C314.708 545.479 315.089 545.562 315.516 545.562ZM325.125 552.156C324.453 552.156 323.841 552.026 323.289 551.766C322.742 551.505 322.305 551.148 321.977 550.695C321.654 550.242 321.479 549.729 321.453 549.156H322.812C322.844 549.49 322.966 549.789 323.18 550.055C323.393 550.32 323.669 550.531 324.008 550.688C324.352 550.844 324.724 550.922 325.125 550.922C325.609 550.922 326.042 550.812 326.422 550.594C326.807 550.375 327.109 550.076 327.328 549.695C327.547 549.315 327.656 548.891 327.656 548.422C327.656 547.938 327.544 547.503 327.32 547.117C327.096 546.727 326.784 546.419 326.383 546.195C325.982 545.971 325.531 545.859 325.031 545.859C324.536 545.849 324.112 545.927 323.758 546.094C323.404 546.255 323.125 546.516 322.922 546.875H321.562L322.359 540.688H328.484V541.938H323.531L323.109 545.25H323.219C323.479 545.052 323.789 544.893 324.148 544.773C324.513 544.654 324.891 544.594 325.281 544.594C325.99 544.594 326.63 544.755 327.203 545.078C327.776 545.401 328.224 545.854 328.547 546.438C328.87 547.016 329.031 547.667 329.031 548.391C329.031 549.109 328.862 549.755 328.523 550.328C328.185 550.901 327.719 551.349 327.125 551.672C326.536 551.995 325.87 552.156 325.125 552.156ZM334.688 552.156C333.854 552.156 333.143 551.93 332.555 551.477C331.966 551.023 331.516 550.362 331.203 549.492C330.891 548.622 330.734 547.573 330.734 546.344C330.734 545.13 330.891 544.089 331.203 543.219C331.516 542.344 331.966 541.677 332.555 541.219C333.148 540.76 333.859 540.531 334.688 540.531C335.51 540.531 336.219 540.76 336.812 541.219C337.406 541.677 337.859 542.344 338.172 543.219C338.484 544.089 338.641 545.13 338.641 546.344C338.641 547.573 338.487 548.622 338.18 549.492C337.872 550.362 337.422 551.023 336.828 551.477C336.234 551.93 335.521 552.156 334.688 552.156ZM334.688 550.906C335.229 550.906 335.695 550.729 336.086 550.375C336.477 550.021 336.771 549.503 336.969 548.82C337.167 548.138 337.266 547.312 337.266 546.344C337.266 545.375 337.164 544.547 336.961 543.859C336.758 543.172 336.464 542.648 336.078 542.289C335.693 541.93 335.229 541.75 334.688 541.75C334.146 541.75 333.682 541.93 333.297 542.289C332.911 542.648 332.615 543.172 332.406 543.859C332.198 544.547 332.094 545.375 332.094 546.344C332.094 547.312 332.198 548.138 332.406 548.82C332.615 549.503 332.909 550.021 333.289 550.375C333.674 550.729 334.141 550.906 334.688 550.906ZM349.266 549.453H348.031V546.359H349.266V549.453ZM355.484 549.938H354.25V539.391H355.484V549.938ZM355.828 552.969H345.953V551.938H355.828V552.969ZM347.188 552.234H345.953V548.906H347.188V552.234ZM343.953 545.828C345.812 545.818 347.458 545.789 348.891 545.742C350.323 545.69 351.693 545.583 353 545.422L353.078 546.312C351.729 546.526 350.315 546.667 348.836 546.734C347.357 546.802 345.786 546.833 344.125 546.828L343.953 545.828ZM354.578 548.5H351.375V547.609H354.578V548.5ZM348.516 539.953C349.188 539.953 349.784 540.052 350.305 540.25C350.831 540.448 351.237 540.732 351.523 541.102C351.81 541.471 351.953 541.896 351.953 542.375C351.953 542.865 351.81 543.289 351.523 543.648C351.237 544.008 350.833 544.286 350.312 544.484C349.792 544.682 349.193 544.781 348.516 544.781C347.833 544.781 347.232 544.682 346.711 544.484C346.195 544.286 345.794 544.008 345.508 543.648C345.221 543.289 345.078 542.865 345.078 542.375C345.078 541.896 345.221 541.471 345.508 541.102C345.794 540.732 346.198 540.448 346.719 540.25C347.24 540.052 347.839 539.953 348.516 539.953ZM348.516 540.891C348.068 540.885 347.672 540.945 347.328 541.07C346.984 541.19 346.716 541.365 346.523 541.594C346.336 541.823 346.245 542.083 346.25 542.375C346.245 542.672 346.336 542.935 346.523 543.164C346.716 543.388 346.984 543.562 347.328 543.688C347.672 543.812 348.068 543.875 348.516 543.875C348.953 543.875 349.344 543.812 349.688 543.688C350.031 543.562 350.299 543.388 350.492 543.164C350.685 542.935 350.781 542.672 350.781 542.375C350.781 542.083 350.685 541.823 350.492 541.594C350.299 541.365 350.031 541.19 349.688 541.07C349.344 540.945 348.953 540.885 348.516 540.891Z" fill="#56555A"/> -<path d="M376 542L380 546L376 550" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -<path d="M390 574H40C35.5817 574 32 577.582 32 582V606C32 610.418 35.5817 614 40 614H390C394.418 614 398 610.418 398 606V582C398 577.582 394.418 574 390 574Z" fill="white"/> -<path d="M56.4922 593.648H54.0703V592.016H56.4922V593.648ZM52.5781 590.891C52.5781 592.005 52.4635 593.06 52.2344 594.055C52.0104 595.044 51.659 595.938 51.1798 596.734C50.7058 597.526 50.1042 598.143 49.375 598.586L48.1562 597.102C48.8281 596.69 49.3802 596.156 49.8125 595.5C50.2448 594.839 50.5573 594.12 50.75 593.344C50.9479 592.568 51.0469 591.75 51.0469 590.891V588.438H52.5781V590.891ZM52.9767 590.797C52.9767 591.641 53.06 592.43 53.2267 593.164C53.3933 593.893 53.6694 594.57 54.0548 595.195C54.4402 595.815 54.9427 596.326 55.5625 596.727L54.4844 598.258C53.7604 597.82 53.1746 597.216 52.7267 596.445C52.2787 595.674 51.9583 594.818 51.7656 593.875C51.5729 592.927 51.4792 591.901 51.4844 590.797V588.438H52.9767V590.797ZM60.75 601.438H58.8359V587.203H60.75V601.438ZM57.7734 600.781H55.9062V587.422H57.7734V600.781ZM74.2345 598.062H72.25V587.234H74.2345V598.062ZM72.9922 592.375H70.3281V590.766H72.9922V592.375ZM72.9922 595.383H70.3281V593.797H72.9922V595.383ZM70.1797 590.289H62.2812V588.719H70.1797V590.289ZM66.3125 590.789C66.9531 590.789 67.5287 590.909 68.0392 591.148C68.5548 591.383 68.9557 591.714 69.2422 592.141C69.5339 592.568 69.6797 593.049 69.6797 593.586C69.6797 594.128 69.5339 594.612 69.2422 595.039C68.9557 595.461 68.5574 595.792 68.047 596.031C67.5366 596.266 66.9583 596.383 66.3125 596.383C65.6771 596.383 65.1069 596.266 64.6017 596.031C64.0965 595.792 63.698 595.461 63.4062 595.039C63.1199 594.612 62.9793 594.128 62.9845 593.586C62.9793 593.049 63.1199 592.57 63.4062 592.148C63.698 591.721 64.0965 591.388 64.6017 591.148C65.1069 590.909 65.6771 590.789 66.3125 590.789ZM66.3125 592.344C66.0208 592.349 65.7631 592.401 65.5392 592.5C65.3204 592.594 65.1484 592.734 65.0234 592.922C64.8984 593.109 64.8359 593.331 64.8359 593.586C64.8359 593.857 64.8984 594.086 65.0234 594.273C65.1484 594.461 65.3204 594.604 65.5392 594.703C65.7631 594.802 66.0208 594.852 66.3125 594.852C66.6042 594.852 66.862 594.802 67.0859 594.703C67.3099 594.604 67.4845 594.461 67.6095 594.273C67.7397 594.081 67.8047 593.852 67.8047 593.586C67.8047 593.331 67.7397 593.109 67.6095 592.922C67.4845 592.729 67.3099 592.586 67.0859 592.492C66.862 592.398 66.6042 592.349 66.3125 592.344ZM67.3281 589.688H65.3359V587.195H67.3281V589.688ZM74.5392 601.195H64.7656V599.586H74.5392V601.195ZM66.7812 600.328H64.7656V597.133H66.7812V600.328Z" fill="#56555A"/> -<path d="M289.047 598.969L292.906 594.906C293.411 594.365 293.797 593.927 294.062 593.594C294.333 593.26 294.539 592.943 294.68 592.641C294.82 592.333 294.891 592.01 294.891 591.672C294.891 591.292 294.792 590.958 294.594 590.672C294.396 590.38 294.125 590.154 293.781 589.992C293.443 589.831 293.062 589.75 292.641 589.75C292.198 589.75 291.81 589.839 291.477 590.016C291.148 590.193 290.893 590.443 290.711 590.766C290.529 591.083 290.438 591.453 290.438 591.875H289.109C289.104 591.219 289.255 590.638 289.562 590.133C289.875 589.628 290.305 589.234 290.852 588.953C291.398 588.672 292.01 588.531 292.688 588.531C293.359 588.531 293.961 588.669 294.492 588.945C295.029 589.221 295.448 589.599 295.75 590.078C296.052 590.557 296.203 591.089 296.203 591.672C296.198 592.104 296.117 592.518 295.961 592.914C295.81 593.305 295.549 593.74 295.18 594.219C294.81 594.698 294.286 595.286 293.609 595.984L291.016 598.656V598.75H296.406V600H289.062L289.047 598.969ZM302.359 600.156C301.615 600.156 300.948 600.031 300.359 599.781C299.776 599.531 299.312 599.18 298.969 598.727C298.625 598.268 298.443 597.745 298.422 597.156H299.844C299.87 597.51 299.995 597.818 300.219 598.078C300.448 598.339 300.745 598.542 301.109 598.688C301.479 598.833 301.891 598.906 302.344 598.906C302.839 598.906 303.281 598.823 303.672 598.656C304.068 598.49 304.375 598.255 304.594 597.953C304.812 597.651 304.922 597.307 304.922 596.922C304.917 596.51 304.807 596.146 304.594 595.828C304.385 595.505 304.073 595.255 303.656 595.078C303.24 594.901 302.745 594.812 302.172 594.812H301.25V593.578H302.172C302.625 593.578 303.029 593.497 303.383 593.336C303.742 593.174 304.018 592.948 304.211 592.656C304.404 592.359 304.5 592.021 304.5 591.641C304.5 591.266 304.414 590.935 304.242 590.648C304.07 590.362 303.826 590.141 303.508 589.984C303.19 589.828 302.818 589.75 302.391 589.75C301.984 589.755 301.604 589.831 301.25 589.977C300.896 590.117 300.607 590.323 300.383 590.594C300.159 590.859 300.036 591.172 300.016 591.531H298.656C298.677 590.948 298.859 590.427 299.203 589.969C299.547 589.51 300 589.156 300.562 588.906C301.125 588.656 301.74 588.531 302.406 588.531C303.104 588.531 303.716 588.669 304.242 588.945C304.768 589.221 305.169 589.591 305.445 590.055C305.727 590.518 305.865 591.021 305.859 591.562C305.865 591.984 305.789 592.37 305.633 592.719C305.482 593.062 305.26 593.354 304.969 593.594C304.677 593.833 304.333 594.01 303.938 594.125V594.203C304.422 594.276 304.841 594.435 305.195 594.68C305.555 594.924 305.828 595.24 306.016 595.625C306.203 596.01 306.297 596.443 306.297 596.922C306.297 597.531 306.128 598.083 305.789 598.578C305.451 599.068 304.979 599.453 304.375 599.734C303.776 600.016 303.104 600.156 302.359 600.156ZM308.531 603.203H307.375L308.234 598.953H309.75L308.531 603.203ZM315.516 600.156C314.734 600.156 314.039 600.021 313.43 599.75C312.82 599.479 312.346 599.104 312.008 598.625C311.669 598.146 311.5 597.604 311.5 597C311.5 596.521 311.602 596.073 311.805 595.656C312.008 595.24 312.284 594.898 312.633 594.633C312.982 594.362 313.37 594.193 313.797 594.125V594.062C313.427 593.979 313.102 593.815 312.82 593.57C312.544 593.326 312.328 593.026 312.172 592.672C312.016 592.318 311.938 591.938 311.938 591.531C311.938 590.964 312.091 590.453 312.398 590C312.706 589.542 313.13 589.182 313.672 588.922C314.219 588.661 314.833 588.531 315.516 588.531C316.193 588.531 316.805 588.661 317.352 588.922C317.898 589.182 318.326 589.542 318.633 590C318.945 590.453 319.104 590.964 319.109 591.531C319.104 591.938 319.021 592.318 318.859 592.672C318.703 593.026 318.484 593.326 318.203 593.57C317.922 593.815 317.599 593.979 317.234 594.062V594.125C317.656 594.193 318.042 594.362 318.391 594.633C318.745 594.898 319.023 595.24 319.227 595.656C319.435 596.073 319.542 596.521 319.547 597C319.542 597.604 319.367 598.146 319.023 598.625C318.685 599.104 318.208 599.479 317.594 599.75C316.984 600.021 316.292 600.156 315.516 600.156ZM315.516 598.922C316.047 598.922 316.51 598.836 316.906 598.664C317.302 598.492 317.607 598.258 317.82 597.961C318.034 597.664 318.141 597.318 318.141 596.922C318.141 596.51 318.029 596.141 317.805 595.812C317.581 595.479 317.268 595.219 316.867 595.031C316.466 594.844 316.016 594.75 315.516 594.75C315.016 594.75 314.568 594.844 314.172 595.031C313.776 595.219 313.464 595.479 313.234 595.812C313.01 596.141 312.901 596.51 312.906 596.922C312.901 597.318 313.003 597.664 313.211 597.961C313.424 598.258 313.727 598.492 314.117 598.664C314.513 598.836 314.979 598.922 315.516 598.922ZM315.516 593.562C315.943 593.562 316.326 593.479 316.664 593.312C317.003 593.146 317.266 592.919 317.453 592.633C317.641 592.346 317.734 592.016 317.734 591.641C317.734 591.266 317.643 590.935 317.461 590.648C317.279 590.362 317.018 590.141 316.68 589.984C316.341 589.828 315.953 589.75 315.516 589.75C315.073 589.75 314.685 589.828 314.352 589.984C314.023 590.141 313.766 590.362 313.578 590.648C313.391 590.935 313.297 591.266 313.297 591.641C313.297 592.016 313.393 592.346 313.586 592.633C313.779 592.919 314.042 593.146 314.375 593.312C314.708 593.479 315.089 593.562 315.516 593.562ZM325.125 600.156C324.453 600.156 323.841 600.026 323.289 599.766C322.742 599.505 322.305 599.148 321.977 598.695C321.654 598.242 321.479 597.729 321.453 597.156H322.812C322.844 597.49 322.966 597.789 323.18 598.055C323.393 598.32 323.669 598.531 324.008 598.688C324.352 598.844 324.724 598.922 325.125 598.922C325.609 598.922 326.042 598.812 326.422 598.594C326.807 598.375 327.109 598.076 327.328 597.695C327.547 597.315 327.656 596.891 327.656 596.422C327.656 595.938 327.544 595.503 327.32 595.117C327.096 594.727 326.784 594.419 326.383 594.195C325.982 593.971 325.531 593.859 325.031 593.859C324.536 593.849 324.112 593.927 323.758 594.094C323.404 594.255 323.125 594.516 322.922 594.875H321.562L322.359 588.688H328.484V589.938H323.531L323.109 593.25H323.219C323.479 593.052 323.789 592.893 324.148 592.773C324.513 592.654 324.891 592.594 325.281 592.594C325.99 592.594 326.63 592.755 327.203 593.078C327.776 593.401 328.224 593.854 328.547 594.438C328.87 595.016 329.031 595.667 329.031 596.391C329.031 597.109 328.862 597.755 328.523 598.328C328.185 598.901 327.719 599.349 327.125 599.672C326.536 599.995 325.87 600.156 325.125 600.156ZM334.688 600.156C333.854 600.156 333.143 599.93 332.555 599.477C331.966 599.023 331.516 598.362 331.203 597.492C330.891 596.622 330.734 595.573 330.734 594.344C330.734 593.13 330.891 592.089 331.203 591.219C331.516 590.344 331.966 589.677 332.555 589.219C333.148 588.76 333.859 588.531 334.688 588.531C335.51 588.531 336.219 588.76 336.812 589.219C337.406 589.677 337.859 590.344 338.172 591.219C338.484 592.089 338.641 593.13 338.641 594.344C338.641 595.573 338.487 596.622 338.18 597.492C337.872 598.362 337.422 599.023 336.828 599.477C336.234 599.93 335.521 600.156 334.688 600.156ZM334.688 598.906C335.229 598.906 335.695 598.729 336.086 598.375C336.477 598.021 336.771 597.503 336.969 596.82C337.167 596.138 337.266 595.312 337.266 594.344C337.266 593.375 337.164 592.547 336.961 591.859C336.758 591.172 336.464 590.648 336.078 590.289C335.693 589.93 335.229 589.75 334.688 589.75C334.146 589.75 333.682 589.93 333.297 590.289C332.911 590.648 332.615 591.172 332.406 591.859C332.198 592.547 332.094 593.375 332.094 594.344C332.094 595.312 332.198 596.138 332.406 596.82C332.615 597.503 332.909 598.021 333.289 598.375C333.674 598.729 334.141 598.906 334.688 598.906ZM349.266 597.453H348.031V594.359H349.266V597.453ZM355.484 597.938H354.25V587.391H355.484V597.938ZM355.828 600.969H345.953V599.938H355.828V600.969ZM347.188 600.234H345.953V596.906H347.188V600.234ZM343.953 593.828C345.812 593.818 347.458 593.789 348.891 593.742C350.323 593.69 351.693 593.583 353 593.422L353.078 594.312C351.729 594.526 350.315 594.667 348.836 594.734C347.357 594.802 345.786 594.833 344.125 594.828L343.953 593.828ZM354.578 596.5H351.375V595.609H354.578V596.5ZM348.516 587.953C349.188 587.953 349.784 588.052 350.305 588.25C350.831 588.448 351.237 588.732 351.523 589.102C351.81 589.471 351.953 589.896 351.953 590.375C351.953 590.865 351.81 591.289 351.523 591.648C351.237 592.008 350.833 592.286 350.312 592.484C349.792 592.682 349.193 592.781 348.516 592.781C347.833 592.781 347.232 592.682 346.711 592.484C346.195 592.286 345.794 592.008 345.508 591.648C345.221 591.289 345.078 590.865 345.078 590.375C345.078 589.896 345.221 589.471 345.508 589.102C345.794 588.732 346.198 588.448 346.719 588.25C347.24 588.052 347.839 587.953 348.516 587.953ZM348.516 588.891C348.068 588.885 347.672 588.945 347.328 589.07C346.984 589.19 346.716 589.365 346.523 589.594C346.336 589.823 346.245 590.083 346.25 590.375C346.245 590.672 346.336 590.935 346.523 591.164C346.716 591.388 346.984 591.562 347.328 591.688C347.672 591.812 348.068 591.875 348.516 591.875C348.953 591.875 349.344 591.812 349.688 591.688C350.031 591.562 350.299 591.388 350.492 591.164C350.685 590.935 350.781 590.672 350.781 590.375C350.781 590.083 350.685 589.823 350.492 589.594C350.299 589.365 350.031 589.19 349.688 589.07C349.344 588.945 348.953 588.885 348.516 588.891Z" fill="#56555A"/> -<path d="M376 590L380 594L376 598" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -<path d="M390 622H40C35.5817 622 32 625.582 32 630V654C32 658.418 35.5817 662 40 662H390C394.418 662 398 658.418 398 654V630C398 625.582 394.418 622 390 622Z" fill="white"/> -<path d="M53.6016 638.031C53.5964 638.938 53.4401 639.789 53.1328 640.586C52.8307 641.378 52.3724 642.07 51.7578 642.664C51.1432 643.258 50.3958 643.701 49.5156 643.992L48.4844 642.43C49.2448 642.19 49.8828 641.841 50.3984 641.383C50.9193 640.924 51.3047 640.409 51.5547 639.836C51.8099 639.258 51.9375 638.656 51.9375 638.031V636.789H53.6016V638.031ZM53.9609 638.031C53.9609 638.62 54.0833 639.185 54.3281 639.727C54.5781 640.268 54.9583 640.755 55.4688 641.188C55.9792 641.615 56.6068 641.94 57.3516 642.164L56.3438 643.734C55.474 643.453 54.7396 643.031 54.1406 642.469C53.5417 641.901 53.0885 641.237 52.7812 640.477C52.4792 639.716 52.3307 638.901 52.3359 638.031V636.789H53.9609V638.031ZM56.8281 637.828H49.0078V636.234H56.8281V637.828ZM60.3203 645.508H58.3281V635.234H60.3203V645.508ZM60.7109 649.195H50.7969V647.586H60.7109V649.195ZM52.8125 648.391H50.7969V644.57H52.8125V648.391ZM74.6406 638.609H62.8047V637.016H74.6406V638.609ZM75.2578 647.992H62.2578V646.383H75.2578V647.992ZM69.7031 647.008H67.7266V644.469H69.7031V647.008ZM68.7188 639.227C69.6979 639.227 70.5521 639.336 71.2812 639.555C72.0156 639.773 72.5781 640.094 72.9688 640.516C73.3646 640.932 73.5625 641.424 73.5625 641.992C73.5625 642.57 73.3646 643.07 72.9688 643.492C72.5781 643.909 72.0182 644.232 71.2891 644.461C70.5599 644.685 69.7031 644.799 68.7188 644.805C67.7188 644.799 66.8542 644.685 66.125 644.461C65.3958 644.232 64.8333 643.909 64.4375 643.492C64.0469 643.07 63.8542 642.57 63.8594 641.992C63.8542 641.419 64.0469 640.924 64.4375 640.508C64.8333 640.091 65.3958 639.773 66.125 639.555C66.8594 639.336 67.724 639.227 68.7188 639.227ZM68.7188 640.781C68.0938 640.786 67.5729 640.833 67.1562 640.922C66.7448 641.005 66.4323 641.138 66.2188 641.32C66.0052 641.497 65.901 641.721 65.9062 641.992C65.901 642.263 66.0052 642.49 66.2188 642.672C66.4323 642.849 66.7448 642.984 67.1562 643.078C67.5729 643.167 68.0938 643.211 68.7188 643.211C69.3281 643.211 69.8385 643.167 70.25 643.078C70.6667 642.984 70.9818 642.849 71.1953 642.672C71.4089 642.49 71.5156 642.263 71.5156 641.992C71.5156 641.721 71.4089 641.497 71.1953 641.32C70.9818 641.138 70.6667 641.005 70.25 640.922C69.8385 640.833 69.3281 640.786 68.7188 640.781ZM69.7031 638.008H67.7266V635.359H69.7031V638.008Z" fill="#56555A"/> -<path d="M289.047 646.969L292.906 642.906C293.411 642.365 293.797 641.927 294.062 641.594C294.333 641.26 294.539 640.943 294.68 640.641C294.82 640.333 294.891 640.01 294.891 639.672C294.891 639.292 294.792 638.958 294.594 638.672C294.396 638.38 294.125 638.154 293.781 637.992C293.443 637.831 293.062 637.75 292.641 637.75C292.198 637.75 291.81 637.839 291.477 638.016C291.148 638.193 290.893 638.443 290.711 638.766C290.529 639.083 290.438 639.453 290.438 639.875H289.109C289.104 639.219 289.255 638.638 289.562 638.133C289.875 637.628 290.305 637.234 290.852 636.953C291.398 636.672 292.01 636.531 292.688 636.531C293.359 636.531 293.961 636.669 294.492 636.945C295.029 637.221 295.448 637.599 295.75 638.078C296.052 638.557 296.203 639.089 296.203 639.672C296.198 640.104 296.117 640.518 295.961 640.914C295.81 641.305 295.549 641.74 295.18 642.219C294.81 642.698 294.286 643.286 293.609 643.984L291.016 646.656V646.75H296.406V648H289.062L289.047 646.969ZM302.359 648.156C301.615 648.156 300.948 648.031 300.359 647.781C299.776 647.531 299.312 647.18 298.969 646.727C298.625 646.268 298.443 645.745 298.422 645.156H299.844C299.87 645.51 299.995 645.818 300.219 646.078C300.448 646.339 300.745 646.542 301.109 646.688C301.479 646.833 301.891 646.906 302.344 646.906C302.839 646.906 303.281 646.823 303.672 646.656C304.068 646.49 304.375 646.255 304.594 645.953C304.812 645.651 304.922 645.307 304.922 644.922C304.917 644.51 304.807 644.146 304.594 643.828C304.385 643.505 304.073 643.255 303.656 643.078C303.24 642.901 302.745 642.812 302.172 642.812H301.25V641.578H302.172C302.625 641.578 303.029 641.497 303.383 641.336C303.742 641.174 304.018 640.948 304.211 640.656C304.404 640.359 304.5 640.021 304.5 639.641C304.5 639.266 304.414 638.935 304.242 638.648C304.07 638.362 303.826 638.141 303.508 637.984C303.19 637.828 302.818 637.75 302.391 637.75C301.984 637.755 301.604 637.831 301.25 637.977C300.896 638.117 300.607 638.323 300.383 638.594C300.159 638.859 300.036 639.172 300.016 639.531H298.656C298.677 638.948 298.859 638.427 299.203 637.969C299.547 637.51 300 637.156 300.562 636.906C301.125 636.656 301.74 636.531 302.406 636.531C303.104 636.531 303.716 636.669 304.242 636.945C304.768 637.221 305.169 637.591 305.445 638.055C305.727 638.518 305.865 639.021 305.859 639.562C305.865 639.984 305.789 640.37 305.633 640.719C305.482 641.062 305.26 641.354 304.969 641.594C304.677 641.833 304.333 642.01 303.938 642.125V642.203C304.422 642.276 304.841 642.435 305.195 642.68C305.555 642.924 305.828 643.24 306.016 643.625C306.203 644.01 306.297 644.443 306.297 644.922C306.297 645.531 306.128 646.083 305.789 646.578C305.451 647.068 304.979 647.453 304.375 647.734C303.776 648.016 303.104 648.156 302.359 648.156ZM308.531 651.203H307.375L308.234 646.953H309.75L308.531 651.203ZM315.516 648.156C314.734 648.156 314.039 648.021 313.43 647.75C312.82 647.479 312.346 647.104 312.008 646.625C311.669 646.146 311.5 645.604 311.5 645C311.5 644.521 311.602 644.073 311.805 643.656C312.008 643.24 312.284 642.898 312.633 642.633C312.982 642.362 313.37 642.193 313.797 642.125V642.062C313.427 641.979 313.102 641.815 312.82 641.57C312.544 641.326 312.328 641.026 312.172 640.672C312.016 640.318 311.938 639.938 311.938 639.531C311.938 638.964 312.091 638.453 312.398 638C312.706 637.542 313.13 637.182 313.672 636.922C314.219 636.661 314.833 636.531 315.516 636.531C316.193 636.531 316.805 636.661 317.352 636.922C317.898 637.182 318.326 637.542 318.633 638C318.945 638.453 319.104 638.964 319.109 639.531C319.104 639.938 319.021 640.318 318.859 640.672C318.703 641.026 318.484 641.326 318.203 641.57C317.922 641.815 317.599 641.979 317.234 642.062V642.125C317.656 642.193 318.042 642.362 318.391 642.633C318.745 642.898 319.023 643.24 319.227 643.656C319.435 644.073 319.542 644.521 319.547 645C319.542 645.604 319.367 646.146 319.023 646.625C318.685 647.104 318.208 647.479 317.594 647.75C316.984 648.021 316.292 648.156 315.516 648.156ZM315.516 646.922C316.047 646.922 316.51 646.836 316.906 646.664C317.302 646.492 317.607 646.258 317.82 645.961C318.034 645.664 318.141 645.318 318.141 644.922C318.141 644.51 318.029 644.141 317.805 643.812C317.581 643.479 317.268 643.219 316.867 643.031C316.466 642.844 316.016 642.75 315.516 642.75C315.016 642.75 314.568 642.844 314.172 643.031C313.776 643.219 313.464 643.479 313.234 643.812C313.01 644.141 312.901 644.51 312.906 644.922C312.901 645.318 313.003 645.664 313.211 645.961C313.424 646.258 313.727 646.492 314.117 646.664C314.513 646.836 314.979 646.922 315.516 646.922ZM315.516 641.562C315.943 641.562 316.326 641.479 316.664 641.312C317.003 641.146 317.266 640.919 317.453 640.633C317.641 640.346 317.734 640.016 317.734 639.641C317.734 639.266 317.643 638.935 317.461 638.648C317.279 638.362 317.018 638.141 316.68 637.984C316.341 637.828 315.953 637.75 315.516 637.75C315.073 637.75 314.685 637.828 314.352 637.984C314.023 638.141 313.766 638.362 313.578 638.648C313.391 638.935 313.297 639.266 313.297 639.641C313.297 640.016 313.393 640.346 313.586 640.633C313.779 640.919 314.042 641.146 314.375 641.312C314.708 641.479 315.089 641.562 315.516 641.562ZM325.125 648.156C324.453 648.156 323.841 648.026 323.289 647.766C322.742 647.505 322.305 647.148 321.977 646.695C321.654 646.242 321.479 645.729 321.453 645.156H322.812C322.844 645.49 322.966 645.789 323.18 646.055C323.393 646.32 323.669 646.531 324.008 646.688C324.352 646.844 324.724 646.922 325.125 646.922C325.609 646.922 326.042 646.812 326.422 646.594C326.807 646.375 327.109 646.076 327.328 645.695C327.547 645.315 327.656 644.891 327.656 644.422C327.656 643.938 327.544 643.503 327.32 643.117C327.096 642.727 326.784 642.419 326.383 642.195C325.982 641.971 325.531 641.859 325.031 641.859C324.536 641.849 324.112 641.927 323.758 642.094C323.404 642.255 323.125 642.516 322.922 642.875H321.562L322.359 636.688H328.484V637.938H323.531L323.109 641.25H323.219C323.479 641.052 323.789 640.893 324.148 640.773C324.513 640.654 324.891 640.594 325.281 640.594C325.99 640.594 326.63 640.755 327.203 641.078C327.776 641.401 328.224 641.854 328.547 642.438C328.87 643.016 329.031 643.667 329.031 644.391C329.031 645.109 328.862 645.755 328.523 646.328C328.185 646.901 327.719 647.349 327.125 647.672C326.536 647.995 325.87 648.156 325.125 648.156ZM334.688 648.156C333.854 648.156 333.143 647.93 332.555 647.477C331.966 647.023 331.516 646.362 331.203 645.492C330.891 644.622 330.734 643.573 330.734 642.344C330.734 641.13 330.891 640.089 331.203 639.219C331.516 638.344 331.966 637.677 332.555 637.219C333.148 636.76 333.859 636.531 334.688 636.531C335.51 636.531 336.219 636.76 336.812 637.219C337.406 637.677 337.859 638.344 338.172 639.219C338.484 640.089 338.641 641.13 338.641 642.344C338.641 643.573 338.487 644.622 338.18 645.492C337.872 646.362 337.422 647.023 336.828 647.477C336.234 647.93 335.521 648.156 334.688 648.156ZM334.688 646.906C335.229 646.906 335.695 646.729 336.086 646.375C336.477 646.021 336.771 645.503 336.969 644.82C337.167 644.138 337.266 643.312 337.266 642.344C337.266 641.375 337.164 640.547 336.961 639.859C336.758 639.172 336.464 638.648 336.078 638.289C335.693 637.93 335.229 637.75 334.688 637.75C334.146 637.75 333.682 637.93 333.297 638.289C332.911 638.648 332.615 639.172 332.406 639.859C332.198 640.547 332.094 641.375 332.094 642.344C332.094 643.312 332.198 644.138 332.406 644.82C332.615 645.503 332.909 646.021 333.289 646.375C333.674 646.729 334.141 646.906 334.688 646.906ZM349.266 645.453H348.031V642.359H349.266V645.453ZM355.484 645.938H354.25V635.391H355.484V645.938ZM355.828 648.969H345.953V647.938H355.828V648.969ZM347.188 648.234H345.953V644.906H347.188V648.234ZM343.953 641.828C345.812 641.818 347.458 641.789 348.891 641.742C350.323 641.69 351.693 641.583 353 641.422L353.078 642.312C351.729 642.526 350.315 642.667 348.836 642.734C347.357 642.802 345.786 642.833 344.125 642.828L343.953 641.828ZM354.578 644.5H351.375V643.609H354.578V644.5ZM348.516 635.953C349.188 635.953 349.784 636.052 350.305 636.25C350.831 636.448 351.237 636.732 351.523 637.102C351.81 637.471 351.953 637.896 351.953 638.375C351.953 638.865 351.81 639.289 351.523 639.648C351.237 640.008 350.833 640.286 350.312 640.484C349.792 640.682 349.193 640.781 348.516 640.781C347.833 640.781 347.232 640.682 346.711 640.484C346.195 640.286 345.794 640.008 345.508 639.648C345.221 639.289 345.078 638.865 345.078 638.375C345.078 637.896 345.221 637.471 345.508 637.102C345.794 636.732 346.198 636.448 346.719 636.25C347.24 636.052 347.839 635.953 348.516 635.953ZM348.516 636.891C348.068 636.885 347.672 636.945 347.328 637.07C346.984 637.19 346.716 637.365 346.523 637.594C346.336 637.823 346.245 638.083 346.25 638.375C346.245 638.672 346.336 638.935 346.523 639.164C346.716 639.388 346.984 639.562 347.328 639.688C347.672 639.812 348.068 639.875 348.516 639.875C348.953 639.875 349.344 639.812 349.688 639.688C350.031 639.562 350.299 639.388 350.492 639.164C350.685 638.935 350.781 638.672 350.781 638.375C350.781 638.083 350.685 637.823 350.492 637.594C350.299 637.365 350.031 637.19 349.688 637.07C349.344 636.945 348.953 636.885 348.516 636.891Z" fill="#56555A"/> -<path d="M376 638L380 642L376 646" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -<path d="M390 670H40C35.5817 670 32 673.582 32 678V702C32 706.418 35.5817 710 40 710H390C394.418 710 398 706.418 398 702V678C398 673.582 394.418 670 390 670Z" fill="white"/> -<path d="M49.8984 692.523C51.0703 692.518 52.0183 692.497 52.7423 692.461C53.4662 692.424 54.2083 692.352 54.9688 692.242L55.1173 693.875C54.3308 694 53.5522 694.083 52.7812 694.125C52.0156 694.167 51.0547 694.185 49.8984 694.18H48.9062V692.523H49.8984ZM54.6953 686.273H50.8048V693.195H48.9062V684.711H54.6953V686.273ZM54.4219 689.961H50.2656V688.43H54.4219V689.961ZM60.75 697.438H58.8359V683.203H60.75V697.438ZM59.4688 690.328H57.0625V688.727H59.4688V690.328ZM57.6172 696.781H55.7267V683.422H57.6172V696.781ZM75.2267 692.766H62.2579V691.195H75.2267V692.766ZM69.8984 694.523H67.9297V692.344H69.8984V694.523ZM73.8125 697.195H63.7579V695.617H73.8125V697.195ZM65.7579 696.602H63.7579V693.641H65.7579V696.602ZM74.5392 685.906H62.8672V684.414H74.5392V685.906ZM68.7345 686.297C70.2605 686.297 71.4375 686.482 72.2656 686.852C73.0938 687.216 73.5079 687.747 73.5079 688.445C73.5079 688.919 73.3229 689.32 72.9531 689.648C72.5833 689.971 72.0392 690.219 71.3204 690.391C70.6069 690.562 69.7449 690.648 68.7345 690.648C67.7189 690.648 66.8542 690.562 66.1406 690.391C65.4271 690.219 64.8829 689.971 64.5079 689.648C64.1329 689.32 63.9454 688.919 63.9454 688.445C63.9454 687.747 64.3594 687.216 65.1875 686.852C66.0208 686.482 67.2032 686.297 68.7345 686.297ZM68.7345 687.688C68.0834 687.682 67.5574 687.706 67.1562 687.758C66.7553 687.81 66.4583 687.893 66.2656 688.008C66.0729 688.122 65.9793 688.268 65.9845 688.445C65.9793 688.633 66.0729 688.784 66.2656 688.898C66.4583 689.008 66.7526 689.091 67.1484 689.148C67.5495 689.201 68.0782 689.227 68.7345 689.227C69.3803 689.227 69.9011 689.201 70.297 689.148C70.6928 689.091 70.987 689.008 71.1797 688.898C71.3776 688.784 71.4767 688.633 71.4767 688.445C71.4767 688.268 71.3776 688.122 71.1797 688.008C70.987 687.893 70.6928 687.81 70.297 687.758C69.9011 687.706 69.3803 687.682 68.7345 687.688ZM69.7267 685.359H67.7267V683.141H69.7267V685.359Z" fill="#56555A"/> -<path d="M289.047 694.969L292.906 690.906C293.411 690.365 293.797 689.927 294.062 689.594C294.333 689.26 294.539 688.943 294.68 688.641C294.82 688.333 294.891 688.01 294.891 687.672C294.891 687.292 294.792 686.958 294.594 686.672C294.396 686.38 294.125 686.154 293.781 685.992C293.443 685.831 293.062 685.75 292.641 685.75C292.198 685.75 291.81 685.839 291.477 686.016C291.148 686.193 290.893 686.443 290.711 686.766C290.529 687.083 290.438 687.453 290.438 687.875H289.109C289.104 687.219 289.255 686.638 289.562 686.133C289.875 685.628 290.305 685.234 290.852 684.953C291.398 684.672 292.01 684.531 292.688 684.531C293.359 684.531 293.961 684.669 294.492 684.945C295.029 685.221 295.448 685.599 295.75 686.078C296.052 686.557 296.203 687.089 296.203 687.672C296.198 688.104 296.117 688.518 295.961 688.914C295.81 689.305 295.549 689.74 295.18 690.219C294.81 690.698 294.286 691.286 293.609 691.984L291.016 694.656V694.75H296.406V696H289.062L289.047 694.969ZM302.359 696.156C301.615 696.156 300.948 696.031 300.359 695.781C299.776 695.531 299.312 695.18 298.969 694.727C298.625 694.268 298.443 693.745 298.422 693.156H299.844C299.87 693.51 299.995 693.818 300.219 694.078C300.448 694.339 300.745 694.542 301.109 694.688C301.479 694.833 301.891 694.906 302.344 694.906C302.839 694.906 303.281 694.823 303.672 694.656C304.068 694.49 304.375 694.255 304.594 693.953C304.812 693.651 304.922 693.307 304.922 692.922C304.917 692.51 304.807 692.146 304.594 691.828C304.385 691.505 304.073 691.255 303.656 691.078C303.24 690.901 302.745 690.812 302.172 690.812H301.25V689.578H302.172C302.625 689.578 303.029 689.497 303.383 689.336C303.742 689.174 304.018 688.948 304.211 688.656C304.404 688.359 304.5 688.021 304.5 687.641C304.5 687.266 304.414 686.935 304.242 686.648C304.07 686.362 303.826 686.141 303.508 685.984C303.19 685.828 302.818 685.75 302.391 685.75C301.984 685.755 301.604 685.831 301.25 685.977C300.896 686.117 300.607 686.323 300.383 686.594C300.159 686.859 300.036 687.172 300.016 687.531H298.656C298.677 686.948 298.859 686.427 299.203 685.969C299.547 685.51 300 685.156 300.562 684.906C301.125 684.656 301.74 684.531 302.406 684.531C303.104 684.531 303.716 684.669 304.242 684.945C304.768 685.221 305.169 685.591 305.445 686.055C305.727 686.518 305.865 687.021 305.859 687.562C305.865 687.984 305.789 688.37 305.633 688.719C305.482 689.062 305.26 689.354 304.969 689.594C304.677 689.833 304.333 690.01 303.938 690.125V690.203C304.422 690.276 304.841 690.435 305.195 690.68C305.555 690.924 305.828 691.24 306.016 691.625C306.203 692.01 306.297 692.443 306.297 692.922C306.297 693.531 306.128 694.083 305.789 694.578C305.451 695.068 304.979 695.453 304.375 695.734C303.776 696.016 303.104 696.156 302.359 696.156ZM308.531 699.203H307.375L308.234 694.953H309.75L308.531 699.203ZM315.516 696.156C314.734 696.156 314.039 696.021 313.43 695.75C312.82 695.479 312.346 695.104 312.008 694.625C311.669 694.146 311.5 693.604 311.5 693C311.5 692.521 311.602 692.073 311.805 691.656C312.008 691.24 312.284 690.898 312.633 690.633C312.982 690.362 313.37 690.193 313.797 690.125V690.062C313.427 689.979 313.102 689.815 312.82 689.57C312.544 689.326 312.328 689.026 312.172 688.672C312.016 688.318 311.938 687.938 311.938 687.531C311.938 686.964 312.091 686.453 312.398 686C312.706 685.542 313.13 685.182 313.672 684.922C314.219 684.661 314.833 684.531 315.516 684.531C316.193 684.531 316.805 684.661 317.352 684.922C317.898 685.182 318.326 685.542 318.633 686C318.945 686.453 319.104 686.964 319.109 687.531C319.104 687.938 319.021 688.318 318.859 688.672C318.703 689.026 318.484 689.326 318.203 689.57C317.922 689.815 317.599 689.979 317.234 690.062V690.125C317.656 690.193 318.042 690.362 318.391 690.633C318.745 690.898 319.023 691.24 319.227 691.656C319.435 692.073 319.542 692.521 319.547 693C319.542 693.604 319.367 694.146 319.023 694.625C318.685 695.104 318.208 695.479 317.594 695.75C316.984 696.021 316.292 696.156 315.516 696.156ZM315.516 694.922C316.047 694.922 316.51 694.836 316.906 694.664C317.302 694.492 317.607 694.258 317.82 693.961C318.034 693.664 318.141 693.318 318.141 692.922C318.141 692.51 318.029 692.141 317.805 691.812C317.581 691.479 317.268 691.219 316.867 691.031C316.466 690.844 316.016 690.75 315.516 690.75C315.016 690.75 314.568 690.844 314.172 691.031C313.776 691.219 313.464 691.479 313.234 691.812C313.01 692.141 312.901 692.51 312.906 692.922C312.901 693.318 313.003 693.664 313.211 693.961C313.424 694.258 313.727 694.492 314.117 694.664C314.513 694.836 314.979 694.922 315.516 694.922ZM315.516 689.562C315.943 689.562 316.326 689.479 316.664 689.312C317.003 689.146 317.266 688.919 317.453 688.633C317.641 688.346 317.734 688.016 317.734 687.641C317.734 687.266 317.643 686.935 317.461 686.648C317.279 686.362 317.018 686.141 316.68 685.984C316.341 685.828 315.953 685.75 315.516 685.75C315.073 685.75 314.685 685.828 314.352 685.984C314.023 686.141 313.766 686.362 313.578 686.648C313.391 686.935 313.297 687.266 313.297 687.641C313.297 688.016 313.393 688.346 313.586 688.633C313.779 688.919 314.042 689.146 314.375 689.312C314.708 689.479 315.089 689.562 315.516 689.562ZM325.125 696.156C324.453 696.156 323.841 696.026 323.289 695.766C322.742 695.505 322.305 695.148 321.977 694.695C321.654 694.242 321.479 693.729 321.453 693.156H322.812C322.844 693.49 322.966 693.789 323.18 694.055C323.393 694.32 323.669 694.531 324.008 694.688C324.352 694.844 324.724 694.922 325.125 694.922C325.609 694.922 326.042 694.812 326.422 694.594C326.807 694.375 327.109 694.076 327.328 693.695C327.547 693.315 327.656 692.891 327.656 692.422C327.656 691.938 327.544 691.503 327.32 691.117C327.096 690.727 326.784 690.419 326.383 690.195C325.982 689.971 325.531 689.859 325.031 689.859C324.536 689.849 324.112 689.927 323.758 690.094C323.404 690.255 323.125 690.516 322.922 690.875H321.562L322.359 684.688H328.484V685.938H323.531L323.109 689.25H323.219C323.479 689.052 323.789 688.893 324.148 688.773C324.513 688.654 324.891 688.594 325.281 688.594C325.99 688.594 326.63 688.755 327.203 689.078C327.776 689.401 328.224 689.854 328.547 690.438C328.87 691.016 329.031 691.667 329.031 692.391C329.031 693.109 328.862 693.755 328.523 694.328C328.185 694.901 327.719 695.349 327.125 695.672C326.536 695.995 325.87 696.156 325.125 696.156ZM334.688 696.156C333.854 696.156 333.143 695.93 332.555 695.477C331.966 695.023 331.516 694.362 331.203 693.492C330.891 692.622 330.734 691.573 330.734 690.344C330.734 689.13 330.891 688.089 331.203 687.219C331.516 686.344 331.966 685.677 332.555 685.219C333.148 684.76 333.859 684.531 334.688 684.531C335.51 684.531 336.219 684.76 336.812 685.219C337.406 685.677 337.859 686.344 338.172 687.219C338.484 688.089 338.641 689.13 338.641 690.344C338.641 691.573 338.487 692.622 338.18 693.492C337.872 694.362 337.422 695.023 336.828 695.477C336.234 695.93 335.521 696.156 334.688 696.156ZM334.688 694.906C335.229 694.906 335.695 694.729 336.086 694.375C336.477 694.021 336.771 693.503 336.969 692.82C337.167 692.138 337.266 691.312 337.266 690.344C337.266 689.375 337.164 688.547 336.961 687.859C336.758 687.172 336.464 686.648 336.078 686.289C335.693 685.93 335.229 685.75 334.688 685.75C334.146 685.75 333.682 685.93 333.297 686.289C332.911 686.648 332.615 687.172 332.406 687.859C332.198 688.547 332.094 689.375 332.094 690.344C332.094 691.312 332.198 692.138 332.406 692.82C332.615 693.503 332.909 694.021 333.289 694.375C333.674 694.729 334.141 694.906 334.688 694.906ZM349.266 693.453H348.031V690.359H349.266V693.453ZM355.484 693.938H354.25V683.391H355.484V693.938ZM355.828 696.969H345.953V695.938H355.828V696.969ZM347.188 696.234H345.953V692.906H347.188V696.234ZM343.953 689.828C345.812 689.818 347.458 689.789 348.891 689.742C350.323 689.69 351.693 689.583 353 689.422L353.078 690.312C351.729 690.526 350.315 690.667 348.836 690.734C347.357 690.802 345.786 690.833 344.125 690.828L343.953 689.828ZM354.578 692.5H351.375V691.609H354.578V692.5ZM348.516 683.953C349.188 683.953 349.784 684.052 350.305 684.25C350.831 684.448 351.237 684.732 351.523 685.102C351.81 685.471 351.953 685.896 351.953 686.375C351.953 686.865 351.81 687.289 351.523 687.648C351.237 688.008 350.833 688.286 350.312 688.484C349.792 688.682 349.193 688.781 348.516 688.781C347.833 688.781 347.232 688.682 346.711 688.484C346.195 688.286 345.794 688.008 345.508 687.648C345.221 687.289 345.078 686.865 345.078 686.375C345.078 685.896 345.221 685.471 345.508 685.102C345.794 684.732 346.198 684.448 346.719 684.25C347.24 684.052 347.839 683.953 348.516 683.953ZM348.516 684.891C348.068 684.885 347.672 684.945 347.328 685.07C346.984 685.19 346.716 685.365 346.523 685.594C346.336 685.823 346.245 686.083 346.25 686.375C346.245 686.672 346.336 686.935 346.523 687.164C346.716 687.388 346.984 687.562 347.328 687.688C347.672 687.812 348.068 687.875 348.516 687.875C348.953 687.875 349.344 687.812 349.688 687.688C350.031 687.562 350.299 687.388 350.492 687.164C350.685 686.935 350.781 686.672 350.781 686.375C350.781 686.083 350.685 685.823 350.492 685.594C350.299 685.365 350.031 685.19 349.688 685.07C349.344 684.945 348.953 684.885 348.516 684.891Z" fill="#56555A"/> -<path d="M376 686L380 690L376 694" stroke="#B2B1B6" stroke-width="1.5" stroke-linecap="round"/> -</g> -</g> -<mask id="mask3_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="426" y="221" width="3" height="105"> -<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="white"/> -</mask> -<g mask="url(#mask3_1837_11068)"> -<path d="M426.288 325.939H428.762V221.428H426.288V325.939Z" fill="url(#paint0_linear_1837_11068)"/> -</g> -<mask id="mask4_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="428" y="221" width="2" height="105"> -<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="white"/> -</mask> -<g mask="url(#mask4_1837_11068)"> -<path d="M428.763 325.942V221.455L430 222.812C429.374 233.937 429.417 313.485 430 324.586L428.763 325.942Z" fill="url(#paint1_linear_1837_11068)"/> -</g> -<mask id="mask5_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="3" height="67"> -<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="white"/> -</mask> -<g mask="url(#mask5_1837_11068)"> -<path d="M2.11943 265.633H0.706543V199.429H2.11943V265.633Z" fill="url(#paint2_linear_1837_11068)"/> -</g> -<mask id="mask6_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="199" width="1" height="67"> -<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.353 0 200.307L0.706443 199.447V265.633V265.637Z" fill="white"/> -</mask> -<g mask="url(#mask6_1837_11068)"> -<path d="M0.706443 265.637L0 264.777C0.333038 257.745 0.357259 207.353 0 200.307L0.706443 199.447V265.633V265.637Z" fill="url(#paint3_linear_1837_11068)"/> -</g> -<mask id="mask7_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="199" width="2" height="67"> -<path d="M2.11914 265.652H3.63295V199.447H2.11914V265.652Z" fill="white"/> -</mask> -<g mask="url(#mask7_1837_11068)"> -<path d="M2.11914 265.652H3.63295V199.447H2.11914V265.652Z" fill="url(#paint4_linear_1837_11068)"/> -</g> -<mask id="mask8_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="3" height="67"> -<path d="M2.11943 348.925H0.706543V282.721H2.11943V348.925Z" fill="white"/> -</mask> -<g mask="url(#mask8_1837_11068)"> -<path d="M2.11943 348.925H0.706543V282.721H2.11943V348.925Z" fill="url(#paint5_linear_1837_11068)"/> -</g> -<mask id="mask9_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="282" width="1" height="67"> -<path d="M0.706443 348.929L0 348.069C0.333038 341.037 0.357259 290.645 0 283.599L0.706443 282.739V348.925V348.929Z" fill="white"/> -</mask> -<g mask="url(#mask9_1837_11068)"> -<path d="M0.706443 348.929L0 348.069C0.333038 341.037 0.357259 290.645 0 283.599L0.706443 282.739V348.925V348.929Z" fill="url(#paint6_linear_1837_11068)"/> -</g> -<mask id="mask10_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="282" width="2" height="67"> -<path d="M2.11914 348.944H3.63295V282.739H2.11914V348.944Z" fill="white"/> -</mask> -<g mask="url(#mask10_1837_11068)"> -<path d="M2.11914 348.944H3.63295V282.739H2.11914V348.944Z" fill="url(#paint7_linear_1837_11068)"/> -</g> -<mask id="mask11_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="3" height="35"> -<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="white"/> -</mask> -<g mask="url(#mask11_1837_11068)"> -<path d="M2.11943 170.858H0.706543V136.878H2.11943V170.858Z" fill="url(#paint8_linear_1837_11068)"/> -</g> -<mask id="mask12_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="136" width="1" height="35"> -<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="white"/> -</mask> -<g mask="url(#mask12_1837_11068)"> -<path d="M0.706443 170.862L0 170.049C0.333038 163.398 0.357259 144.373 0 137.706L0.706443 136.895V170.858V170.862Z" fill="url(#paint9_linear_1837_11068)"/> -</g> -<mask id="mask13_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="136" width="2" height="35"> -<path d="M2.11914 170.879H3.63295V136.896H2.11914V170.879Z" fill="white"/> -</mask> -<g mask="url(#mask13_1837_11068)"> -<path d="M2.11914 170.879H3.63295V136.896H2.11914V170.879Z" fill="url(#paint10_linear_1837_11068)"/> -</g> -<path d="M246.886 60.54H179.37C171.773 60.54 165.615 54.3819 165.615 46.7846C165.615 39.1873 171.773 33.0291 179.37 33.0291H246.886C254.483 33.0291 260.641 39.1873 260.641 46.7846C260.641 54.3819 254.483 60.54 246.886 60.54ZM243.083 40.7798C239.767 40.7798 237.079 43.4683 237.079 46.7846C237.079 50.1029 239.767 52.7894 243.083 52.7894C246.4 52.7894 249.088 50.1029 249.088 46.7846C249.088 43.4683 246.4 40.7798 243.083 40.7798Z" fill="#1D1D1B"/> -<mask id="mask14_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="40" width="13" height="13"> -<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="white"/> -</mask> -<g mask="url(#mask14_1837_11068)"> -<path d="M243.083 52.7891C239.767 52.7891 237.079 50.1026 237.079 46.7843C237.079 43.468 239.767 40.7795 243.083 40.7795C246.4 40.7795 249.088 43.468 249.088 46.7843C249.088 50.1026 246.4 52.7891 243.083 52.7891ZM243.061 41.1792C242.502 41.1792 241.941 41.2619 241.398 41.4315C240.524 41.708 239.745 42.1883 239.115 42.8201C238.75 43.1834 238.437 43.5992 238.183 44.0533C237.42 45.4218 237.295 47.0345 237.747 48.4777C238.011 49.3214 238.473 50.1065 239.117 50.7524C239.747 51.3801 240.526 51.8626 241.4 52.1371C241.943 52.3087 242.504 52.3914 243.063 52.3914C243.717 52.3914 244.367 52.2763 244.981 52.0563C245.75 51.7818 246.462 51.3418 247.052 50.7524C247.697 50.1065 248.156 49.3214 248.42 48.4777C248.874 47.0345 248.749 45.4218 247.986 44.0533C247.734 43.5992 247.419 43.1834 247.054 42.8201C246.464 42.2287 245.752 41.7887 244.983 41.5122C244.367 41.2922 243.715 41.1792 243.061 41.1792Z" fill="url(#paint11_linear_1837_11068)"/> -</g> -<mask id="mask15_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="237" y="41" width="12" height="12"> -<path d="M243.063 52.3916C242.504 52.3916 241.943 52.3089 241.4 52.1373C240.526 51.8628 239.747 51.3804 239.117 50.7526C238.473 50.1067 238.011 49.3216 237.746 48.4779C237.294 47.0347 237.419 45.422 238.182 44.0535C238.437 43.5994 238.75 43.1836 239.115 42.8203C239.745 42.1886 240.524 41.7082 241.398 41.4317C241.941 41.2621 242.502 41.1794 243.061 41.1794C243.715 41.1794 244.367 41.2924 244.982 41.5124C245.751 41.7889 246.464 42.2289 247.053 42.8203C247.419 43.1836 247.734 43.5994 247.986 44.0535C248.749 45.422 248.874 47.0347 248.42 48.4779C248.155 49.3216 247.697 50.1067 247.051 50.7526C246.462 51.342 245.749 51.782 244.98 52.0565C244.367 52.2765 243.717 52.3916 243.063 52.3916ZM243.083 43.3532C241.19 43.3532 239.654 44.8892 239.654 46.7845C239.654 48.6798 241.19 50.2158 243.083 50.2158C244.978 50.2158 246.516 48.6798 246.516 46.7845C246.516 44.8892 244.978 43.3532 243.083 43.3532Z" fill="white"/> -</mask> -<g mask="url(#mask15_1837_11068)"> -<rect x="235.513" y="39.4111" width="14.7748" height="14.7748" fill="url(#pattern0_1837_11068)"/> -</g> -<mask id="mask16_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="239" y="43" width="8" height="8"> -<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="white"/> -</mask> -<g mask="url(#mask16_1837_11068)"> -<path d="M243.083 50.2158C241.19 50.2158 239.654 48.6798 239.654 46.7845C239.654 44.8892 241.19 43.3532 243.083 43.3532C244.978 43.3532 246.516 44.8892 246.516 46.7845C246.516 48.6798 244.978 50.2158 243.083 50.2158ZM240.08 46.7886C240.08 48.4457 241.416 49.7899 243.081 49.7899C243.612 49.7899 244.112 49.6507 244.546 49.4085C244.607 49.4185 244.668 49.4266 244.732 49.4266C245.324 49.4266 245.804 48.9442 245.804 48.3528C245.804 48.2701 245.794 48.1893 245.778 48.1146C245.973 47.715 246.084 47.2629 246.084 46.7886C246.084 45.1234 244.74 43.7831 243.081 43.7831C241.416 43.7831 240.08 45.1234 240.08 46.7886Z" fill="url(#paint12_linear_1837_11068)"/> -</g> -<mask id="mask17_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="240" y="43" width="7" height="7"> -<path d="M243.081 49.79C241.416 49.79 240.08 48.4459 240.08 46.7887C240.08 45.1236 241.416 43.7833 243.081 43.7833C244.74 43.7833 246.084 45.1236 246.084 46.7887C246.084 47.2631 245.973 47.7152 245.778 48.1148C245.669 47.6364 245.241 47.2812 244.732 47.2812C244.139 47.2812 243.66 47.7616 243.66 48.353C243.66 48.8818 244.042 49.3218 244.546 49.4086C244.112 49.6508 243.612 49.79 243.081 49.79Z" fill="white"/> -</mask> -<g mask="url(#mask17_1837_11068)"> -<rect x="238.337" y="42.2383" width="8.92141" height="8.92141" fill="url(#pattern1_1837_11068)"/> -</g> -<mask id="mask18_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="244" y="48" width="2" height="2"> -<path d="M244.732 49.4258C244.668 49.4258 244.607 49.4177 244.546 49.4076C245.077 49.1109 245.507 48.6588 245.778 48.1138C245.794 48.1885 245.804 48.2693 245.804 48.352C245.804 48.9434 245.324 49.4258 244.732 49.4258Z" fill="white"/> -</mask> -<g mask="url(#mask18_1837_11068)"> -<rect x="243.182" y="46.2734" width="4.07723" height="4.88459" fill="url(#pattern2_1837_11068)"/> -</g> -<mask id="mask19_1837_11068" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="243" y="47" width="3" height="3"> -<path d="M244.547 49.4082C244.042 49.3214 243.661 48.8814 243.661 48.3526C243.661 47.7612 244.139 47.2808 244.732 47.2808C245.241 47.2808 245.669 47.636 245.778 48.1144C245.507 48.6593 245.078 49.1115 244.547 49.4082Z" fill="white"/> -</mask> -<g mask="url(#mask19_1837_11068)"> -<rect x="242.173" y="46.2734" width="5.08643" height="4.88459" fill="url(#pattern3_1837_11068)"/> -</g> -<defs> -<pattern id="pattern0_1837_11068" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image0_1837_11068" transform="scale(0.0666667)"/> -</pattern> -<pattern id="pattern1_1837_11068" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image1_1837_11068" transform="scale(0.111111)"/> -</pattern> -<pattern id="pattern2_1837_11068" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image2_1837_11068" transform="scale(0.25 0.2)"/> -</pattern> -<pattern id="pattern3_1837_11068" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image3_1837_11068" transform="scale(0.2)"/> -</pattern> -<linearGradient id="paint0_linear_1837_11068" x1="427.525" y1="221.428" x2="427.525" y2="325.938" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2B1D2A"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2B1D2A"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint1_linear_1837_11068" x1="429.38" y1="221.455" x2="429.38" y2="325.943" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint2_linear_1837_11068" x1="1.41299" y1="199.429" x2="1.41299" y2="265.633" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint3_linear_1837_11068" x1="0.353221" y1="199.447" x2="0.353221" y2="265.637" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint4_linear_1837_11068" x1="2.87604" y1="265.652" x2="2.87604" y2="199.445" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint5_linear_1837_11068" x1="1.41299" y1="282.721" x2="1.41299" y2="348.925" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint6_linear_1837_11068" x1="0.353221" y1="282.739" x2="0.353221" y2="348.929" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint7_linear_1837_11068" x1="2.87604" y1="348.944" x2="2.87604" y2="282.737" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint8_linear_1837_11068" x1="1.41299" y1="136.878" x2="1.41299" y2="170.859" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0185053" stop-color="#896E80"/> -<stop offset="0.0381953" stop-color="#5E3B5B"/> -<stop offset="0.0820552" stop-color="#2D1E2C"/> -<stop offset="0.105304" stop-color="#704A6A"/> -<stop offset="0.904875" stop-color="#615060"/> -<stop offset="0.939094" stop-color="#2D1E2C"/> -<stop offset="0.96458" stop-color="#5E3B5B"/> -<stop offset="0.98292" stop-color="#845675"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint9_linear_1837_11068" x1="0.353222" y1="136.895" x2="0.353222" y2="170.862" gradientUnits="userSpaceOnUse"> -<stop stop-color="#676067"/> -<stop offset="0.0640242" stop-color="#654E63"/> -<stop offset="0.186012" stop-color="#786F77"/> -<stop offset="0.806376" stop-color="#786F77"/> -<stop offset="0.919115" stop-color="#654E63"/> -<stop offset="1" stop-color="#676067"/> -</linearGradient> -<linearGradient id="paint10_linear_1837_11068" x1="2.87604" y1="170.879" x2="2.87604" y2="136.895" gradientUnits="userSpaceOnUse"> -<stop stop-color="#68595F"/> -<stop offset="0.0530612" stop-color="#2D1E2C"/> -<stop offset="0.518367" stop-color="#5E3B5B"/> -<stop offset="0.96458" stop-color="#2D1E2C"/> -<stop offset="1" stop-color="#5B4A5C"/> -</linearGradient> -<linearGradient id="paint11_linear_1837_11068" x1="243.083" y1="52.4197" x2="243.083" y2="40.5892" gradientUnits="userSpaceOnUse"> -<stop stop-color="#666666"/> -<stop offset="1" stop-color="#010104"/> -</linearGradient> -<linearGradient id="paint12_linear_1837_11068" x1="243.083" y1="43.5652" x2="243.083" y2="50.325" gradientUnits="userSpaceOnUse"> -<stop stop-color="#0B131C"/> -<stop offset="1" stop-color="#354039"/> -</linearGradient> -<clipPath id="clip0_1837_11068"> -<rect width="382" height="827" fill="white" transform="translate(24 20)"/> -</clipPath> -<image id="image0_1837_11068" width="15" height="15" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAABHNCSVQICAgIfAhkiAAAAUBJREFUKJGFks1S3TAMhT/JshPndl8ehIH3X8LQ9m1uAP+IhXMbAs1U2nhkHR0dSfLz7s45sTRNRItYtEP8slz48/sXegb8n90/PGJnnxoCACKCqo4O7Jh+Cr6ZM1SJCuEL+LTtoIFoEdm81kop70dms/iNxbtz87C1b2aEYOAOIiOmYSd3902vYmbkJRMtEmMkpUQpdVBseSZbFWBLKExpIsaIiCIiXC4/iDHy+rrSWuO9lAFeluUvuJRCnjPIkJBzZkoJVSGEwDxn1vW6a/7K/Pk9pYSZMc8ZC4E3d1R3mWZhH7/70KOq4OCAqtJ756011nXluq47eJrnw/i9d2qt4yB8FCy1YMEIQdGt0+7+/UhEFdUxqNYq12uh9T628EkinFzY7ZJqa4d4v61ShJfnJwTw+4fHf9U4tZfnJwA+AH+jc5A39zmDAAAAAElFTkSuQmCC"/> -<image id="image1_1837_11068" width="9" height="9" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAABHNCSVQICAgIfAhkiAAAAMRJREFUGJWF0LFKA1EQheH/3GxW4qIkogSCjUGstLDQKnUqKx9CH0vs8kYhxNJCElJkCSy6985YhDUoQqb+ivmP2lnm/HOWF6SDI5Rqwj4g+4sUiJcPpPELGoyQ1SjF36i+fcavn2D9hp9c4Wc3yCJZA+LgHoaPaPqKVlP88BRvd8DSFlle4P07WM+hWsJXCXIgIjfCz5OzCVQLyAu808Ptk1C+A47onXtTIbWw7gXEDWHzQajKbY+O+95UyCJYQm7Abr5vonZV760IjhkAAAAASUVORK5CYII="/> -<image id="image2_1837_11068" width="4" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAFCAYAAABirU3bAAAABHNCSVQICAgIfAhkiAAAAEVJREFUCJljlFHV+M+ABFjY2FkYUAXYWBg8XFwZPnz8yHDi9CkGRj1Lk/+srKwMf//+Zfj37x9EBQPDfwYWFiYGBgYmBgAtwhBN2erPwAAAAABJRU5ErkJggg=="/> -<image id="image3_1837_11068" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAABHNCSVQICAgIfAhkiAAAAGJJREFUCJk1wbEKglAAheH/yE0rp8A18A1samxpa+4BfNMew7EHEBPkgiBeT5PfJzWtNXT4XGES4fshMPewTCADK/JGRl7i04X368HzVgNGut7NGjkuPxxHUkooHArLG2B2f3kOIpEJnXBlAAAAAElFTkSuQmCC"/> -</defs> -</svg> diff --git a/client/src/assets/image/runningDog.svg b/client/src/assets/image/runningDog.svg deleted file mode 100644 index 60951e642..000000000 --- a/client/src/assets/image/runningDog.svg +++ /dev/null @@ -1,9 +0,0 @@ -<svg width="280" height="280" viewBox="0 0 280 280" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<rect x="0.5" y="0.5" width="280" height="280" fill="url(#pattern0_1905_4749)"/> -<defs> -<pattern id="pattern0_1905_4749" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image0_1905_4749" transform="scale(0.00124224 0.00124533)"/> -</pattern> -<image id="image0_1905_4749" width="805" height="803" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyUAAAMjCAYAAAC7zb+CAAABdWlDQ1BrQ0dDb2xvclNwYWNlRGlzcGxheVAzAAAokXWQvUvDUBTFT6tS0DqIDh0cMolD1NIKdnFoKxRFMFQFq1OafgltfCQpUnETVyn4H1jBWXCwiFRwcXAQRAcR3Zw6KbhoeN6XVNoi3sfl/Ticc7lcwBtQGSv2AijplpFMxKS11Lrke4OHnlOqZrKooiwK/v276/PR9d5PiFlNu3YQ2U9cl84ul3aeAlN//V3Vn8maGv3f1EGNGRbgkYmVbYsJ3iUeMWgp4qrgvMvHgtMunzuelWSc+JZY0gpqhrhJLKc79HwHl4plrbWD2N6f1VeXxRzqUcxhEyYYilBRgQQF4X/8044/ji1yV2BQLo8CLMpESRETssTz0KFhEjJxCEHqkLhz634PrfvJbW3vFZhtcM4v2tpCAzidoZPV29p4BBgaAG7qTDVUR+qh9uZywPsJMJgChu8os2HmwiF3e38M6Hvh/GMM8B0CdpXzryPO7RqFn4Er/QcXKWq8UwZBywAAAHhlWElmTU0AKgAAAAgABQEGAAMAAAABAAIAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAACEAAAAAQAAAIQAAAABAAKgAgAEAAAAAQAAAyWgAwAEAAAAAQAAAyMAAAAAdtVDCAAAAAlwSFlzAAAUTQAAFE0BlMqNLwAAA5JpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6SXB0YzR4bXBFeHQ9Imh0dHA6Ly9pcHRjLm9yZy9zdGQvSXB0YzR4bXBFeHQvMjAwOC0wMi0yOS8iPgogICAgICAgICA8ZGM6dGl0bGU+CiAgICAgICAgICAgIDxyZGY6QWx0PgogICAgICAgICAgICAgICA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPuygnOuqqSDsl4bripQg7JWE7Yq47JuM7YGsPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOkFsdD4KICAgICAgICAgPC9kYzp0aXRsZT4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+MTMyPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpYUmVzb2x1dGlvbj4xMzI8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlBob3RvbWV0cmljSW50ZXJwcmV0YXRpb24+MjwvdGlmZjpQaG90b21ldHJpY0ludGVycHJldGF0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8SXB0YzR4bXBFeHQ6QXJ0d29ya1RpdGxlPuygnOuqqSDsl4bripQg7JWE7Yq47JuM7YGsPC9JcHRjNHhtcEV4dDpBcnR3b3JrVGl0bGU+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgp+oXZ5AABAAElEQVR4AeydCZxkVXX/b3XPvg/MDMswMAv7LiIILoCKwAAa/SsajTFmMX+TaFxYTDR/559/4gK4RD+JidlMjInBuLIMKojIIiAIyDYsA7MzAwwzzL511//3fbdfT3VNVb1X1VXd1d2/AzVV/d599933fds595xzbwgWEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzABEzCBe99fHJ1SWLSo2JH+9rcJmIAJmIAJmEDrCBRaV7VrNgETMIHBI/DdPy7uP3ZCGL11WXj+km8Xuq75o+Kk8RPDQaOKYUZhVHg+7AwvzpkatjyiJs4MoXvnxjCz0BmmLtsclh55cChu3RxOGl0IS8ZMCoVN20Kh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gARIIFACVqXc1NQkazHjdBWUjI4eCt+GH4SvnDvTesdDHoqSAAmQAAmQQCAE6OgeCEYWQgIkQALhIjBnqn0FWjQDD3ldEc8+AWXDB8WS5ZYtf50w2/phuHrB1pAACZAACZQLgew/VOVCgP0kARIggRgS6FArd+6tkcOwWnImlI4B6GL7TN20LVlVVSmT60WWZbrOcyRAAiRAAiRQDAJcKSkGZdZBAiRAAiUi8MAUuze0kRFQPn6JJgzAukhX+I0IlJUGrKG8aFfKNyfdZH1UouaxWhIgARIgARIgARIgARIggXIiYE+3E8FN5kyxL1kwxR5VTn1nX0mABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABEiABCJEwIpQW9lUEiABEiABEiCBMibw8FR7WEWFtLOa5MaJs6zz50+1T7NtmdEocmOFJXcAzTic/1gRzZ1mHzxxpvVpGeNi10kgUgSolETqdrGxJEACJEACJBB/AvOm2k/ZImc4PcVgZTM+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+kOWXvnzItuhgR2u3zHLdCiXxSLtjAxBmY8h/RUd5eA6fj+D/DSPcRpfZ6xWPGKORYEfFLNtTsZonPz2Mrll/KeN1mVz2q6SloZHcg0yctxlxhsan4EESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAESIAEak/g/wPgRzBQnpl3FAAAAABJRU5ErkJggg=="/> -</defs> -</svg> diff --git a/client/src/assets/image/standingDog.svg b/client/src/assets/image/standingDog.svg deleted file mode 100644 index 2d34a8cf9..000000000 --- a/client/src/assets/image/standingDog.svg +++ /dev/null @@ -1,9 +0,0 @@ -<svg width="310" height="300" viewBox="0 0 310 300" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<rect width="310" height="300" fill="url(#pattern0_1905_4751)"/> -<defs> -<pattern id="pattern0_1905_4751" patternContentUnits="objectBoundingBox" width="1" height="1"> -<use xlink:href="#image0_1905_4751" transform="scale(0.00131926 0.0013369)"/> -</pattern> -<image id="image0_1905_4751" width="758" height="748" xlink:href="data:image/png;base64,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QAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk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PZ0ujIbprSq6UU55UMSkHkuvBXJKn82dTEtFEY9PsxAgQGDCAv4oTbgDnJ4AgXYKXF7O9xzO6cX4T/TZsgU5p414iqgn47azO2876vgk5+pUTl8P704r888X12/7QAUJECBwBwQk9ncA2SkIEOiXQNyguxBzrM/EvP2vIuF/qt76SAyHUynFj6UNAqON9MHjp4ufy1ivfZ6PPHyiWG9D3GIkQKCfAhL7fva7VhMgMGGB75by8cjuX9vMo1+mi8GDMRD4K+b0H55wWL08fXmj6zCnjxZOFVevLOcXHjtZXOwlhEYTINB6AYl967tQAwgQ6JrA5Y/zzPEzxY1vF/PcYJDe3Okm3pjU/Ucu0m+DnB7tmsE42xNGa/HJyZzvkR+nqroIEGiigMS+ib0iJgIECOxBYPVcfqicNvL9cj5x6K7005/r6ejCS8WXq+V396d0JW71LeqDgEh4r8eDpj6NewNOlZ8WlFeudxpElOFs3TA8iCcA5F2LlUW3llGRfoz6Hony//lbE/X8Hjcez1blqnXEcyNuQZ2pXpfrGLxsxu+vUc+xeHEuajpd7i9jTRvpbNzVcCgS9i/KlxYCBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAi0WOAfA/FQm5Hf5vcAAAAASUVORK5CYII="/> -</defs> -</svg> diff --git a/client/src/components/Design/components/Button/Button.tsx b/client/src/components/Design/components/Button/Button.tsx index 3b8896a1c..5ce12118e 100644 --- a/client/src/components/Design/components/Button/Button.tsx +++ b/client/src/components/Design/components/Button/Button.tsx @@ -1,11 +1,11 @@ /** @jsxImportSource @emotion/react */ import React, {forwardRef} from 'react'; -import Lottie from 'lottie-react'; -import loadingAnimation from '@assets/image/loadingAnimation.json'; import {useTheme} from '@theme/HDesignProvider'; +import Lottie from '../Lottie/Lottie'; + import {ButtonProps, ButtonSize} from './Button.type'; import {buttonStyle} from './Button.style'; @@ -34,11 +34,7 @@ export const Button: React.FC<ButtonProps> = forwardRef<HTMLButtonElement, Butto disabled={variants === 'loading' ? true : disabled} {...htmlProps} > - {variants === 'loading' ? ( - <Lottie animationData={loadingAnimation} loop={true} style={animationSize(size)} /> - ) : ( - children - )} + {variants === 'loading' ? <Lottie /> : children} </button> ); }); diff --git a/client/src/components/Design/components/FixedButton/FixedButton.tsx b/client/src/components/Design/components/FixedButton/FixedButton.tsx index 28192cd33..897cbbc64 100644 --- a/client/src/components/Design/components/FixedButton/FixedButton.tsx +++ b/client/src/components/Design/components/FixedButton/FixedButton.tsx @@ -1,8 +1,6 @@ /** @jsxImportSource @emotion/react */ import {forwardRef} from 'react'; -import Lottie from 'lottie-react'; -import loadingAnimation from '@assets/image/loadingAnimation.json'; import { fixedButtonContainerStyle, fixedButtonStyle, @@ -11,15 +9,22 @@ import { deleteButtonStyle, } from '@HDcomponents/FixedButton/FixedButton.style'; import {FixedButtonProps} from '@HDcomponents/FixedButton/FixedButton.type'; -import IconButton from '@HDcomponents/IconButton/IconButton'; -import Icon from '@HDcomponents/Icon/Icon'; import {useTheme} from '@theme/HDesignProvider'; +import Lottie from '../Lottie/Lottie'; + export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElement, FixedButtonProps>(function Button( {variants = 'primary', onDeleteClick, onBackClick, disabled, children, ...htmlProps}: FixedButtonProps, ref, ) { const {theme} = useTheme(); + + const imageStyle = { + width: '100%', + height: '100%', + objectFit: 'contain', // 이미지가 왜곡되지 않게 비율을 유지하며 버튼 크기에 맞춤 + }; + return ( <div css={fixedButtonContainerStyle(theme)}> <div css={buttonContainerStyle}> @@ -39,11 +44,7 @@ export const FixedButton: React.FC<FixedButtonProps> = forwardRef<HTMLButtonElem disabled={variants === 'loading' ? true : disabled} {...htmlProps} > - {variants === 'loading' ? ( - <Lottie animationData={loadingAnimation} loop={true} style={{height: '1.25rem'}} /> - ) : ( - children - )} + {variants === 'loading' ? <Lottie /> : children} </button> </div> </div> diff --git a/client/src/components/Design/components/Icon/Icon.tsx b/client/src/components/Design/components/Icon/Icon.tsx index d59a08bc4..fcedcdde7 100644 --- a/client/src/components/Design/components/Icon/Icon.tsx +++ b/client/src/components/Design/components/Icon/Icon.tsx @@ -14,7 +14,6 @@ import X from '@assets/image/x.svg'; import PencilMini from '@assets/image/pencil_mini.svg'; import Meatballs from '@assets/image/meatballs.svg'; import EditPencil from '@assets/image/editPencil.svg'; -import Heundeut from '@assets/image/heundeut.svg'; import {IconProps} from '@HDcomponents/Icon/Icon.type'; import {useTheme} from '@theme/HDesignProvider'; @@ -35,7 +34,7 @@ const ICON = { toss: <img src={Toss} width="16" height="16" alt="toss icon" />, meatballs: <Meatballs />, editPencil: <EditPencil />, - heundeut: <Heundeut />, + heundeut: <img src={`${process.env.IMAGE_URL}/heundeut.svg`} />, }; export const Icon: React.FC<IconProps> = ({iconColor, iconType, ...htmlProps}: IconProps) => { diff --git a/client/src/components/Design/components/Lottie/Lottie.style.ts b/client/src/components/Design/components/Lottie/Lottie.style.ts new file mode 100644 index 000000000..ac4232637 --- /dev/null +++ b/client/src/components/Design/components/Lottie/Lottie.style.ts @@ -0,0 +1,66 @@ +import {css, keyframes} from '@emotion/react'; + +const movingFrames = keyframes` + 0% { transform: translate(4px, 50%) scale(0); } + 25% { transform: translate(4px, 50%) scale(0); } + 50% { transform: translate(4px, 50%) scale(1); } + 75% { transform: translate(16px, 50%) scale(1); } + 100% { transform: translate(28px, 50%) scale(1); } +`; + +const disappearFrames = keyframes` + 0% { transform: translate(28px, 50%) scale(1); } + 100% { transform: translate(28px, 50%) scale(0); } +`; + +export const lottieStyle = (frameColors: string[]) => + css({ + width: '100%', + height: '100%', + position: 'relative', + transform: 'translateZ(0) scale(1)', + backfaceVisibility: 'hidden', + transformOrigin: '0 0', + + div: { + position: 'absolute', + width: '8px', + height: '8px', + borderRadius: '50%', + transform: 'translate(16px, 50%) scale(1)', + background: frameColors[3], + animation: `${movingFrames} 1s infinite cubic-bezier(0, 0.5, 0.5, 1)`, + boxSizing: 'content-box', + + '&:nth-of-type(1)': { + background: frameColors[2], + transform: 'translate(28px, 50%) scale(1)', + animation: `${disappearFrames} 0.25s infinite cubic-bezier(0, 0.5, 0.5, 1)`, + }, + '&:nth-of-type(2)': { + animationDelay: '-0.25s', + background: frameColors[3], + }, + '&:nth-of-type(3)': { + animationDelay: '-0.5s', + background: frameColors[2], + }, + '&:nth-of-type(4)': { + animationDelay: '-0.75s', + background: frameColors[1], + }, + '&:nth-of-type(5)': { + animationDelay: '-1s', + background: frameColors[0], + }, + }, + }); + +export const lottieContainerStyle = () => + css({ + width: '40px', + height: '20px', + display: 'inline-block', + overflow: 'hidden', + background: 'none', + }); diff --git a/client/src/components/Design/components/Lottie/Lottie.tsx b/client/src/components/Design/components/Lottie/Lottie.tsx new file mode 100644 index 000000000..2152539e1 --- /dev/null +++ b/client/src/components/Design/components/Lottie/Lottie.tsx @@ -0,0 +1,23 @@ +/** @jsxImportSource @emotion/react */ + +import {PRIMARY_COLORS} from '@components/Design/token/colors'; + +import {lottieContainerStyle, lottieStyle} from './Lottie.style'; + +const Lottie = () => { + const frameColors = [PRIMARY_COLORS[100], PRIMARY_COLORS[200], PRIMARY_COLORS[300], PRIMARY_COLORS[400]]; + + return ( + <div css={lottieContainerStyle}> + <div css={lottieStyle(frameColors)}> + <div></div> + <div></div> + <div></div> + <div></div> + <div></div> + </div> + </div> + ); +}; + +export default Lottie; diff --git a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx index bc8d499df..97d8b090d 100644 --- a/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx +++ b/client/src/components/Design/components/NumberKeyboard/NumberKeyboard.tsx @@ -1,7 +1,9 @@ /** @jsxImportSource @emotion/react */ import {css} from '@emotion/react'; -import {Button, useTheme} from '@components/Design'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + +import {Button} from '@components/Design'; import {Keypad} from './Keypad'; import useNumberKeyboard from './useNumberKeyboard'; diff --git a/client/src/components/Design/components/Text/Text.tsx b/client/src/components/Design/components/Text/Text.tsx index e8b28c19e..24468beca 100644 --- a/client/src/components/Design/components/Text/Text.tsx +++ b/client/src/components/Design/components/Text/Text.tsx @@ -11,7 +11,7 @@ const Text: React.FC<TextProps> = ({size = 'body', textColor = 'black', children const {theme} = useTheme(); return ( <p css={getSizeStyling({size, textColor, theme})} {...attributes}> - {children} + {children === '' ? '\u00A0' : children} </p> ); }; diff --git a/client/src/components/Design/index.tsx b/client/src/components/Design/index.tsx index aaada3e57..756f63b65 100644 --- a/client/src/components/Design/index.tsx +++ b/client/src/components/Design/index.tsx @@ -1,6 +1,5 @@ import {MainLayout} from './layouts/MainLayout'; import FunnelLayout from './layouts/FunnelLayout'; -import {ContentLayout} from './layouts/ContentLayout'; import {HDesignProvider, useTheme} from './theme/HDesignProvider'; import BankSelect from './components/BankSelect/BankSelect'; import BottomSheet from './components/BottomSheet/BottomSheet'; @@ -29,6 +28,9 @@ import Dropdown from './components/Dropdown/Dropdown'; import DropdownButton from './components/Dropdown/DropdownButton'; export { + HDesignProvider, + MainLayout, + FunnelLayout, BankSelect, BottomSheet, Button, @@ -49,14 +51,10 @@ export { TextButton, Title, TopNav, - MainLayout, - FunnelLayout, - ContentLayout, - HDesignProvider, - useTheme, DepositCheck, DepositToggle, Amount, Dropdown, DropdownButton, + useTheme, }; diff --git a/client/src/components/Design/token/colors.ts b/client/src/components/Design/token/colors.ts index 3dccdf2d3..38eea4de7 100644 --- a/client/src/components/Design/token/colors.ts +++ b/client/src/components/Design/token/colors.ts @@ -107,3 +107,5 @@ export const COLORS: ColorTokens = { warn: PRIMITIVE_COLORS.yellow[400], complete: PRIMITIVE_COLORS.green[300], }; + +export const PRIMARY_COLORS = PRIMITIVE_COLORS.purple; diff --git a/client/src/components/Logo/RunningDogLogo.tsx b/client/src/components/Logo/RunningDogLogo.tsx index a09a904c1..602ef24dc 100644 --- a/client/src/components/Logo/RunningDogLogo.tsx +++ b/client/src/components/Logo/RunningDogLogo.tsx @@ -1,11 +1,9 @@ -import RunningDog from '@assets/image/runningDog.svg'; - import {logoStyle} from './Logo.style'; const RunningDogLogo = () => { return ( <div css={logoStyle}> - <RunningDog /> + <img src={`${process.env.IMAGE_URL}/runningDog.svg`} /> </div> ); }; diff --git a/client/src/components/Logo/StandingDogLogo.tsx b/client/src/components/Logo/StandingDogLogo.tsx index 5c2cf591e..1cfd54029 100644 --- a/client/src/components/Logo/StandingDogLogo.tsx +++ b/client/src/components/Logo/StandingDogLogo.tsx @@ -1,11 +1,9 @@ -import StandingDog from '@assets/image/standingDog.svg'; - import {logoStyle} from './Logo.style'; const StandingDogLogo = () => { return ( <div css={logoStyle}> - <StandingDog /> + <img src={`${process.env.IMAGE_URL}/standingDog.svg`} /> </div> ); }; diff --git a/client/src/components/Toast/Toast.tsx b/client/src/components/Toast/Toast.tsx index cbc6824f4..1de3672d2 100644 --- a/client/src/components/Toast/Toast.tsx +++ b/client/src/components/Toast/Toast.tsx @@ -1,7 +1,8 @@ import {createPortal} from 'react-dom'; import {useState, useEffect} from 'react'; -import {useTheme} from '@HDesign/index'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; + import {Button, Flex, Icon, Text} from '@HDesign/index'; import {toastStyle, textStyle, toastMarginStyle} from './Toast.style'; diff --git a/client/src/global.d.ts b/client/src/global.d.ts index 63226360f..109234ddc 100644 --- a/client/src/global.d.ts +++ b/client/src/global.d.ts @@ -9,5 +9,6 @@ declare namespace NodeJS { readonly API_BASE_URL: string; readonly AMPLITUDE_KEY: string; readonly KAKAO_JAVASCRIPT_KEY: string; + readonly IMAGE_URL: string; } } diff --git a/client/src/mocks/handlers/eventHandlers.ts b/client/src/mocks/handlers/eventHandlers.ts index 1b06c5f9d..135be564c 100644 --- a/client/src/mocks/handlers/eventHandlers.ts +++ b/client/src/mocks/handlers/eventHandlers.ts @@ -4,6 +4,8 @@ import {http, HttpResponse} from 'msw'; import {ADMIN_API_PREFIX, USER_API_PREFIX} from '@apis/endpointPrefix'; +import RULE from '@constants/rule'; + import {VALID_EVENT_NAME_LENGTH_IN_SERVER} from '@mocks/serverConstants'; import {MOCK_API_PREFIX} from '@mocks/mockEndpointPrefix'; import {eventData} from '@mocks/sharedState'; @@ -20,7 +22,7 @@ export const eventHandler = [ return HttpResponse.json( { errorCode: 'EVENT_NAME_LENGTH_INVALID', - message: '행사 이름은 2자 이상 30자 이하만 입력 가능합니다.', + message: `행사 이름은 2자 이상 ${RULE.maxEventNameLength}자 이하만 입력 가능합니다.`, }, {status: 400}, ); @@ -30,7 +32,7 @@ export const eventHandler = [ return HttpResponse.json( { errorCode: 'EVENT_PASSWORD_FORMAT_INVALID', - message: '비밀번호는 4자리 숫자만 가능합니다.', + message: `비밀번호는 ${RULE.maxEventPasswordLength}자리 숫자만 가능합니다.`, }, {status: 400}, ); diff --git a/client/src/pages/EventPage/AdminPage/EventMember.tsx b/client/src/pages/EventPage/AdminPage/EventMember.tsx index cdeaa8d40..cfd790837 100644 --- a/client/src/pages/EventPage/AdminPage/EventMember.tsx +++ b/client/src/pages/EventPage/AdminPage/EventMember.tsx @@ -1,10 +1,10 @@ /** @jsxImportSource @emotion/react */ import {Report} from 'types/serviceType'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; import useEventMember from '@hooks/useEventMember'; import {MainLayout, TopNav, Top, Amount, DepositToggle, Icon, IconButton, FixedButton, Text} from '@components/Design'; -import {useTheme} from '@components/Design'; import {eventMemberStyle, memberList, eventMember, memberEditInput, noneReports} from './EventMember.style'; diff --git a/client/src/pages/MainPage/MainPage.tsx b/client/src/pages/MainPage/MainPage.tsx index 50cae98b8..702972eff 100644 --- a/client/src/pages/MainPage/MainPage.tsx +++ b/client/src/pages/MainPage/MainPage.tsx @@ -1,4 +1,4 @@ -import {Flex, MainLayout} from '@HDesign/index'; +import {MainLayout} from '@HDesign/index'; import Nav from './Nav/Nav'; import MainSection from './Section/MainSection'; diff --git a/client/src/pages/MainPage/Nav/Nav.tsx b/client/src/pages/MainPage/Nav/Nav.tsx index 2ca0cfb4d..65c7399db 100644 --- a/client/src/pages/MainPage/Nav/Nav.tsx +++ b/client/src/pages/MainPage/Nav/Nav.tsx @@ -1,6 +1,6 @@ import {useNavigate} from 'react-router-dom'; -import {useTheme} from '@theme/HDesignProvider'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; import {Button, Flex, Text, Icon, TopNav, IconButton} from '@HDesign/index'; diff --git a/client/src/pages/MainPage/Section/AddBillSection.tsx b/client/src/pages/MainPage/Section/AddBillSection.tsx index ca2fe1f34..e20145c45 100644 --- a/client/src/pages/MainPage/Section/AddBillSection.tsx +++ b/client/src/pages/MainPage/Section/AddBillSection.tsx @@ -1,8 +1,6 @@ import {css} from '@emotion/react'; -import AddBillMockup from '@assets/image/addBillMockup.svg'; - -import {Text} from '@HDesign/index'; +import Text from '@components/Design/components/Text/Text'; const AddBillSection = () => { return ( @@ -24,7 +22,7 @@ const AddBillSection = () => { 실시간으로 기록해 놓을 수 있어요`} </Text> </div> - <AddBillMockup /> + <img src={`${process.env.IMAGE_URL}/addBillMockup.svg`} /> </div> ); }; diff --git a/client/src/pages/MainPage/Section/AddMemberSection.tsx b/client/src/pages/MainPage/Section/AddMemberSection.tsx index a7ff92539..9207ec6ea 100644 --- a/client/src/pages/MainPage/Section/AddMemberSection.tsx +++ b/client/src/pages/MainPage/Section/AddMemberSection.tsx @@ -1,9 +1,7 @@ import {css} from '@emotion/react'; -import AddMemberMockup from '@assets/image/addMemberMockup.svg'; - -import {Text} from '@HDesign/index'; -import {useTheme} from '@HDesign/index'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; +import Text from '@HDesign/components/Text/Text'; const AddMemberSection = () => { const {theme} = useTheme(); @@ -26,7 +24,7 @@ const AddMemberSection = () => { 행동대장이 알아서 차수를 나눠줘요`} </Text> </div> - <AddMemberMockup /> + <img src={`${process.env.IMAGE_URL}/addMemberMockup.svg`} /> </div> ); }; diff --git a/client/src/pages/MainPage/Section/DescriptionSection.tsx b/client/src/pages/MainPage/Section/DescriptionSection.tsx index f53e88cf9..ffd319467 100644 --- a/client/src/pages/MainPage/Section/DescriptionSection.tsx +++ b/client/src/pages/MainPage/Section/DescriptionSection.tsx @@ -1,6 +1,7 @@ import {css} from '@emotion/react'; -import {Text, useTheme} from '@HDesign/index'; +import {useTheme} from '@components/Design/theme/HDesignProvider'; +import Text from '@HDesign/components/Text/Text'; const DescriptionSection = () => { const {theme} = useTheme(); diff --git a/client/src/pages/MainPage/Section/MainSection.tsx b/client/src/pages/MainPage/Section/MainSection.tsx index 3be031978..1f7b8367f 100644 --- a/client/src/pages/MainPage/Section/MainSection.tsx +++ b/client/src/pages/MainPage/Section/MainSection.tsx @@ -2,10 +2,8 @@ import {css, keyframes} from '@emotion/react'; import {useNavigate} from 'react-router-dom'; import ChevronDown from '@assets/image/chevronDownLarge.svg'; - -import {StandingDog} from '@components/Logo'; - -import {Button, Text} from '@HDesign/index'; +import Button from '@HDesign/components/Button/Button'; +import Text from '@HDesign/components/Text/Text'; import {ROUTER_URLS} from '@constants/routerUrls'; @@ -36,7 +34,7 @@ const MainSection = () => { })} > <div css={animateWithDelay(0)}> - <StandingDog /> + <img src={`${process.env.IMAGE_URL}/standingDog.svg`} /> </div> <Text css={animateWithDelay(1)} style={{textAlign: 'center'}} size="title">{`행동대장을 통해 간편하게 정산하세요 diff --git a/client/src/pages/MainPage/Section/ReportSection.tsx b/client/src/pages/MainPage/Section/ReportSection.tsx index 452365ea2..cbf150b96 100644 --- a/client/src/pages/MainPage/Section/ReportSection.tsx +++ b/client/src/pages/MainPage/Section/ReportSection.tsx @@ -1,8 +1,6 @@ import {css} from '@emotion/react'; -import MemberReportMockup from '@assets/image/memberReportMockup.svg'; - -import {Text} from '@HDesign/index'; +import Text from '@components/Design/components/Text/Text'; const ReportSection = () => { return ( @@ -24,7 +22,7 @@ const ReportSection = () => { 금액은 자동으로 계산돼요`} </Text> </div> - <MemberReportMockup /> + <img src={`${process.env.IMAGE_URL}/memberReportMockup.svg`} /> </div> ); }; diff --git a/client/src/router.tsx b/client/src/router.tsx index 735b09786..f78874f65 100644 --- a/client/src/router.tsx +++ b/client/src/router.tsx @@ -1,26 +1,32 @@ import {createBrowserRouter} from 'react-router-dom'; +import {lazy, Suspense} from 'react'; -import {AdminPage} from '@pages/EventPage/AdminPage'; -import {HomePage} from '@pages/EventPage/HomePage'; import ErrorPage from '@pages/ErrorPage/ErrorPage'; import EventLoginPage from '@pages/EventPage/AdminPage/EventLoginPage'; -import AddBillFunnel from '@pages/AddBillFunnel/AddBillFunnel'; -import CreateEventFunnel from '@pages/CreateEventPage/CreateEventFunnel'; -import EventMember from '@pages/EventPage/AdminPage/EventMember'; -import EditBillPage from '@pages/EditBillPage/EditBillPage'; -import Account from '@pages/AccountPage/Account'; -import {MainPage} from '@pages/MainPage'; import {EventPage} from '@pages/EventPage'; import {ROUTER_URLS} from '@constants/routerUrls'; import App from './App'; +const MainPage = lazy(() => import('@pages/MainPage/MainPage')); +const HomePage = lazy(() => import('@pages/EventPage/HomePage/HomePage')); +const CreateEventFunnel = lazy(() => import('@pages/CreateEventPage/CreateEventFunnel')); +const AdminPage = lazy(() => import('@pages/EventPage/AdminPage/AdminPage')); +const AddBillFunnel = lazy(() => import('@pages/AddBillFunnel/AddBillFunnel')); +const EventMember = lazy(() => import('@pages/EventPage/AdminPage/EventMember')); +const EditBillPage = lazy(() => import('@pages/EditBillPage/EditBillPage')); +const Account = lazy(() => import('@pages/AccountPage/Account')); + const router = createBrowserRouter([ { path: '', - element: <App />, + element: ( + <Suspense> + <App /> + </Suspense> + ), children: [ { index: true, diff --git a/client/webpack.common.mjs b/client/webpack.common.mjs index 90879f2f9..653456280 100644 --- a/client/webpack.common.mjs +++ b/client/webpack.common.mjs @@ -47,7 +47,7 @@ export default { ], }, { - test: /\.png$/i, + test: /\.(png|webp)$/, loader: 'file-loader', }, ], diff --git a/client/webpack.dev.mjs b/client/webpack.dev.mjs index 5ad42ed45..5765a8c8f 100644 --- a/client/webpack.dev.mjs +++ b/client/webpack.dev.mjs @@ -3,6 +3,7 @@ import {merge} from 'webpack-merge'; import Dotenv from 'dotenv-webpack'; import common from './webpack.common.mjs'; import {fileURLToPath} from 'url'; +import TerserPlugin from 'terser-webpack-plugin'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); @@ -30,4 +31,25 @@ export default merge(common, { path: '.env.dev', }), ], + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + terserOptions: { + compress: { + // 가능한 모든 코드를 압축 + drop_console: true, // 콘솔 로그를 제거하여 파일 크기 감소 + drop_debugger: true, // 디버거 코드 제거 + pure_funcs: ['console.info'], // 특정 함수 호출 제거 + }, + mangle: true, // 변수 및 함수 이름을 짧게 변경 + output: { + comments: false, // 주석을 제거 + }, + }, + extractComments: false, // 별도의 파일로 주석을 추출하지 않음 + parallel: true, // 멀티 프로세스를 사용하여 빌드 속도 향상 + }), + ], + }, }); From a8db3a53980e7049c5b93389127128615408d87d Mon Sep 17 00:00:00 2001 From: JinHo Kim <81083461+jinhokim98@users.noreply.github.com> Date: Fri, 27 Sep 2024 01:14:01 +0900 Subject: [PATCH 271/273] =?UTF-8?q?fix:=20=EC=86=A1=EA=B8=88=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EB=90=90=EC=9D=84=20=EB=95=8C=20=ED=86=A0=EC=8A=A4?= =?UTF-8?q?=20=EB=B2=84=ED=8A=BC=20=EA=B0=80=EB=A6=AC=EA=B8=B0=20(#676)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Design/components/ExpenseList/ExpenseList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx index f34cc1aaf..4741780a3 100644 --- a/client/src/components/Design/components/ExpenseList/ExpenseList.tsx +++ b/client/src/components/Design/components/ExpenseList/ExpenseList.tsx @@ -42,7 +42,7 @@ function ExpenseItem({ <BankSendButton clipboardText={clipboardText} onBankButtonClick={onBankButtonClick} - isDeposited={price <= 0} + isDeposited={price <= 0 || isDeposited} /> ) : ( <IconButton variants="none" size="small"> From 06553ff8dc090e6f7212d9967401e33d060e6315 Mon Sep 17 00:00:00 2001 From: TaehunLee <85233397+Todari@users.noreply.github.com> Date: Fri, 27 Sep 2024 01:14:31 +0900 Subject: [PATCH 272/273] =?UTF-8?q?fix:=20=EC=A7=80=EC=B6=9C=20=EB=82=B4?= =?UTF-8?q?=EC=97=AD=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EB=82=98=EA=B0=94?= =?UTF-8?q?=EB=8B=A4=20=EB=93=A4=EC=96=B4=EC=98=A8=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=A0=20=EC=88=98=20=EC=97=86=EB=8A=94=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20(#677)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/hooks/useMembersStep.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/hooks/useMembersStep.ts b/client/src/hooks/useMembersStep.ts index b7183124d..dba0aeacd 100644 --- a/client/src/hooks/useMembersStep.ts +++ b/client/src/hooks/useMembersStep.ts @@ -12,6 +12,7 @@ import REGEXP from '@constants/regExp'; import useRequestPostMembers from './queries/member/useRequestPostMembers'; import useRequestPostBill from './queries/bill/useRequestPostBill'; import {BillStep} from './useAddBillFunnel'; +import useRequestGetAllMembers from './queries/member/useRequestGetAllMembers'; interface Props { billInfo: BillInfo; @@ -26,6 +27,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) const inputRef = useRef<HTMLInputElement>(null); const hiddenRef = useRef<HTMLInputElement>(null); + const {members: allMembers} = useRequestGetAllMembers(); const {postMembersAsync, isPending: isPendingPostMembers} = useRequestPostMembers(); const {postBill, isSuccess: isSuccessPostBill, isPending: isPendingPostBill} = useRequestPostBill(); @@ -53,7 +55,7 @@ const useMembersStep = ({billInfo, setBillInfo, currentMembers, setStep}: Props) const canSubmitMembers = billInfo.members.length !== 0; const setBillInfoMemberWithId = (name: string) => { - const existingMember = currentMembers.find(currentMember => currentMember.name === name); + const existingMember = allMembers.find(currentMember => currentMember.name === name); if (existingMember) { setBillInfo(prev => ({...prev, members: [...prev.members, {id: existingMember.id, name: name}]})); } else { From a26f043752926152df2c6c84fd395fd7ea1fffe8 Mon Sep 17 00:00:00 2001 From: Pakxe <64801796+pakxe@users.noreply.github.com> Date: Fri, 27 Sep 2024 01:15:24 +0900 Subject: [PATCH 273/273] =?UTF-8?q?fix:=20=EB=B9=A0=EC=A7=84=20=EC=84=9C?= =?UTF-8?q?=EB=B2=84=20=EC=97=90=EB=9F=AC=20=EC=BD=94=EB=93=9C=EC=9D=B8=20?= =?UTF-8?q?PASSWORD=5FINVALID=20=EC=B6=94=EA=B0=80=20(#679)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/constants/errorMessage.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/constants/errorMessage.ts b/client/src/constants/errorMessage.ts index 113b7c7e1..d775d25b4 100644 --- a/client/src/constants/errorMessage.ts +++ b/client/src/constants/errorMessage.ts @@ -36,6 +36,7 @@ export const SERVER_ERROR_MESSAGES: ErrorMessage = { TOKEN_EXPIRED: '로그인이 만료되었어요. 다시 로그인해주세요.', TOKEN_INVALID: '비밀번호를 올바르게 입력해주세요.', FORBIDDEN: '접근할 수 없는 행사에요.', + PASSWORD_INVALID: '비밀번호를 올바르게 입력해주세요.', // 사용자에게 뜨면 안되며 프론트 구현 미스인 에러 코드 MESSAGE_NOT_READABLE: '읽을 수 없는 요청이에요.',

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 z